'use client' import { type PropsWithChildren, type ReactNode, forwardRef } from 'react' import { CommandItem_Shadcn_, cn } from 'ui' import { useCrossCompatRouter } from '../api/hooks/useCrossCompatRouter' import { useQuery } from '../api/hooks/queryHooks' import { useSetCommandMenuOpen } from '../api/hooks/viewHooks' type ICommand = IActionCommand | IRouteCommand interface IBaseCommand { id: string name: string value?: string className?: string forceMount?: boolean badge?: () => ReactNode icon?: () => ReactNode /** * Whether the item should be hidden until searched */ defaultHidden?: boolean /** * Currently unused */ keywords?: string[] /** * Currently unused */ shortcut?: string } interface IActionCommand extends IBaseCommand { action: () => void } interface IRouteCommand extends IBaseCommand { route: `/${string}` | `http${string}` } const isActionCommand = (command: ICommand): command is IActionCommand => 'action' in command const isRouteCommand = (command: ICommand): command is IRouteCommand => 'route' in command const generateCommandClassNames = (isLink: boolean) => cn( 'cursor-default', 'select-none', 'items-center gap-2', 'rounded-md', 'text-sm', 'group', 'py-3', 'text-foreground-light', 'relative', 'flex', isLink ? ` bg-transparent px-2 transition-all outline-none aria-selected:border-overlay aria-selected:bg-selection/90 aria-selected:shadow-sm aria-selected:scale-[100.3%] data-[disabled]:pointer-events-none data-[disabled]:opacity-50` : ` px-2 aria-selected:bg-selection/80 aria-selected:backdrop-filter aria-selected:backdrop-blur-md data-[disabled]:pointer-events-none data-[disabled]:opacity-50 ` ) interface CommandItemProps extends React.ComponentPropsWithoutRef { command: ICommand } const CommandItem = forwardRef< React.ElementRef, PropsWithChildren >(({ children, className, command: _command, ...props }, ref) => { const router = useCrossCompatRouter() const setIsOpen = useSetCommandMenuOpen() const query = useQuery() const command = _command as ICommand // strip the readonly applied from the proxy return ( { command.route.startsWith('http') ? (setIsOpen(false), window.open(command.route, '_blank', 'noreferrer,noopener')) : router.push(command.route) } : () => {} } value={command.forceMount ? `${query} ${command.value}` : command.value} className={cn( generateCommandClassNames(isRouteCommand(command)), className, command.className )} {...props} >
{command.icon?.()} {children}
{command.badge?.()}
) }) CommandItem.displayName = CommandItem_Shadcn_.displayName export { CommandItem, generateCommandClassNames, isActionCommand, isRouteCommand } export type { ICommand }