import { Command, useCommandRegistry, } from '@/features/ide-react/context/command-registry-context' import { DropdownDivider, DropdownHeader, } from '@/features/ui/components/bootstrap-5/dropdown-menu' import { MenuBarDropdown, NestedMenuBarDropdown, } from '@/shared/components/menu-bar/menu-bar-dropdown' import { MenuBarOption } from '@/shared/components/menu-bar/menu-bar-option' import { Fragment, useCallback, useMemo } from 'react' type CommandId = string type TaggedCommand = Command & { type: 'command' } type Entry = T | GroupStructure type GroupStructure = { id: string title: string children: Array> } export type MenuSectionStructure = { title?: string id: string children: Array> } export type MenuStructure = Array> const CommandDropdown = ({ menu, title, id, }: { menu: MenuStructure title: string id: string }) => { const { registry } = useCommandRegistry() const populatedSections = useMemo( () => menu .map(section => populateSectionOrGroup(section, registry)) .filter(x => x.children.length > 0), [menu, registry] ) if (populatedSections.length === 0) { return null } return ( {populatedSections.map((section, index) => { return ( {index > 0 && } {section.title && {section.title}} {section.children.map(child => ( ))} ) })} ) } export const CommandSection = ({ section: sectionStructure, }: { section: MenuSectionStructure }) => { const { registry } = useCommandRegistry() const section = populateSectionOrGroup(sectionStructure, registry) if (section.children.length === 0) { return null } return ( <> {section.title && {section.title}} {section.children.map(child => ( ))} ) } const CommandDropdownChild = ({ item }: { item: Entry }) => { const onClickHandler = useCallback(() => { if (isTaggedCommand(item)) { item.handler?.({ location: 'menu-bar' }) } }, [item]) if (isTaggedCommand(item)) { return ( ) } else { return ( {item.children.map(subChild => { return })} ) } } export default CommandDropdown function populateSectionOrGroup< T extends { children: Array> }, >( section: T, registry: Map ): Omit & { children: Array> } { const { children, ...rest } = section return { ...rest, children: children .map(child => { if (typeof child !== 'string') { const populatedChild = populateSectionOrGroup(child, registry) if (populatedChild.children.length === 0) { // Skip empty groups return undefined } return populatedChild } const command = registry.get(child) if (command) { return { ...command, type: 'command' as const } } return undefined }) .filter(x => x !== undefined), } } function isTaggedCommand(item: Entry): item is TaggedCommand { return 'type' in item && item.type === 'command' }