How it works
A reference for debugging and extending. You do not need this page to use the package.
Which file does what
| Piece | File | Role |
|---|---|---|
| Blade component | resources/views/components/editor.blade.php, src/View/Components/Editor.php | Wraps <flux:editor>, renders the toolbar preset, the JSON config and the drag and drop data attributes |
| Toolbar buttons | resources/views/flux/editor/image.blade.php, file-link.blade.php, checklist.blade.php | <flux:editor.button> elements with a data-editor or data-filemanager-checklist attribute |
| JavaScript | resources/js/laravel-filemanager.js | Button handling, the popup, the resize menu, the modals and the drop and paste plugin |
| Drag and drop helpers | resources/js/drag-drop-config.js | Reads the data attributes, validates a file, converts to base64 or uploads |
| Setup block | resources/stubs/flux-filemanager-setup.js, examples/app.js | Registers the Image and Link extensions on the flux:editor event |
| Styles | resources/css/tiptap-image.css, file-link-modal.css | Images in the editor, the resize menu, the modals |
| Config reader | src/Support/FluxFilemanagerConfig.php | The only class that reads config/flux-filemanager.php, with one method per key |
| Installer | src/Console/InstallCommand.php | flux-filemanager:install: Laravel Filemanager config and routes, storage, npm, config, app.js |
| Installation check | src/Console/CheckCommand.php, src/Support/InstallationCheck.php | flux-filemanager:check and the checklist page read the same list of nine checks |
| Demo | routes/web.php, src/Livewire/EditorDemo.php, resources/views/examples/ | Opt-in demo and checklist pages |
The DOM contract: which clicks the JavaScript listens to
Everything is event delegation on document: one listener on the page instead of one per button. That is why it works for editors that Livewire renders later:
- A click on an element with
data-editor="image"ordata-editor="file-link"finds the closestui-editorelement. Flux puts the TipTap instance on it aseditor. Without that property the click is ignored. - A click on
.ProseMirror imgshows the resize menu, a double click opens the image modal. - A click on
.ProseMirror aopens the link modal in edit mode, withpreventDefault()so the link doesn’t navigate. - A click on
[data-filemanager-checklist]opens the checklist URL in a new tab.
Settings come from a <script type="application/json" data-flux-filemanager-config> tag the component renders once per page, or from window.fluxFilemanagerConfig if the host app sets it first. The JSON holds the file manager URL, the popup size, the resize presets, the custom width limits, the two messages and the translations. The drag and drop settings are data attributes on the ui-editor element, because the plugin reads them per editor.
How the Laravel Filemanager popup hands back a file
The package calls window.open() with ?type=Images or ?type=Files. Laravel Filemanager calls window.SetUrl(items) in the opener when the user confirms. The package defines that function right after opening the popup, reads url (or path, or thumb_url) from each item, removes the function again and closes the popup.
A URL on another origin than the page is made relative when its path starts with /storage/, /filemanager, /laravel-filemanager, /cms/filemanager or /cms/laravel-filemanager. That keeps images working when APP_URL does not match the host in use. Every other URL is stored as an absolute URL.
Images are inserted with the setImage command, with a fallback to raw HTML and then to a link if the extension refuses. Files open the link modal.
How images and links are changed
The resize menu and the modal call updateAttributes('image', ...) on the selected node, so attributes they don’t touch stay. The generated part of class and style is recomputed every time: tiptap-image, align-*, width, the alignment margins and display: block for center. Anything else in those attributes is treated as the editor’s own and kept.
Editing a link extends the selection to the whole link mark and replaces it with new text carrying a new link mark, so text and attributes change together.
After a change through commands, the package dispatches input and blur on the ui-editor element, because Flux syncs wire:model on those events.
The two TipTap extensions in the setup block
The setup block registers two extensions on every editor through Flux’s flux:editor event and e.detail.registerExtension():
- Image: TipTap’s Image extension, extended with
class,styleanddata-alignattributes and the drop and paste plugin.addNodeView()returns null andresizeis off, because Flux’s editor already renders images with its own node view; a second one breaks selection.inline: trueso an image can sit in a paragraph,allowBase64: truefor dropped images. - Link: TipTap’s Link extension with
target,classandstyleattributes,openOnClick: falseso clicks open the modal instead of navigating, andrel="noopener noreferrer nofollow".
A flag on e.detail stops the block from registering twice when the event fires more than once.
How drop and paste are handled
createImageDropPastePlugin() is a ProseMirror plugin with handleDrop and handlePaste. It takes over only when the event carries image files and the editor belongs to a ui-editor; everything else goes to the editor’s defaults. Files are processed one at a time through processImageFile(): size and type check, then base64 or an upload, then insertContentAt() at the drop position or the cursor. A file that fails the size or type check, or an upload that returns an error status, shows an alert and the rest continue. An upload that returns no URL is skipped without a message.