sibiraj-s / svelte-tiptap

Svelte components for tiptap v2
https://sibiraj-s.github.io/svelte-tiptap/
MIT License
225 stars 18 forks source link

Help with the `isActive` reactivity #29

Closed shyakadavis closed 1 year ago

shyakadavis commented 1 year ago

Hi.

First and foremost, thank you so much for the project. It has been a great joy using it.

That said, I ran into some trouble trying to create the style toggle items.

From the examples, you create individual functions, say:

const toggleHeading = (level: 1 | 2) => {
        return () => {
            $editor.chain().focus().toggleHeading({ level }).run();
        };
    };

and then create a button to toggle:

<button
        type="button"
        class={cx('hover:bg-black hover:text-white w-7 h-7 rounded', {
            'bg-black text-white': isActive('heading', { level: 1 })
        })}
        on:click={toggleHeading(1)}
    >
            H1
</button>

Now, given that I want to create several menu items, I don't want the trouble of repeating the above snippet2 for every item.

So, I created an array as such:

const menuItems = [
        {
            name: 'heading 1',
            command: toggleHeading(1),
            content: 'Heading 1',
            icon: Heading1,
            active: () => isActive('heading', { level: 1 })
        },
        {
            name: 'heading 2',
            command: toggleHeading(2),
            content: 'Heading 2',
            icon: Heading2,
            active: () => isActive('heading', { level: 2 })
        },
        {
            name: 'heading 3',
            command: toggleHeading(3),
            content: 'Heading 3',
            icon: Heading3,
            active: () => isActive('heading', { level: 3 })
        },
        {
            name: 'heading 4',
            command: toggleHeading(4),
            content: 'Heading 4',
            icon: Heading4,
            active: () => isActive('heading', { level: 4 })
        },
        {
            name: 'heading 5',
            command: toggleHeading(5),
            content: 'Heading 5',
            icon: Heading5,
            active: () => isActive('heading', { level: 5 })
        },
        {
            name: 'heading 6',
            command: toggleHeading(6),
            content: 'Heading 6',
            icon: Heading6,
            active: () => isActive('heading', { level: 6 })
        },
        {
            name: 'bold',
            command: toggleBold,
            content: 'Bold',
            icon: Bold,
            active: () => isActive('bold')
        },
        {
            name: 'italic',
            command: toggleItalic,
            content: 'Italic',
            icon: Italic,
            active: () => isActive('italic')
        },
        {
            name: 'code',
            command: toggleCodeBlock,
            content: 'Code',
            icon: Code,
            active: () => isActive('codeBlock')
        },
        {
            name: 'strike',
            command: toggleStrike,
            content: 'Strike',
            icon: Strikethrough,
            active: () => isActive('strike')
        },
        {
            name: 'bulletList',
            command: toggleBulletList,
            content: 'Bullet List',
            icon: List,
            active: () => isActive('bulletList')
        },
        {
            name: 'orderedList',
            command: toggleOrderedList,
            content: 'Ordered List',
            icon: ListOrdered,
            active: () => isActive('orderedList')
        },
        {
            name: 'paragraph',
            command: setParagraph,
            content: 'Paragraph',
            icon: Pilcrow,
            active: () => isActive('paragraph')
        }
    ];

so that I can iterate in the markup like so:

    {#if editor && editable}
    <TooltipProvider>
        <ul class="flex p-2 border-2 border-b-0 rounded-t-md">
            {#each menuItems as item (item.name)}
                <li>
                    <Tooltip>
                        <TooltipTrigger>
                            <button
                                class={cn(
                                    'hover:bg-black hover:text-white w-7 h-7 rounded grid place-items-center',
                                    {
                                        'bg-black text-white': item.active()
                                    }
                                )}
                                on:click={item.command}
                            >
                                <svelte:component this={item.icon} class="w-4 h-4" />
                                <span class="sr-only">{item.content}</span>
                            </button>
                        </TooltipTrigger>
                        <TooltipContent>
                            <p>{item.content}</p>
                        </TooltipContent>
                    </Tooltip>
                </li>
            {/each}
        </ul>
    </TooltipProvider>
    {/if}

The problem I ran into, is that when doing it like that, the isActive store doesn't seem to work. What I mean is:

Any help is greatly appreciated.

Here is a link to a detailed Gist

Thanks.

sibiraj-s commented 1 year ago

I am not sure, if this is an issue with the package. Also, thanks for the detailed code, And I don't have lot of spare time ATM, It would be greatly appreciated if you could move this code to a stackblitz and provide a working example so it would help me assist faster.

You can include the part (for loop) version that you are trying to get working. No need to included the one that is commented out in gist.

shyakadavis commented 1 year ago

Hey, @sibiraj-s. Here is the StackBlitz link.

Please let me know if something is wrong or the like.

Thanks.

sibiraj-s commented 1 year ago

The stackblitz doesn't load for some reason.

Also I see this error on terminal Screenshot 2023-08-03 at 8 48 53 PM

sibiraj-s commented 1 year ago

Okay. I copied some code to my local and tried it.

Change

const menuItems = []

to

$: menuItems = []

This should fix the issue.

I am moving this to a discussion as this is not an issue with editor.