Filament Tiptap Editor

repository·3.x·Indexed 19 days ago

https://github.com/awcodes/filament-tiptap-editor

A Tiptap-based rich text editor integration for Filament Admin and Forms. It features custom tool profiles, media management, and support for HTML, JSON, and Text output formats. Key capabilities include custom blocks, merge tags, static and dynamic mentions, and a tiptap_converter() helper for Blade rendering. Note: This package is deprecated as of Filament v4, where the native Filament Rich Editor is recommended.

Tokens
10.2K
Snippets
40
Records
43
Agent score
64%

What's inside filament-tiptap-editor

  1. Set Tiptap Output Format

    3.x

    Tiptap supports three output formats: HTML, JSON, and Text. You can set the default globally in the config or per-instance using ->output().

    Important: If storing as JSON, ensure your database column is longText or json and that your model casts the attribute to json or array.

    use FilamentTiptapEditor\Enums\TiptapOutput;
    
    TiptapEditor::make('content')
        ->output(TiptapOutput::Json);
  2. Use Merge Tags with JSON content

    3.x

    Merge tags allow you to replace placeholders (like {{ first_name }}) with dynamic content in JSON-based editor content.

    1. Define Tags: Use mergeTags([...]) on the editor instance.
    2. User Interaction: Users can type {{ to trigger autocomplete or drag tags from the blocks panel.
    3. Hide from Panel: Use showMergeTagsInBlocksPanel(false) to remove them from the drag-and-drop UI.
    4. Rendering: Use the tiptap_converter helper in Blade to replace tags with actual data during output.
    // Define tags
    TiptapEditor::make('content')->mergeTags(['first_name', 'last_name'])
    
    // Render tags in Blade
    {!! tiptap_converter()->mergeTagsMap(['first_name' => 'John', 'last_name' => 'Doe'])->asHTML($content) !!}
  3. Create a toolbar button for extensions

    3.x

    Custom extensions require a dedicated Blade view for their toolbar button. Place this in your resources/views/components directory. It is recommended to use the <x-filament-tiptap-editor::button> component for consistency. The action attribute should call the appropriate Tiptap command (e.g., editor().commands.toggleYourExtension()).

    <x-filament-tiptap-editor::button
        label="Hero"
        active="hero"
        action="editor().commands.toggleHero()"
    >
        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M5 21q-.825 0-1.413-.588T3 19V5q0-.825.588-1.413T5 3h14q.825 1.413.588T21 5v14q0 .825-.588 1.413T19 21H5Zm0-2h14v-5H5v5Z"/></svg>
        
        <span class="sr-only">{{ $label }}</span>
    </x-filament-tiptap-editor::button>
  4. Create custom blocks for Tiptap Editor

    3.x

    To use custom blocks, you must store your content as JSON. A custom block requires three components:

    1. A Block Class: Extends TiptapBlock. It defines the settings (via getFormSchema), the preview view, and the rendered view.
    2. A Preview Blade File: A standard Blade view used for the editor's UI. Note: You cannot use Livewire components here because the editor uses wire:ignore.
    3. A Rendered Blade File: A standard Blade view used for the final output. You can use Livewire components here to output data.

    Block Class Options

    • Settings: Implement getFormSchema(): array to show a modal for configuring the block.
    • Static Blocks: If you omit getFormSchema(), the block is inserted directly without a modal.
    • UI Customization:
      • $width: Set modal width (e.g., 'xl').
      • $slideOver: Set to true to use a slide-over instead of a modal.
      • $icon: Set an icon (e.g., 'heroicon-o-film') to show in the drag-and-drop panel.
    use FilamentTiptapEditor\TiptapBlock;
    
    class BatmanBlock extends TiptapBlock
    {
        public string $preview = 'blocks.previews.batman';
        public string $rendered = 'blocks.rendered.batman';
    
        public function getFormSchema(): array
        {
            return [
                TextInput::make('name'),
                TextInput::make('color'),
                Select::make('side')
                    ->options(['Hero' => 'Hero', 'Villain' => 'Villain'])
                    ->default('Hero')
            ];
        }
    }
  5. Register custom blocks with the editor

    3.x

    To make your custom blocks available, register them in a Service Provider using TiptapEditor::configureUsing. You must also ensure the 'blocks' key is added to your profiles in the Tiptap configuration.

    You can also use collapseBlocksPanel() globally via configureUsing to change the default state of the drag-and-drop panel.

    use App\TiptapBlocks\BatmanBlock;
    use App\TiptapBlocks\StaticBlock;
    use FilamentTiptapEditor\TiptapEditor;
    
    TiptapEditor::configureUsing(function (TiptapEditor $component) {
        $component
            ->collapseBlocksPanel()
            ->blocks([
                BatmanBlock::class,
                StaticBlock::class,
            ]);
    });
  6. Render Tiptap Content in Blade Files

    3.x

    If storing content as JSON, use the tiptap_converter() helper to transform it for display in Blade templates.

    Basic Conversion

    • asHTML(): Converts to HTML.
    • asJSON(): Converts to JSON.
    • asText(): Converts to plain text.

    Table of Contents (TOC)

    If using the heading tool, you can generate a TOC:

    • Inline HTML: Use asHTML() with toc: true and an optional maxDepth.
    • Dedicated Method: Use asToc() to get the TOC content.
    • Blade Component: Use the <x-filament-tiptap-editor::table-of-contents /> component.
    <!-- Convert to HTML -->
    {!! tiptap_converter()->asHTML($post->content) !!}
    
    <!-- Generate TOC with max depth of 3 -->
    {!! tiptap_converter()->asHTML($post->content, toc: true, maxDepth: 3) !!}
    
    <!-- Using the Blade component for a nested array TOC -->
    <x-filament-tiptap-editor::table-of-contents :headings="tiptap_converter()->asTOC($page->body, array: true)" />
  7. Configure Vite for custom extensions

    3.x

    To ensure your custom JS and CSS files are compiled, add them to the input array in your vite.config.js file.

    export default defineConfig({
        plugins: [
            laravel({
                input: [
                    ...
                    'resources/js/tiptap/extensions.js',
                    'resources/css/tiptap/extensions.css',
                ],
                refresh: true,
            }),
        ],
    });
  8. Use Tiptap Editor in Standalone Forms

    3.x

    If you are using the editor within a custom Livewire form (outside of standard Filament resources) and need to use tools that require modals (like Media or Video insertion), you must manually include the modal container in your Blade view after the form.

    <form wire:submit.prevent="submit">
        {{ $this->form }}
        <button type="submit">Save</button>
    </form>
    
    {{ $this->modal }}
  9. Create custom CSS for extensions

    3.x

    Custom styles for extensions should be placed in resources/css/tiptap/extensions.css. To ensure styles are applied correctly to the editor content, all CSS rules must be scoped to the .tiptap-content parent class.

    /* resources/css/tiptap/extensions.css */
    .tiptap-content {
        .hero-block {
            ...
        }
    }
  10. Configure Custom Theme for Tiptap Editor

    3.x

    To align with Filament's theming methodology, you must use a custom theme. Follow these steps:

    1. Import Stylesheets: Add the plugin and tippy.js stylesheets to your theme's CSS file.
    2. Update Tailwind Config: Add the plugin's Blade views to your tailwind.config.js content array.
    3. Configure PostCSS: Add tailwindcss/nesting to your postcss.config.js.
    4. Rebuild: Run your build command (e.g., npm run build).
    /* 1. CSS Import */
    @import '<path-to-vendor>/awcodes/filament-tiptap-editor/resources/css/plugin.css';
    
    /* 2. tailwind.config.js */
    content: [
        ...
        '<path-to-vendor>/awcodes/filament-tiptap-editor/resources/**/*.blade.php',
    ]
    
    /* 3. postcss.config.js */
    module.exports = {
        plugins: {
            'tailwindcss/nesting': {},
            tailwindcss: {},
            autoprefixer: {},
        },
    }
    
    /* 4. Rebuild */
    npm run build
  11. Create a PHP parser for extensions

    3.x

    To allow the editor to read content from the database and render it correctly on the frontend, you must create a corresponding PHP class. This class should extend Tiptap\Core\Node. A common location for these is app/TiptapExtensions/.

    namespace App\TiptapExtensions;
    
    use Tiptap\Core\Node;
    
    class Hero extends Node
    {
        public static $name = 'hero';
        ...
    }