fix: ignore stale suggestion menu close
This commit is contained in:
@@ -1,6 +1,33 @@
|
||||
--- a/dist/defaultBlocks-DE5GNdJH.js
|
||||
+++ b/dist/defaultBlocks-DE5GNdJH.js
|
||||
@@ -2761,7 +2761,7 @@
|
||||
@@ -2651,17 +2651,24 @@
|
||||
if (!a && !(o !== void 0 && r !== void 0) && !s)
|
||||
return;
|
||||
if (this.pluginState = s ? o : r, s || !this.editor.isEditable) {
|
||||
- this.state && (this.state.show = !1), this.emitUpdate(this.pluginState.triggerCharacter);
|
||||
+ if (!this.state)
|
||||
+ return;
|
||||
+ this.state.show = !1, this.emitUpdate(this.pluginState.triggerCharacter);
|
||||
return;
|
||||
}
|
||||
const c = (l = this.rootEl) == null ? void 0 : l.querySelector(
|
||||
`[data-decoration-id="${this.pluginState.decorationId}"]`
|
||||
);
|
||||
- this.editor.isEditable && c && (this.state = {
|
||||
+ if (!c) {
|
||||
+ this.state && (this.state.show = !1, this.emitUpdate(this.pluginState.triggerCharacter));
|
||||
+ return;
|
||||
+ }
|
||||
+ this.state = {
|
||||
show: !0,
|
||||
referencePos: c.getBoundingClientRect().toJSON(),
|
||||
query: this.pluginState.query
|
||||
- }, this.emitUpdate(this.pluginState.triggerCharacter));
|
||||
+ }, this.emitUpdate(this.pluginState.triggerCharacter);
|
||||
}
|
||||
destroy() {
|
||||
var t;
|
||||
@@ -2761,7 +2768,7 @@
|
||||
if (a === s) {
|
||||
const c = r.state.doc;
|
||||
for (const l of t) {
|
||||
@@ -53,6 +80,60 @@
|
||||
}
|
||||
function kn(o, e) {
|
||||
const t = [
|
||||
--- a/src/extensions/SuggestionMenu/SuggestionMenu.ts
|
||||
+++ b/src/extensions/SuggestionMenu/SuggestionMenu.ts
|
||||
@@ -83,27 +83,34 @@
|
||||
this.pluginState = stopped ? prev : next;
|
||||
|
||||
if (stopped || !this.editor.isEditable) {
|
||||
- if (this.state) {
|
||||
- this.state.show = false;
|
||||
- }
|
||||
+ if (!this.state) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ this.state.show = false;
|
||||
this.emitUpdate(this.pluginState!.triggerCharacter);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const decorationNode = this.rootEl?.querySelector(
|
||||
`[data-decoration-id="${this.pluginState!.decorationId}"]`,
|
||||
);
|
||||
|
||||
- if (this.editor.isEditable && decorationNode) {
|
||||
- this.state = {
|
||||
- show: true,
|
||||
- referencePos: decorationNode
|
||||
- .getBoundingClientRect()
|
||||
- .toJSON() as DOMRect,
|
||||
- query: this.pluginState!.query,
|
||||
- };
|
||||
-
|
||||
- this.emitUpdate(this.pluginState!.triggerCharacter!);
|
||||
+ if (!decorationNode) {
|
||||
+ if (this.state) {
|
||||
+ this.state.show = false;
|
||||
+ this.emitUpdate(this.pluginState!.triggerCharacter!);
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
}
|
||||
+
|
||||
+ this.state = {
|
||||
+ show: true,
|
||||
+ referencePos: decorationNode
|
||||
+ .getBoundingClientRect()
|
||||
+ .toJSON() as DOMRect,
|
||||
+ query: this.pluginState!.query,
|
||||
+ };
|
||||
+
|
||||
+ this.emitUpdate(this.pluginState!.triggerCharacter!);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
--- a/src/extensions/TableHandles/TableHandles.ts
|
||||
+++ b/src/extensions/TableHandles/TableHandles.ts
|
||||
@@ -572,9 +572,14 @@
|
||||
|
||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -6,7 +6,7 @@ settings:
|
||||
|
||||
patchedDependencies:
|
||||
'@blocknote/core@0.46.2':
|
||||
hash: dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94
|
||||
hash: 3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7
|
||||
path: patches/@blocknote__core@0.46.2.patch
|
||||
'@blocknote/react@0.46.2':
|
||||
hash: e09f7011df33f4ff92c0d3fd8c9060e62f08997d076f3e438e1e82f8c1ab2f76
|
||||
@@ -27,10 +27,10 @@ importers:
|
||||
version: 0.78.0(zod@4.3.6)
|
||||
'@blocknote/code-block':
|
||||
specifier: ^0.46.2
|
||||
version: 0.46.2(@blocknote/core@0.46.2(patch_hash=dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0))
|
||||
version: 0.46.2(@blocknote/core@0.46.2(patch_hash=3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0))
|
||||
'@blocknote/core':
|
||||
specifier: ^0.46.2
|
||||
version: 0.46.2(patch_hash=dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
|
||||
version: 0.46.2(patch_hash=3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
|
||||
'@blocknote/mantine':
|
||||
specifier: ^0.46.2
|
||||
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)
|
||||
@@ -5359,9 +5359,9 @@ snapshots:
|
||||
|
||||
'@bcoe/v8-coverage@1.0.2': {}
|
||||
|
||||
'@blocknote/code-block@0.46.2(@blocknote/core@0.46.2(patch_hash=dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0))':
|
||||
'@blocknote/code-block@0.46.2(@blocknote/core@0.46.2(patch_hash=3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0))':
|
||||
dependencies:
|
||||
'@blocknote/core': 0.46.2(patch_hash=dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
|
||||
'@blocknote/core': 0.46.2(patch_hash=3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
|
||||
'@shikijs/core': 3.23.0
|
||||
'@shikijs/engine-javascript': 3.23.0
|
||||
'@shikijs/langs': 3.23.0
|
||||
@@ -5369,7 +5369,7 @@ snapshots:
|
||||
'@shikijs/themes': 3.23.0
|
||||
'@shikijs/types': 3.22.0
|
||||
|
||||
'@blocknote/core@0.46.2(patch_hash=dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)':
|
||||
'@blocknote/core@0.46.2(patch_hash=3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)':
|
||||
dependencies:
|
||||
'@emoji-mart/data': 1.2.1
|
||||
'@handlewithcare/prosemirror-inputrules': 0.1.4(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.6)
|
||||
@@ -5421,7 +5421,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=dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
|
||||
'@blocknote/core': 0.46.2(patch_hash=3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7)(@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)
|
||||
'@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)
|
||||
@@ -5443,7 +5443,7 @@ snapshots:
|
||||
|
||||
'@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)':
|
||||
dependencies:
|
||||
'@blocknote/core': 0.46.2(patch_hash=dc394d11ab419b36b8d306cbbb6ce39f0722e042b63b2b7d254c7d7f90782e94)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
|
||||
'@blocknote/core': 0.46.2(patch_hash=3ff0414270086514addc1fa21c7cb0d730d141d1d255ac4faca126085ddf35c7)(@types/hast@3.0.4)(highlight.js@11.11.1)(lowlight@3.3.0)
|
||||
'@emoji-mart/data': 1.2.1
|
||||
'@floating-ui/react': 0.27.17(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@floating-ui/utils': 0.2.10
|
||||
|
||||
96
src/lib/blockNoteSuggestionMenu.regression.test.ts
Normal file
96
src/lib/blockNoteSuggestionMenu.regression.test.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { SuggestionMenu } from '@blocknote/core/extensions'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
type SuggestionPluginState = {
|
||||
triggerCharacter: string
|
||||
deleteTriggerCharacter: boolean
|
||||
queryStartPos: () => number
|
||||
query: string
|
||||
decorationId: string
|
||||
ignoreQueryLength?: boolean
|
||||
}
|
||||
|
||||
type SuggestionEditorState = Record<string, SuggestionPluginState | undefined>
|
||||
|
||||
type SuggestionRoot = {
|
||||
addEventListener: (
|
||||
type: string,
|
||||
listener: EventListenerOrEventListenerObject,
|
||||
options?: boolean | AddEventListenerOptions,
|
||||
) => void
|
||||
removeEventListener: (
|
||||
type: string,
|
||||
listener: EventListenerOrEventListenerObject,
|
||||
options?: boolean | EventListenerOptions,
|
||||
) => void
|
||||
querySelector: (selectors: string) => Element | null
|
||||
}
|
||||
|
||||
type SuggestionEditorView = {
|
||||
root: SuggestionRoot
|
||||
state: SuggestionEditorState
|
||||
}
|
||||
|
||||
type SuggestionPluginView = {
|
||||
update: (view: SuggestionEditorView, prevState: SuggestionEditorState) => void
|
||||
}
|
||||
|
||||
type SuggestionMenuPlugin = {
|
||||
spec: {
|
||||
key: { key: string }
|
||||
view: (view: SuggestionEditorView) => SuggestionPluginView
|
||||
}
|
||||
}
|
||||
|
||||
function createSuggestionPlugin() {
|
||||
const extensionFactory = SuggestionMenu() as unknown as (context: {
|
||||
editor: { isEditable: boolean }
|
||||
}) => { prosemirrorPlugins: SuggestionMenuPlugin[] }
|
||||
|
||||
return extensionFactory({ editor: { isEditable: true } }).prosemirrorPlugins[0]
|
||||
}
|
||||
|
||||
function createState(
|
||||
plugin: SuggestionMenuPlugin,
|
||||
pluginState?: SuggestionPluginState,
|
||||
): SuggestionEditorState {
|
||||
return {
|
||||
[plugin.spec.key.key]: pluginState,
|
||||
}
|
||||
}
|
||||
|
||||
function createPluginState(): SuggestionPluginState {
|
||||
return {
|
||||
triggerCharacter: '/',
|
||||
deleteTriggerCharacter: true,
|
||||
queryStartPos: () => 1,
|
||||
query: '',
|
||||
decorationId: 'missing-decoration',
|
||||
}
|
||||
}
|
||||
|
||||
function createEditorView(state: SuggestionEditorState): SuggestionEditorView {
|
||||
return {
|
||||
root: {
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn(),
|
||||
querySelector: vi.fn(() => null),
|
||||
},
|
||||
state,
|
||||
}
|
||||
}
|
||||
|
||||
describe('patched BlockNote suggestion menu lifecycle', () => {
|
||||
it('closes a suggestion menu before its decoration mounts without throwing', () => {
|
||||
const plugin = createSuggestionPlugin()
|
||||
const inactiveState = createState(plugin)
|
||||
const activeState = createState(plugin, createPluginState())
|
||||
const editorView = createEditorView(activeState)
|
||||
const pluginView = plugin.spec.view(editorView)
|
||||
|
||||
expect(() => pluginView.update(editorView, inactiveState)).not.toThrow()
|
||||
|
||||
editorView.state = inactiveState
|
||||
expect(() => pluginView.update(editorView, activeState)).not.toThrow()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user