Skip to content

Commit 4e87349

Browse files
authored
fix: Emoji suggestion slash menu does not display (#984)
* fix #975 * fix: Unexpected show GridSuggestionMenu * feat: add payload state in SuggestionPlugin.ts * feat: rename SuggestionPlugin pluginState
1 parent 1b0828b commit 4e87349

File tree

4 files changed

+42
-16
lines changed

4 files changed

+42
-16
lines changed

packages/core/src/editor/BlockNoteEditor.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,15 +1159,26 @@ export class BlockNoteEditor<
11591159
};
11601160
}
11611161

1162-
public openSuggestionMenu(triggerCharacter: string) {
1162+
public openSuggestionMenu(
1163+
triggerCharacter: string,
1164+
pluginState?: {
1165+
deleteTriggerCharacter?: boolean;
1166+
ignoreQueryLength?: boolean;
1167+
}
1168+
) {
1169+
const tr = this.prosemirrorView.state.tr;
1170+
const transaction =
1171+
pluginState && pluginState.deleteTriggerCharacter
1172+
? tr.insertText(triggerCharacter)
1173+
: tr;
1174+
11631175
this.prosemirrorView.focus();
11641176
this.prosemirrorView.dispatch(
1165-
this.prosemirrorView.state.tr
1166-
.scrollIntoView()
1167-
.setMeta(this.suggestionMenus.plugin, {
1168-
triggerCharacter: triggerCharacter,
1169-
fromUserInput: false,
1170-
})
1177+
transaction.scrollIntoView().setMeta(this.suggestionMenus.plugin, {
1178+
triggerCharacter: triggerCharacter,
1179+
deleteTriggerCharacter: pluginState?.deleteTriggerCharacter || false,
1180+
ignoreQueryLength: pluginState?.ignoreQueryLength || false,
1181+
})
11711182
);
11721183
}
11731184
}

packages/core/src/extensions/SuggestionMenu/SuggestionPlugin.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const findBlock = findParentNode((node) => node.type.name === "blockContainer");
1111

1212
export type SuggestionMenuState = UiElementPosition & {
1313
query: string;
14+
ignoreQueryLength?: boolean;
1415
};
1516

1617
class SuggestionMenuView<
@@ -34,7 +35,10 @@ class SuggestionMenuView<
3435
throw new Error("Attempting to update uninitialized suggestions menu");
3536
}
3637

37-
emitUpdate(menuName, this.state);
38+
emitUpdate(menuName, {
39+
...this.state,
40+
ignoreQueryLength: this.pluginState?.ignoreQueryLength,
41+
});
3842
};
3943

4044
this.rootEl = this.editor._tiptapEditor.view.root;
@@ -120,7 +124,7 @@ class SuggestionMenuView<
120124
.deleteRange({
121125
from:
122126
this.pluginState.queryStartPos! -
123-
(this.pluginState.fromUserInput
127+
(this.pluginState.deleteTriggerCharacter
124128
? this.pluginState.triggerCharacter!.length
125129
: 0),
126130
to: this.editor._tiptapEditor.state.selection.from,
@@ -132,10 +136,11 @@ class SuggestionMenuView<
132136
type SuggestionPluginState =
133137
| {
134138
triggerCharacter: string;
135-
fromUserInput: boolean;
139+
deleteTriggerCharacter: boolean;
136140
queryStartPos: number;
137141
query: string;
138142
decorationId: string;
143+
ignoreQueryLength?: boolean;
139144
}
140145
| undefined;
141146

@@ -194,7 +199,8 @@ export class SuggestionMenuProseMirrorPlugin<
194199
// or null if it should be hidden.
195200
const suggestionPluginTransactionMeta: {
196201
triggerCharacter: string;
197-
fromUserInput?: boolean;
202+
deleteTriggerCharacter?: boolean;
203+
ignoreQueryLength?: boolean;
198204
} | null = transaction.getMeta(suggestionMenuPluginKey);
199205

200206
// Only opens a menu of no menu is already open
@@ -206,11 +212,14 @@ export class SuggestionMenuProseMirrorPlugin<
206212
return {
207213
triggerCharacter:
208214
suggestionPluginTransactionMeta.triggerCharacter,
209-
fromUserInput:
210-
suggestionPluginTransactionMeta.fromUserInput !== false,
215+
deleteTriggerCharacter:
216+
suggestionPluginTransactionMeta.deleteTriggerCharacter !==
217+
false,
211218
queryStartPos: newState.selection.from,
212219
query: "",
213220
decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,
221+
ignoreQueryLength:
222+
suggestionPluginTransactionMeta?.ignoreQueryLength,
214223
};
215224
}
216225

@@ -285,7 +294,7 @@ export class SuggestionMenuProseMirrorPlugin<
285294

286295
// If the menu was opened programmatically by another extension, it may not use a trigger character. In this
287296
// case, the decoration is set on the whole block instead, as the decoration range would otherwise be empty.
288-
if (!suggestionPluginState.fromUserInput) {
297+
if (!suggestionPluginState.deleteTriggerCharacter) {
289298
const blockNode = findBlock(state.selection);
290299
if (blockNode) {
291300
return DecorationSet.create(state.doc, [

packages/core/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,12 @@ export function getDefaultSlashMenuItems<
272272
}
273273

274274
items.push({
275-
onItemClick: () => editor.openSuggestionMenu(":"),
275+
onItemClick: () => {
276+
editor.openSuggestionMenu(":", {
277+
deleteTriggerCharacter: true,
278+
ignoreQueryLength: true,
279+
});
280+
},
276281
key: "emoji",
277282
...editor.dictionary.slash_menu.emoji,
278283
});

packages/react/src/components/SuggestionMenu/GridSuggestionMenu/GridSuggestionMenuController.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ export function GridSuggestionMenuController<
130130
if (
131131
!isMounted ||
132132
!state ||
133-
(minQueryLength &&
133+
(!state?.ignoreQueryLength &&
134+
minQueryLength &&
134135
(state.query.startsWith(" ") || state.query.length < minQueryLength))
135136
) {
136137
return null;

0 commit comments

Comments
 (0)