From 8d93c35faae1920395f16e30adac491c84e8bdf3 Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Tue, 16 Jun 2026 14:32:55 +0200 Subject: [PATCH 01/11] fix: include yjs relative positions in RESTYjsThreadStore wire format Pass the editor through addThreadToDocument so RESTYjsThreadStore can compute yjs relative positions from the prosemirror selection, restoring wire compatibility with the {prosemirror, yjs} selection shape. --- packages/core/src/comments/extension.ts | 1 + .../src/comments/threadstore/ThreadStore.ts | 2 ++ .../src/yjs/comments/RESTYjsThreadStore.ts | 32 +++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/core/src/comments/extension.ts b/packages/core/src/comments/extension.ts index c037e80ddf..e930a9b4b3 100644 --- a/packages/core/src/comments/extension.ts +++ b/packages/core/src/comments/extension.ts @@ -353,6 +353,7 @@ export const CommentsExtension = createExtension( await threadStore.addThreadToDocument({ threadId: thread.id, selection: editor.transact((tr) => tr.selection), + editor, }); } else { (editor as any)._tiptapEditor.commands.setMark(markType, { diff --git a/packages/core/src/comments/threadstore/ThreadStore.ts b/packages/core/src/comments/threadstore/ThreadStore.ts index bce6be71c0..3e5ef1b58a 100644 --- a/packages/core/src/comments/threadstore/ThreadStore.ts +++ b/packages/core/src/comments/threadstore/ThreadStore.ts @@ -1,3 +1,4 @@ +import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js"; import { CommentBody, CommentData, ThreadData } from "../types.js"; import { ThreadStoreAuth } from "./ThreadStoreAuth.js"; @@ -26,6 +27,7 @@ export abstract class ThreadStore { head: number; anchor: number; }; + editor: BlockNoteEditor; }): Promise; /** diff --git a/packages/core/src/yjs/comments/RESTYjsThreadStore.ts b/packages/core/src/yjs/comments/RESTYjsThreadStore.ts index 23bd49e3f9..2e7fdba910 100644 --- a/packages/core/src/yjs/comments/RESTYjsThreadStore.ts +++ b/packages/core/src/yjs/comments/RESTYjsThreadStore.ts @@ -1,7 +1,12 @@ import * as Y from "yjs"; +import { + absolutePositionToRelativePosition, + ySyncPluginKey, +} from "y-prosemirror"; import type { CommentBody } from "../../comments/types.js"; import type { ThreadStoreAuth } from "../../comments/threadstore/ThreadStoreAuth.js"; import { YjsThreadStoreBase } from "./YjsThreadStoreBase.js"; +import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js"; /** * This is a REST-based implementation of the YjsThreadStoreBase. @@ -50,9 +55,32 @@ export class RESTYjsThreadStore extends YjsThreadStoreBase { head: number; anchor: number; }; + editor: BlockNoteEditor; }) => { - const { threadId, ...rest } = options; - return this.doRequest(`/${threadId}/addToDocument`, "POST", rest); + const { threadId, selection } = options; + + const binding = ySyncPluginKey.getState(options.editor.prosemirrorState); + const yjsSelection = binding + ? { + head: absolutePositionToRelativePosition( + selection.head, + binding.type, + binding.mapping, + ), + anchor: absolutePositionToRelativePosition( + selection.anchor, + binding.type, + binding.mapping, + ), + } + : undefined; + + return this.doRequest(`/${threadId}/addToDocument`, "POST", { + selection: { + prosemirror: selection, + yjs: yjsSelection, + }, + }); }; public createThread = async (options: { From 528b74d6f03756a608db196d0580f39d0cb7afd2 Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Tue, 16 Jun 2026 14:42:35 +0200 Subject: [PATCH 02/11] chore: fix all lint warnings across codebase Resolve 86 lint warnings reported by vp check: prefix unused variables/params with _, remove unused catch bindings, delete unused imports, convert ternary-as-statement to if/else, add missing JSX keys, fix React hook dependency arrays, wrap handlers in useCallback, and suppress intentional lint exceptions. --- docs/app/(home)/error.tsx | 2 +- docs/app/[...slug]/error.tsx | 2 +- docs/app/demo/_components/DemoEditor.tsx | 3 +- docs/app/docs/error.tsx | 2 +- docs/app/examples/error.tsx | 2 +- docs/app/not-found.tsx | 2 +- docs/components/Footer.tsx | 2 +- docs/emails/magic-link.tsx | 2 +- docs/instrumentation-client.ts | 2 ++ .../01-basic/02-block-objects/src/App.tsx | 1 + .../05-removing-default-blocks/src/App.tsx | 6 +++- .../13-custom-paste-handler/src/App.tsx | 8 ++--- .../src/App.tsx | 1 + .../src/App.tsx | 1 + .../11-uppy-file-panel/src/UppyFilePanel.tsx | 2 +- .../13-custom-ui/src/MUIFormattingToolbar.tsx | 17 ++++++---- .../13-custom-ui/src/MUISideMenu.tsx | 1 + .../05-converting-blocks-to-pdf/src/App.tsx | 1 + .../src/App.tsx | 1 + .../src/App.tsx | 4 ++- .../01-alert-block/src/App.tsx | 2 +- .../05-alert-block-full-ux/src/App.tsx | 2 +- .../react-custom-styles/src/App.tsx | 2 +- .../07-ghost-writer/src/App.tsx | 1 + .../09-ai/04-with-collaboration/src/App.tsx | 1 + .../09-ai/07-server-persistence/src/App.tsx | 2 +- .../react-vanilla-custom-styles/src/App.tsx | 2 +- packages/ariakit/src/comments/Comment.tsx | 6 ++-- packages/ariakit/src/comments/Editor.tsx | 2 +- packages/ariakit/src/menu/Menu.tsx | 4 +-- packages/ariakit/src/panel/Panel.tsx | 2 +- packages/ariakit/src/toolbar/Toolbar.tsx | 2 +- .../ariakit/src/toolbar/ToolbarButton.tsx | 2 +- .../commands/updateBlock/updateBlock.test.ts | 6 ++-- packages/core/src/util/string.ts | 2 +- packages/core/src/util/typescript.ts | 2 +- packages/mantine/src/comments/Comment.tsx | 6 ++-- packages/mantine/src/comments/Editor.tsx | 11 ++++-- packages/mantine/src/popover/Popover.tsx | 2 +- .../GridSuggestionMenuLoader.tsx | 2 +- .../react/src/blocks/File/useResolveUrl.tsx | 2 +- .../components/ColorPicker/ColorPicker.tsx | 4 +-- .../Comments/defaultCommentEditorSchema.ts | 6 +++- .../FilePanel/DefaultTabs/UploadTab.tsx | 2 +- .../DefaultButtons/BasicTextStyleButton.tsx | 2 +- .../DefaultButtons/ColorStyleButton.tsx | 16 +++++---- packages/react/src/hooks/useFocusWithin.ts | 34 +++++++++++-------- packages/react/src/util/sanitizeUrl.ts | 2 +- packages/shadcn/src/comments/Comment.tsx | 6 ++-- packages/shadcn/src/comments/Editor.tsx | 2 +- packages/shadcn/src/form/TextInput.tsx | 4 +-- packages/shadcn/src/menu/Menu.tsx | 2 +- packages/shadcn/src/panel/Panel.tsx | 2 +- packages/shadcn/src/popover/popover.tsx | 2 +- .../formats/html-blocks/htmlBlocks.test.ts | 3 +- .../src/odt/defaultSchema/blocks.tsx | 2 +- .../xl-odt-exporter/src/odt/odtExporter.tsx | 3 ++ 57 files changed, 130 insertions(+), 87 deletions(-) diff --git a/docs/app/(home)/error.tsx b/docs/app/(home)/error.tsx index e9d74decf7..dad7906e5e 100644 --- a/docs/app/(home)/error.tsx +++ b/docs/app/(home)/error.tsx @@ -6,7 +6,7 @@ import { useEffect } from "react"; export default function Error({ error, - reset, + reset: _reset, }: { error: Error & { digest?: string }; reset: () => void; diff --git a/docs/app/[...slug]/error.tsx b/docs/app/[...slug]/error.tsx index 5bd0f86ddb..3e60d8583f 100644 --- a/docs/app/[...slug]/error.tsx +++ b/docs/app/[...slug]/error.tsx @@ -6,7 +6,7 @@ import { useEffect } from "react"; export default function Error({ error, - reset, + reset: _reset, }: { error: Error & { digest?: string }; reset: () => void; diff --git a/docs/app/demo/_components/DemoEditor.tsx b/docs/app/demo/_components/DemoEditor.tsx index fa16d07a8f..e7cb3268e5 100644 --- a/docs/app/demo/_components/DemoEditor.tsx +++ b/docs/app/demo/_components/DemoEditor.tsx @@ -202,7 +202,8 @@ function DemoEditorInner({ doc, ); return { doc, provider }; - }, [roomId, activeUser]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [roomId]); // Thread Store const threadStore = useMemo(() => { return new YjsThreadStore( diff --git a/docs/app/docs/error.tsx b/docs/app/docs/error.tsx index b2fd1a418b..460a3a7c0c 100644 --- a/docs/app/docs/error.tsx +++ b/docs/app/docs/error.tsx @@ -6,7 +6,7 @@ import { useEffect } from "react"; export default function Error({ error, - reset, + reset: _reset, }: { error: Error & { digest?: string }; reset: () => void; diff --git a/docs/app/examples/error.tsx b/docs/app/examples/error.tsx index 422af4d0b6..3933796c05 100644 --- a/docs/app/examples/error.tsx +++ b/docs/app/examples/error.tsx @@ -6,7 +6,7 @@ import { useEffect } from "react"; export default function Error({ error, - reset, + reset: _reset, }: { error: Error & { digest?: string }; reset: () => void; diff --git a/docs/app/not-found.tsx b/docs/app/not-found.tsx index 01305c0b45..ae7a441734 100644 --- a/docs/app/not-found.tsx +++ b/docs/app/not-found.tsx @@ -79,7 +79,7 @@ export default function NotFound() { .slice(0, 8); setSearchResults(pageResults.length > 0 ? pageResults : fallbackPages); - } catch (error) { + } catch { setSearchResults(fallbackPages); } finally { setIsLoading(false); diff --git a/docs/components/Footer.tsx b/docs/components/Footer.tsx index 15094b1e2b..365f0efb33 100644 --- a/docs/components/Footer.tsx +++ b/docs/components/Footer.tsx @@ -145,7 +145,7 @@ export function FooterContent() { ); } -export function Footer({ menu }: { menu?: boolean }): ReactElement { +export function Footer({ menu: _menu }: { menu?: boolean }): ReactElement { return (