|
6 | 6 | filterSuggestionItems,
|
7 | 7 | } from "@blocknote/core";
|
8 | 8 | import { flip, offset, size } from "@floating-ui/react";
|
9 |
| -import { FC } from "react"; |
| 9 | +import { FC, useCallback, useMemo } from "react"; |
10 | 10 |
|
11 | 11 | import { useBlockNoteEditor } from "../../hooks/useBlockNoteEditor";
|
12 | 12 | import { useUIElementPositioning } from "../../hooks/useUIElementPositioning";
|
@@ -55,26 +55,42 @@ export function SuggestionMenuController<
|
55 | 55 |
|
56 | 56 | const { triggerCharacter, suggestionMenuComponent } = props;
|
57 | 57 |
|
58 |
| - let { onItemClick, getItems } = props; |
| 58 | + const { onItemClick, getItems } = props; |
59 | 59 |
|
60 |
| - if (!onItemClick) { |
61 |
| - onItemClick = (item: ItemType<GetItemsType>) => { |
62 |
| - item.onItemClick(editor); |
63 |
| - }; |
64 |
| - } |
| 60 | + const onItemClickOrDefault = useMemo(() => { |
| 61 | + return ( |
| 62 | + onItemClick || |
| 63 | + ((item: ItemType<GetItemsType>) => { |
| 64 | + item.onItemClick(editor); |
| 65 | + }) |
| 66 | + ); |
| 67 | + }, [editor, onItemClick]); |
| 68 | + |
| 69 | + const getItemsOrDefault = useMemo(() => { |
| 70 | + return ( |
| 71 | + getItems || |
| 72 | + ((async (query: string) => |
| 73 | + filterSuggestionItems( |
| 74 | + getDefaultReactSlashMenuItems(editor), |
| 75 | + query |
| 76 | + )) as any as typeof getItems) |
| 77 | + ); |
| 78 | + }, [editor, getItems])!; |
65 | 79 |
|
66 | 80 | const callbacks = {
|
67 | 81 | closeMenu: editor.suggestionMenus.closeMenu,
|
68 | 82 | clearQuery: editor.suggestionMenus.clearQuery,
|
69 | 83 | };
|
70 | 84 |
|
71 |
| - const state = useUIPluginState( |
72 |
| - (callback: (state: SuggestionMenuState) => void) => |
73 |
| - editor.suggestionMenus.onUpdate.bind(editor.suggestionMenus)( |
74 |
| - triggerCharacter, |
75 |
| - callback |
76 |
| - ) |
| 85 | + const cb = useCallback( |
| 86 | + (callback: (state: SuggestionMenuState) => void) => { |
| 87 | + return editor.suggestionMenus.onUpdate(triggerCharacter, callback); |
| 88 | + }, |
| 89 | + [editor.suggestionMenus, triggerCharacter] |
77 | 90 | );
|
| 91 | + |
| 92 | + const state = useUIPluginState(cb); |
| 93 | + |
78 | 94 | const { isMounted, ref, style, getFloatingProps } = useUIElementPositioning(
|
79 | 95 | state?.show || false,
|
80 | 96 | state?.referencePos || null,
|
@@ -106,23 +122,15 @@ export function SuggestionMenuController<
|
106 | 122 | return null;
|
107 | 123 | }
|
108 | 124 |
|
109 |
| - if (!getItems) { |
110 |
| - getItems = (async (query: string) => |
111 |
| - filterSuggestionItems( |
112 |
| - getDefaultReactSlashMenuItems(editor), |
113 |
| - query |
114 |
| - )) as any; |
115 |
| - } |
116 |
| - |
117 | 125 | return (
|
118 | 126 | <div ref={ref} style={style} {...getFloatingProps()}>
|
119 | 127 | <SuggestionMenuWrapper
|
120 | 128 | query={state.query}
|
121 | 129 | closeMenu={callbacks.closeMenu}
|
122 | 130 | clearQuery={callbacks.clearQuery}
|
123 |
| - getItems={getItems!} |
| 131 | + getItems={getItemsOrDefault} |
124 | 132 | suggestionMenuComponent={suggestionMenuComponent || SuggestionMenu}
|
125 |
| - onItemClick={onItemClick} |
| 133 | + onItemClick={onItemClickOrDefault} |
126 | 134 | />
|
127 | 135 | </div>
|
128 | 136 | );
|
|
0 commit comments