import { BlockSchema, InlineContentSchema, StyleSchema } from "@blocknote/core"; import { FC, useCallback, useEffect } from "react"; import { useBlockNoteContext } from "../../editor/BlockNoteContext.js"; import { useBlockNoteEditor } from "../../hooks/useBlockNoteEditor.js"; import { useCloseSuggestionMenuNoItems } from "./hooks/useCloseSuggestionMenuNoItems.js"; import { useLoadSuggestionMenuItems } from "./hooks/useLoadSuggestionMenuItems.js"; import { useSuggestionMenuKeyboardNavigation } from "./hooks/useSuggestionMenuKeyboardNavigation.js"; import { SuggestionMenuProps } from "./types.js"; export function SuggestionMenuWrapper(props: { query: string; closeMenu: () => void; clearQuery: () => void; getItems: (query: string) => Promise; onItemClick?: (item: Item) => void; suggestionMenuComponent: FC>; }) { const ctx = useBlockNoteContext(); const setContentEditableProps = ctx!.setContentEditableProps!; const editor = useBlockNoteEditor< BlockSchema, InlineContentSchema, StyleSchema >(); const { getItems, suggestionMenuComponent, query, clearQuery, closeMenu, onItemClick, } = props; const onItemClickCloseMenu = useCallback( (item: Item) => { closeMenu(); clearQuery(); onItemClick?.(item); }, [onItemClick, closeMenu, clearQuery], ); const { items, usedQuery, loadingState } = useLoadSuggestionMenuItems( query, getItems, ); useCloseSuggestionMenuNoItems(items, usedQuery, closeMenu); const { selectedIndex } = useSuggestionMenuKeyboardNavigation( editor, query, items, onItemClickCloseMenu, ); // set basic aria attributes when the menu is open useEffect(() => { setContentEditableProps((p) => ({ ...p, "aria-expanded": true, "aria-controls": "bn-suggestion-menu", })); return () => { setContentEditableProps((p) => ({ ...p, "aria-expanded": false, "aria-controls": undefined, })); }; }, [setContentEditableProps]); // set selected item (activedescendent) attributes when selected item changes useEffect(() => { setContentEditableProps((p) => ({ ...p, "aria-activedescendant": selectedIndex ? "bn-suggestion-menu-item-" + selectedIndex : undefined, })); return () => { setContentEditableProps((p) => ({ ...p, "aria-activedescendant": undefined, })); }; }, [setContentEditableProps, selectedIndex]); const Component = suggestionMenuComponent; return ( ); }