diff --git a/patches/@blocknote__react@0.46.2.patch b/patches/@blocknote__react@0.46.2.patch index ba191c46..10c3f4dd 100644 --- a/patches/@blocknote__react@0.46.2.patch +++ b/patches/@blocknote__react@0.46.2.patch @@ -1,8 +1,9 @@ diff --git a/dist/blocknote-react.js b/dist/blocknote-react.js -index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3f9f0ea59 100644 +index d4d36cd4dbb5370c3b7431ffeb577e4870b39825..5a6c325bf0ff9a23f2023169d7fcf6319df91544 100644 --- a/dist/blocknote-react.js +++ b/dist/blocknote-react.js -@@ -155,8 +155,26 @@ var Rt = (e) => { +@@ -154,8 +154,26 @@ const co = (e) => { + }; function so(e) { let t = new DOMRect(); - const n = "getBoundingClientRect" in e ? () => e.getBoundingClientRect() : () => e.element.getBoundingClientRect(); @@ -17,7 +18,7 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3 + t = n(); + return t; + }; - } ++} +function __bnSafeDomAtPos(e, t) { + const n = e.prosemirrorView; + if (!n || n.isDestroyed) @@ -27,11 +28,10 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3 + } catch { + return null; + } -+} + } const z = (e) => { var h, b, p; - const { refs: t, floatingStyles: n, context: o } = Ze({ -@@ -216,9 +234,7 @@ const Lt = (e) => { +@@ -216,9 +234,7 @@ const z = (e) => { const s = Ue(t, c.doc); if (!s) return; @@ -42,7 +42,39 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3 if (a instanceof Element) return { element: a -@@ -3306,14 +3322,15 @@ const pi = (e) => { +@@ -2499,7 +2515,14 @@ function Kr(e) { + columns: d + } = e, m = H( + (C) => { +- a(), s(), u == null || u(C); ++ a(); ++ try { ++ s(); ++ } catch (x) { ++ console.warn("Ignored stale suggestion menu query cleanup:", x); ++ return; ++ } ++ u == null || u(C); + }, + [u, a, s] + ), { items: g, usedQuery: f, loadingState: h } = Yt( +@@ -2734,7 +2757,14 @@ function ti(e) { + onItemClick: u + } = e, d = H( + (p) => { +- a(), s(), u == null || u(p); ++ a(); ++ try { ++ s(); ++ } catch (C) { ++ console.warn("Ignored stale suggestion menu query cleanup:", C); ++ return; ++ } ++ u == null || u(p); + }, + [u, a, s] + ), { items: m, usedQuery: g, loadingState: f } = Yt( +@@ -3306,14 +3336,15 @@ const ii = (e, t = 0.3) => { ); if (!m) return {}; @@ -61,7 +93,7 @@ index 6271d12d2cd5152e924c5bfe78f3b8904844dbfe..12bb96bb36d445a77d51a18d0de446a3 return p instanceof Element ? (d.cellReference = { element: p }, d.rowReference = { element: f, getBoundingClientRect: () => { -@@ -4371,7 +4388,7 @@ const El = (e) => { +@@ -4371,7 +4402,7 @@ const zi = (e) => { const a = Ue(t, c.prosemirrorState.doc); if (!a) return; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d519fa29..1cd0be10 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,7 +19,7 @@ patchedDependencies: hash: c93b0eab9c8a1800cc1489627146cbe9037999f409efcc8234b33f670d2ccf8d path: patches/@blocknote__core@0.46.2.patch '@blocknote/react@0.46.2': - hash: e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76 + hash: 9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08 path: patches/@blocknote__react@0.46.2.patch '@tiptap/extension-link@3.19.0': hash: fbe59b1b8b798ba3fefa371c0729b5aa3458e1ea70a4b86cd5267f9f62529284 @@ -46,7 +46,7 @@ importers: version: 0.46.2(@floating-ui/dom@1.7.5)(@mantine/core@8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@mantine/hooks@8.3.14(react@19.2.4))(@mantine/utils@6.0.22(react@19.2.4))(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@blocknote/react': specifier: ^0.46.2 - version: 0.46.2(patch_hash=e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 0.46.2(patch_hash=9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@codemirror/commands': specifier: ^6.10.2 version: 6.10.2 @@ -5677,7 +5677,7 @@ snapshots: '@blocknote/mantine@0.46.2(@floating-ui/dom@1.7.5)(@mantine/core@8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@mantine/hooks@8.3.14(react@19.2.4))(@mantine/utils@6.0.22(react@19.2.4))(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@blocknote/core': 0.46.2(patch_hash=c93b0eab9c8a1800cc1489627146cbe9037999f409efcc8234b33f670d2ccf8d)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0) - '@blocknote/react': 0.46.2(patch_hash=e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@blocknote/react': 0.46.2(patch_hash=9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@mantine/core': 8.3.14(@mantine/hooks@8.3.14(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@mantine/hooks': 8.3.14(react@19.2.4) '@mantine/utils': 6.0.22(react@19.2.4) @@ -5696,7 +5696,7 @@ snapshots: - sugar-high - supports-color - '@blocknote/react@0.46.2(patch_hash=e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@blocknote/react@0.46.2(patch_hash=9721936e806f31cf440cc94ead3ec03764ae968870c167d086a8e60d8f6d4a08)(@floating-ui/dom@1.7.5)(@types/hast@3.0.4)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(highlight.js@11.11.1)(lowlight@3.3.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@blocknote/core': 0.46.2(patch_hash=c93b0eab9c8a1800cc1489627146cbe9037999f409efcc8234b33f670d2ccf8d)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0) '@emoji-mart/data': 1.2.1 diff --git a/src/lib/blockNoteSuggestionWrapper.regression.test.tsx b/src/lib/blockNoteSuggestionWrapper.regression.test.tsx new file mode 100644 index 00000000..ea85e34b --- /dev/null +++ b/src/lib/blockNoteSuggestionWrapper.regression.test.tsx @@ -0,0 +1,60 @@ +import { fireEvent, render, screen, waitFor } from '@testing-library/react' +import { BlockNoteContext, SuggestionMenuWrapper } from '@blocknote/react' +import { describe, expect, it, vi } from 'vitest' +import type { SuggestionMenuProps } from '@blocknote/react' + +function createEditor() { + return { + domElement: document.createElement('div'), + } +} + +function Menu({ items, onItemClick }: SuggestionMenuProps) { + return ( + + ) +} + +describe('patched BlockNote suggestion wrapper', () => { + it('ignores stale query cleanup before running a suggestion item action', async () => { + const closeMenu = vi.fn() + const clearQuery = vi.fn(() => { + throw new RangeError('Position -1322 outside of fragment') + }) + const onItemClick = vi.fn() + const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) + + render( + + ['paragraph']} + suggestionMenuComponent={Menu} + onItemClick={onItemClick} + /> + , + ) + + fireEvent.click(await screen.findByRole('button', { name: 'Pick suggestion' })) + + expect(closeMenu).toHaveBeenCalledOnce() + expect(clearQuery).toHaveBeenCalledOnce() + expect(onItemClick).not.toHaveBeenCalled() + await waitFor(() => { + expect(warn).toHaveBeenCalledWith( + 'Ignored stale suggestion menu query cleanup:', + expect.any(RangeError), + ) + }) + warn.mockRestore() + }) +})