diff --git a/docs/ABSTRACTIONS.md b/docs/ABSTRACTIONS.md index 9ce527bf..cf81d6d9 100644 --- a/docs/ABSTRACTIONS.md +++ b/docs/ABSTRACTIONS.md @@ -573,7 +573,7 @@ Defined in `src/components/tolariaEditorFormatting.tsx` and `src/components/tola - `useImageLightbox` listens for `dblclick` on the rich-editor container and opens `ImageLightbox` only when the event target resolves to a viewable BlockNote image. The target resolver handles media wrappers, ignores image captions/resize controls, missing sources, and tiny tracking-style images, preserving BlockNote's ordinary single-click image selection path. - The `/` slash menu remains the supported path for markdown-safe block transformations such as headings, quotes, list blocks, Mermaid diagrams, and whiteboards. Tolaria filters out BlockNote's toggle-heading and toggle-list variants because those do not map cleanly to the markdown note model. - The block-handle side menu keeps only actions that survive Tolaria's markdown round-trip. Delete and table-header toggles remain available; BlockNote's `Colors` submenu is removed because block colors are not part of Tolaria's supported markdown surface. Tolaria renders the add-block button outside the drag handle so the handle stays next to the block content. The side menu aligns itself to the first rendered text line for the hovered block, so H1/H2 typography, line-height, wrapping, and theme changes do not need per-heading offsets. Block reordering uses a Tolaria-owned pointer gesture and direct BlockNote block moves instead of HTML5 `DataTransfer`, keeping it independent from Tauri's native file-drop system. Block-handle actions re-resolve the current live BlockNote block before mutating or dragging, so note reloads and sync churn cannot leave controls acting on stale block references. -- BlockNote's table row/column handles are patched so stale or missing hovered-table state cancels the drag and hides handles instead of throwing. Add/remove row and column actions also validate the table position and cell indexes before resolving a ProseMirror `CellSelection`, so reloads or menu lag cannot turn stale handles into invalid table-selection positions. Browser and native table regressions should exercise row and column dragging plus add-menu actions because the state is tracked per orientation. +- BlockNote's table row/column handles are patched so stale or missing hovered-table state cancels the drag and hides handles instead of throwing. Add/remove row and column actions also validate the table position and cell indexes before resolving a ProseMirror `CellSelection`, so reloads or menu lag cannot turn stale handles into invalid table-selection positions. Checklist checkbox handlers also re-resolve the live block before updating `checked`, making delayed clicks after note reloads a no-op instead of a stale block mutation. Browser and native table regressions should exercise row and column dragging plus add-menu actions because the state is tracked per orientation. - `useNoteWikilinkDrop()` is the shared editor-drop abstraction for dragging note rows into either editor mode. It reads the existing note-retargeting drag payload, resolves the vault-relative stem, and inserts a canonical `[[wikilink]]` without hijacking unrelated plain-text drags. - `plainTextPaste.ts` is the shared plain-text paste target registry. Rich BlockNote and raw CodeMirror surfaces register focused insertion targets, while ordinary focused text controls use DOM selection replacement, so the `Cmd+Shift+V` command can preserve caret/selection behavior without each surface inventing its own clipboard reader. - `useTauriDragDropEvent()` owns the shared Tauri window drag/drop subscription and duplicate-unlisten cleanup used by native drop features. diff --git a/patches/@blocknote__core@0.46.2.patch b/patches/@blocknote__core@0.46.2.patch index 5aa4fce0..ec8de287 100644 --- a/patches/@blocknote__core@0.46.2.patch +++ b/patches/@blocknote__core@0.46.2.patch @@ -346,6 +346,20 @@ index b2761001278486a8b2ac1d10c82420b4994e96d9..c44e9c09100c6d1803bd71b2a338c43e n.updateBlock(t.id, { props: { language: d } }); }; i.addEventListener("change", l), s = () => i.removeEventListener("change", l); +@@ -1802,9 +1804,12 @@ const ln = () => ({ + parseContent: ({ el: e, schema: t }) => Y(e, t, "checkListItem"), + render(e, t) { + const n = document.createDocumentFragment(), o = document.createElement("input"); + o.type = "checkbox", o.checked = e.props.checked, e.props.checked && o.setAttribute("checked", ""), o.addEventListener("change", () => { +- t.updateBlock(e, { props: { checked: !e.props.checked } }); ++ const r = t.getBlock(e.id); ++ if (!r) ++ return; ++ t.updateBlock(r, { props: { checked: !r.props.checked } }); + }); + const r = document.createElement("p"), a = document.createElement("div"); + return a.contentEditable = "false", a.appendChild(o), n.appendChild(a), n.appendChild(r), { + dom: n, @@ -2621,6 +2623,9 @@ class On { this.state.referencePos = o.getBoundingClientRect().toJSON(), this.emitUpdate(this.pluginState.triggerCharacter); } @@ -441,6 +455,24 @@ index dbb7fc33a9add7a96488349876bc56ad60111a3f..58c3cf181f25467d85cd8c3788b5b73d editor.updateBlock(block.id, { props: { language } }); }; select.addEventListener("change", handleLanguageChange); +diff --git a/src/blocks/ListItem/CheckListItem/block.ts b/src/blocks/ListItem/CheckListItem/block.ts +index 682cbba711bd9ca107fe3940f44ab39fc757cfe0..2d2f871ac13836b736543b29a620580a7a3f1057 100644 +--- a/src/blocks/ListItem/CheckListItem/block.ts ++++ b/src/blocks/ListItem/CheckListItem/block.ts +@@ -82,7 +82,12 @@ export const createCheckListItemBlockSpec = createBlockSpec( + checkbox.setAttribute("checked", ""); + } + checkbox.addEventListener("change", () => { +- editor.updateBlock(block, { props: { checked: !block.props.checked } }); ++ const liveBlock = editor.getBlock(block.id); ++ if (!liveBlock) { ++ return; ++ } ++ ++ editor.updateBlock(liveBlock, { props: { checked: !liveBlock.props.checked } }); + }); + // We use a

tag, because for

  • tags we'd need a