({
onSelect,
searchQuery,
onMouseDown,
selectedIndex,
setSelectedIndex,
selectedType,
queryItems,
modes,
dynamicSearchResults = [],
commands = [],
})
| 33 | } |
| 34 | |
| 35 | const ContextMenu: React.FC<ContextMenuProps> = ({ |
| 36 | onSelect, |
| 37 | searchQuery, |
| 38 | onMouseDown, |
| 39 | selectedIndex, |
| 40 | setSelectedIndex, |
| 41 | selectedType, |
| 42 | queryItems, |
| 43 | modes, |
| 44 | dynamicSearchResults = [], |
| 45 | commands = [], |
| 46 | }) => { |
| 47 | const [materialIconsBaseUri, setMaterialIconsBaseUri] = useState("") |
| 48 | const menuRef = useRef<HTMLDivElement>(null) |
| 49 | |
| 50 | const filteredOptions = useMemo(() => { |
| 51 | return getContextMenuOptions(searchQuery, selectedType, queryItems, dynamicSearchResults, modes, commands) |
| 52 | }, [searchQuery, selectedType, queryItems, dynamicSearchResults, modes, commands]) |
| 53 | |
| 54 | useEffect(() => { |
| 55 | if (menuRef.current) { |
| 56 | const selectedElement = menuRef.current.children[selectedIndex] as HTMLElement |
| 57 | if (selectedElement) { |
| 58 | const menuRect = menuRef.current.getBoundingClientRect() |
| 59 | const selectedRect = selectedElement.getBoundingClientRect() |
| 60 | |
| 61 | if (selectedRect.bottom > menuRect.bottom) { |
| 62 | menuRef.current.scrollTop += selectedRect.bottom - menuRect.bottom |
| 63 | } else if (selectedRect.top < menuRect.top) { |
| 64 | menuRef.current.scrollTop -= menuRect.top - selectedRect.top |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | }, [selectedIndex]) |
| 69 | |
| 70 | // get the icons base uri on mount |
| 71 | useEffect(() => { |
| 72 | const w = window as any |
| 73 | setMaterialIconsBaseUri(w.MATERIAL_ICONS_BASE_URI) |
| 74 | }, []) |
| 75 | |
| 76 | const renderOptionContent = (option: ContextMenuQueryItem) => { |
| 77 | switch (option.type) { |
| 78 | case ContextMenuOptionType.SectionHeader: |
| 79 | return ( |
| 80 | <span |
| 81 | style={{ |
| 82 | fontWeight: "bold", |
| 83 | fontSize: "0.85em", |
| 84 | opacity: 0.8, |
| 85 | }}> |
| 86 | {option.label} |
| 87 | </span> |
| 88 | ) |
| 89 | case ContextMenuOptionType.Mode: |
| 90 | return ( |
| 91 | <div style={{ display: "flex", flexDirection: "column", gap: "2px" }}> |
| 92 | <div style={{ lineHeight: "1.2" }}> |
nothing calls this directly
no test coverage detected