fix: fix toolbar active states not updating in Svelte 5
This commit is contained in:
1 parent
c3da447674
commit
da32b2d773
3 files changed
+26
-14
No files matched your search
+3
-2
@@ -5,6 +5,7 @@
|
||||
import { exportToOdt } from './lib/export/odt';
|
||||
|
||||
let editor: Editor | null = $state(null);
|
||||
let tick: number = $state(0);
|
||||
|
||||
async function handleExport() {
|
||||
if (editor) await exportToOdt(editor);
|
||||
@@ -13,12 +14,12 @@
|
||||
|
||||
<main>
|
||||
<header>
|
||||
<Toolbar {editor} />
|
||||
<Toolbar {editor} {tick} />
|
||||
<button class="export-btn" onclick={handleExport} disabled={!editor}>
|
||||
Download .odt
|
||||
</button>
|
||||
</header>
|
||||
<EditorComponent bind:editor />
|
||||
<EditorComponent bind:editor bind:tick />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { saveDocument, loadDocument } from '../storage/autosave';
|
||||
import '../../styles/editor.css';
|
||||
|
||||
let { editor = $bindable() }: { editor: Editor | null } = $props();
|
||||
let { editor = $bindable(), tick = $bindable(0) }: { editor: Editor | null; tick: number } = $props();
|
||||
|
||||
let element: HTMLDivElement;
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
extensions,
|
||||
content: saved || undefined,
|
||||
onTransaction: () => {
|
||||
// Force Svelte reactivity update
|
||||
editor = editor;
|
||||
// Increment tick to signal Svelte that editor state changed.
|
||||
// (editor = editor is a no-op in Svelte 5 for same references)
|
||||
tick++;
|
||||
},
|
||||
onUpdate: ({ editor: e }) => {
|
||||
saveDocument(e.getJSON());
|
||||
|
||||
@@ -1,28 +1,38 @@
|
||||
<script lang="ts">
|
||||
import type { Editor } from '@tiptap/core';
|
||||
|
||||
let { editor }: { editor: Editor | null } = $props();
|
||||
let { editor, tick }: { editor: Editor | null; tick: number } = $props();
|
||||
|
||||
// $derived re-evaluates whenever `tick` changes (i.e. on every TipTap transaction)
|
||||
let isBold = $derived(tick >= 0 && !!editor?.isActive('bold'));
|
||||
let isItalic = $derived(tick >= 0 && !!editor?.isActive('italic'));
|
||||
let isUnderline = $derived(tick >= 0 && !!editor?.isActive('underline'));
|
||||
let isH1 = $derived(tick >= 0 && !!editor?.isActive('heading', { level: 1 }));
|
||||
let isH2 = $derived(tick >= 0 && !!editor?.isActive('heading', { level: 2 }));
|
||||
let isH3 = $derived(tick >= 0 && !!editor?.isActive('heading', { level: 3 }));
|
||||
let canUndo = $derived(tick >= 0 && !!editor?.can().undo());
|
||||
let canRedo = $derived(tick >= 0 && !!editor?.can().redo());
|
||||
</script>
|
||||
|
||||
<div class="toolbar">
|
||||
{#if editor}
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class:active={editor.isActive('bold')}
|
||||
class:active={isBold}
|
||||
onclick={() => editor?.chain().focus().toggleBold().run()}
|
||||
title="Bold (Ctrl+B)"
|
||||
>
|
||||
<strong>B</strong>
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('italic')}
|
||||
class:active={isItalic}
|
||||
onclick={() => editor?.chain().focus().toggleItalic().run()}
|
||||
title="Italic (Ctrl+I)"
|
||||
>
|
||||
<em>I</em>
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('underline')}
|
||||
class:active={isUnderline}
|
||||
onclick={() => editor?.chain().focus().toggleUnderline().run()}
|
||||
title="Underline (Ctrl+U)"
|
||||
>
|
||||
@@ -34,21 +44,21 @@
|
||||
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class:active={editor.isActive('heading', { level: 1 })}
|
||||
class:active={isH1}
|
||||
onclick={() => editor?.chain().focus().toggleHeading({ level: 1 }).run()}
|
||||
title="Heading 1"
|
||||
>
|
||||
H1
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('heading', { level: 2 })}
|
||||
class:active={isH2}
|
||||
onclick={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}
|
||||
title="Heading 2"
|
||||
>
|
||||
H2
|
||||
</button>
|
||||
<button
|
||||
class:active={editor.isActive('heading', { level: 3 })}
|
||||
class:active={isH3}
|
||||
onclick={() => editor?.chain().focus().toggleHeading({ level: 3 }).run()}
|
||||
title="Heading 3"
|
||||
>
|
||||
@@ -61,14 +71,14 @@
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
onclick={() => editor?.chain().focus().undo().run()}
|
||||
disabled={!editor.can().undo()}
|
||||
disabled={!canUndo}
|
||||
title="Undo (Ctrl+Z)"
|
||||
>
|
||||
↩
|
||||
</button>
|
||||
<button
|
||||
onclick={() => editor?.chain().focus().redo().run()}
|
||||
disabled={!editor.can().redo()}
|
||||
disabled={!canRedo}
|
||||
title="Redo (Ctrl+Shift+Z)"
|
||||
>
|
||||
↪
|
||||
|
||||
Reference in new issue
Block a user