From 14d5a7b5a7287f23e375fe4b7a220323b39c9404 Mon Sep 17 00:00:00 2001 From: umaranis <mail@umaranis.com> Date: Wed, 13 Nov 2024 21:56:41 +1100 Subject: [PATCH] feat: Action bar button to toggle read-only mode and move isEditable context into Composer --- .../lib/components/actionbar/ActionBar.svelte | 2 ++ .../components/actionbar/ReadonlyButton.svelte | 17 +++++++++++++++++ .../src/lib/components/toolbar/Toolbar.svelte | 10 ---------- .../src/lib/core/Composer.svelte | 18 ++++++++++++------ 4 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 packages/svelte-lexical/src/lib/components/actionbar/ReadonlyButton.svelte diff --git a/packages/svelte-lexical/src/lib/components/actionbar/ActionBar.svelte b/packages/svelte-lexical/src/lib/components/actionbar/ActionBar.svelte index 77426379..929c94a5 100644 --- a/packages/svelte-lexical/src/lib/components/actionbar/ActionBar.svelte +++ b/packages/svelte-lexical/src/lib/components/actionbar/ActionBar.svelte @@ -1,9 +1,11 @@ <script lang="ts"> import ImportButton from './ImportButton.svelte'; import ExportButton from './ExportButton.svelte'; + import ReadonlyButton from './ReadonlyButton.svelte'; </script> <div class="actions"> <ImportButton /> <ExportButton /> + <ReadonlyButton /> </div> diff --git a/packages/svelte-lexical/src/lib/components/actionbar/ReadonlyButton.svelte b/packages/svelte-lexical/src/lib/components/actionbar/ReadonlyButton.svelte new file mode 100644 index 00000000..a1cfcf64 --- /dev/null +++ b/packages/svelte-lexical/src/lib/components/actionbar/ReadonlyButton.svelte @@ -0,0 +1,17 @@ +<script lang="ts"> + import type {LexicalEditor} from 'lexical'; + import {getEditor, getIsEditable} from '$lib/core/composerContext.js'; + + const editor: LexicalEditor = getEditor(); + const isEditable = getIsEditable(); +</script> + +<button + class={`action-button ${!$isEditable ? 'unlock' : 'lock'}`} + on:click={() => { + editor.setEditable(!editor.isEditable()); + }} + title="Read-Only Mode" + aria-label={`${!$isEditable ? 'Unlock' : 'Lock'} read-only mode`}> + <i class={!$isEditable ? 'unlock' : 'lock'} /> +</button> diff --git a/packages/svelte-lexical/src/lib/components/toolbar/Toolbar.svelte b/packages/svelte-lexical/src/lib/components/toolbar/Toolbar.svelte index 20e90621..ff0e4247 100644 --- a/packages/svelte-lexical/src/lib/components/toolbar/Toolbar.svelte +++ b/packages/svelte-lexical/src/lib/components/toolbar/Toolbar.svelte @@ -4,14 +4,10 @@ import StateStoreRichTextUpdator from './StateStoreRichTextUpdator.svelte'; import {setContext} from 'svelte'; import {getEditor} from '$lib/core/composerContext.js'; - import {onMount} from 'svelte'; import type {NodeKey} from 'lexical'; const editor = getEditor(); - const isEditable = writable(editor.isEditable()); - setContext('isEditable', isEditable); - const activeEditor = writable(editor); setContext('activeEditor', activeEditor); @@ -36,12 +32,6 @@ setContext('codeLanguage', writable('')); setContext('isLink', writable(false)); setContext('isImageCaption', writable(false)); - - onMount(() => { - return editor.registerEditableListener((editable) => { - $isEditable = editable; - }); - }); </script> <StateStoreRichTextUpdator /> diff --git a/packages/svelte-lexical/src/lib/core/Composer.svelte b/packages/svelte-lexical/src/lib/core/Composer.svelte index 15f6999b..5297be5d 100644 --- a/packages/svelte-lexical/src/lib/core/Composer.svelte +++ b/packages/svelte-lexical/src/lib/core/Composer.svelte @@ -29,13 +29,14 @@ type LexicalNodeReplacement, type HTMLConfig, } from 'lexical'; - import {onMount} from 'svelte'; + import {onMount, setContext} from 'svelte'; import {initializeEditor} from './initializeEditor.js'; import { createSharedEditorContext, setEditor, setHistoryStateContext, } from './composerContext.js'; + import {writable} from 'svelte/store'; export let initialConfig: InitialConfigType; @@ -60,16 +61,21 @@ initializeEditor(editor, initialEditorState); setEditor(editor); + const isEditable = writable(editable !== undefined ? editable : true); + setContext('isEditable', isEditable); + + onMount(() => { + editor.setEditable($isEditable); + return editor.registerEditableListener((editable) => { + $isEditable = editable; + }); + }); + setHistoryStateContext(createEmptyHistoryState()); // allows sharing context between plugins and decorator nodes createSharedEditorContext(); - onMount(() => { - const isEditable = initialConfig.editable; - editor.setEditable(isEditable !== undefined ? isEditable : true); - }); - export function getEditor() { return editor; }