{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "extends": "none",
  "name": "command-menu",
  "title": "command-menu",
  "description": "command-menu",
  "dependencies": [
    "@heroicons/react",
    "react-aria-components",
    "cn"
  ],
  "registryDependencies": [
    "https://intentui.com/r/primitive",
    "https://intentui.com/r/dropdown",
    "https://intentui.com/r/loader",
    "https://intentui.com/r/menu"
  ],
  "files": [
    {
      "path": "src/components/ui/command-menu.tsx",
      "content": "\"use client\"\n\nimport { MagnifyingGlassIcon } from \"@heroicons/react/20/solid\"\nimport { createContext, use, useEffect } from \"react\"\nimport { Autocomplete, type AutocompleteProps, useFilter } from \"react-aria-components/Autocomplete\"\nimport { Button } from \"react-aria-components/Button\"\nimport { Collection } from \"react-aria-components/Collection\"\nimport {\n  type CollectionRenderer,\n  CollectionRendererContext,\n  DefaultCollectionRenderer,\n} from \"react-aria-components/CollectionBuilder\"\nimport { Dialog, OverlayTriggerStateContext } from \"react-aria-components/Dialog\"\nimport { Header } from \"react-aria-components/Header\"\nimport { Input } from \"react-aria-components/Input\"\nimport type { MenuProps, MenuTriggerProps } from \"react-aria-components/Menu\"\nimport { Menu as MenuPrimitive, MenuSection } from \"react-aria-components/Menu\"\nimport type { ModalOverlayProps } from \"react-aria-components/Modal\"\nimport { Modal, ModalContext, ModalOverlay } from \"react-aria-components/Modal\"\nimport { SearchField, type SearchFieldProps } from \"react-aria-components/SearchField\"\nimport { cn } from \"cn\"\nimport { cx } from \"@/lib/primitive\"\nimport { DropdownKeyboard } from \"./dropdown\"\nimport { Loader } from \"./loader\"\nimport { MenuDescription, MenuItem, MenuLabel, type MenuSectionProps, MenuSeparator } from \"./menu\"\n\nexport interface CommandMenuProviderProps {\n  isPending?: boolean\n  escapeButton?: boolean\n}\n\nconst CommandMenuContext = createContext<CommandMenuProviderProps | undefined>(undefined)\n\nconst useCommandMenu = () => {\n  const context = use(CommandMenuContext)\n\n  if (!context) {\n    throw new Error(\"useCommandMenu must be used within a <CommandMenuProvider />\")\n  }\n\n  return context\n}\n\nconst sizes = {\n  xs: \"sm:max-w-xs\",\n  sm: \"sm:max-w-sm\",\n  md: \"sm:max-w-md\",\n  lg: \"sm:max-w-lg\",\n  xl: \"sm:max-w-xl\",\n  \"2xl\": \"sm:max-w-2xl\",\n  \"3xl\": \"sm:max-w-3xl\",\n}\n\nexport interface CommandMenuProps\n  extends AutocompleteProps, MenuTriggerProps, CommandMenuProviderProps {\n  isDismissable?: boolean\n  \"aria-label\"?: string\n  shortcut?: string\n  className?: string\n  size?: keyof typeof sizes\n  overlay?: Pick<ModalOverlayProps, \"className\">\n}\n\nexport function CommandMenu({\n  onOpenChange,\n  className,\n  isDismissable = true,\n  escapeButton = true,\n  isPending,\n  overlay,\n  size = \"lg\",\n  shortcut,\n  ...props\n}: CommandMenuProps) {\n  const { contains } = useFilter({ sensitivity: \"base\" })\n  const filter = (textValue: string, inputValue: string) => contains(textValue, inputValue)\n  useEffect(() => {\n    if (!shortcut) return\n\n    const onKeyDown = (e: KeyboardEvent) => {\n      if (e.key === shortcut && (e.metaKey || e.ctrlKey)) {\n        onOpenChange?.(true)\n      }\n    }\n\n    document.addEventListener(\"keydown\", onKeyDown)\n    return () => document.removeEventListener(\"keydown\", onKeyDown)\n  }, [shortcut, onOpenChange])\n  return (\n    <CommandMenuContext value={{ isPending: isPending, escapeButton: escapeButton }}>\n      <ModalContext value={{ isOpen: props.isOpen, onOpenChange: onOpenChange }}>\n        <ModalOverlay\n          {...props}\n          isDismissable={isDismissable}\n          className={cx(\n            \"fixed inset-0 z-50 h-(--visual-viewport-height,100vh) w-screen overflow-hidden bg-black/15\",\n            \"grid grid-rows-[1fr_auto] justify-items-center text-center sm:grid-rows-[1fr_auto_3fr]\",\n            \"entering:fade-in entering:animate-in entering:duration-300 entering:ease-out\",\n            \"exiting:fade-out exiting:animate-out exiting:ease-in\",\n            overlay?.className\n          )}\n        >\n          <Modal\n            className={cx(\n              \"row-start-2 bg-overlay text-start text-overlay-foreground shadow-lg outline-none ring ring-muted-foreground/15 md:row-start-1 dark:ring-border\",\n              \"max-h-[calc(var(--visual-viewport-height)*0.8)] w-full sm:fixed sm:top-[10%] sm:left-1/2 sm:-translate-x-1/2\",\n              \"rounded-t-2xl md:rounded-xl\",\n              sizes[size],\n              \"entering:slide-in-from-bottom sm:entering:zoom-in-95 sm:entering:slide-in-from-bottom-0 entering:animate-in entering:duration-300 entering:ease-out\",\n              \"exiting:slide-out-to-bottom sm:exiting:zoom-out-95 sm:exiting:slide-out-to-bottom-0 exiting:animate-out exiting:ease-in\",\n              className\n            )}\n          >\n            <Dialog\n              aria-label={props[\"aria-label\"] ?? \"Command Menu\"}\n              className=\"flex max-h-[inherit] flex-col overflow-hidden outline-hidden\"\n            >\n              <Autocomplete filter={filter} {...props} />\n            </Dialog>\n          </Modal>\n        </ModalOverlay>\n      </ModalContext>\n    </CommandMenuContext>\n  )\n}\n\nexport interface CommandMenuSearchProps extends SearchFieldProps {\n  placeholder?: string\n  className?: string\n}\n\nexport function CommandMenuSearch({ className, placeholder, ...props }: CommandMenuSearchProps) {\n  const state = use(OverlayTriggerStateContext)!\n  const { isPending, escapeButton } = useCommandMenu()\n  return (\n    <SearchField\n      aria-label=\"Quick search\"\n      autoFocus\n      className={cx(\"flex w-full items-center px-2.5 py-1\", className)}\n      {...props}\n    >\n      {isPending ? (\n        <Loader className=\"size-4.5\" variant=\"spin\" />\n      ) : (\n        <MagnifyingGlassIcon\n          data-slot=\"command-menu-search-icon\"\n          className=\"size-5 shrink-0 text-muted-foreground\"\n        />\n      )}\n      <Input\n        placeholder={placeholder ?? \"Search...\"}\n        className=\"w-full min-w-0 bg-transparent px-2.5 py-2 text-base text-foreground placeholder-muted-foreground outline-hidden focus:outline-hidden sm:px-2 sm:py-1.5 sm:text-sm [&::-ms-reveal]:hidden [&::-webkit-search-cancel-button]:hidden\"\n      />\n      {escapeButton && (\n        <Button\n          onPress={() => state?.close()}\n          className=\"hidden cursor-default rounded border text-current/90 hover:bg-muted lg:inline lg:px-1.5 lg:py-0.5 lg:text-xs\"\n        >\n          Esc\n        </Button>\n      )}\n    </SearchField>\n  )\n}\n\nexport function CommandMenuList<T extends object>({ className, ...props }: MenuProps<T>) {\n  return (\n    <CollectionRendererContext.Provider value={renderer}>\n      <MenuPrimitive\n        className={cx(\n          \"grid max-h-full flex-1 grid-cols-[auto_1fr] content-start overflow-y-auto border-t p-2 sm:max-h-110 *:[[role=group]]:mb-6 *:[[role=group]]:last:mb-0\",\n          className\n        )}\n        {...props}\n      />\n    </CollectionRendererContext.Provider>\n  )\n}\n\nexport function CommandMenuSection<T extends object>({\n  className,\n  ref,\n  ...props\n}: MenuSectionProps<T>) {\n  return (\n    <MenuSection\n      ref={ref}\n      className={cn(\"col-span-full grid grid-cols-[auto_1fr] content-start gap-y-0.25\", className)}\n      {...props}\n    >\n      {\"label\" in props && (\n        <Header className=\"col-span-full mb-1 block min-w-(--trigger-width) truncate px-2.5 text-muted-foreground text-xs\">\n          {props.label}\n        </Header>\n      )}\n      <Collection items={props.items}>{props.children}</Collection>\n    </MenuSection>\n  )\n}\n\nexport function CommandMenuItem({ className, ...props }: React.ComponentProps<typeof MenuItem>) {\n  const textValue =\n    props.textValue || (typeof props.children === \"string\" ? props.children : undefined)\n  return (\n    <MenuItem\n      {...props}\n      textValue={textValue}\n      className={cx(\"items-center gap-y-0.5\", className)}\n    />\n  )\n}\n\nexport interface CommandMenuDescriptionProps extends React.ComponentProps<typeof MenuDescription> {}\n\nexport function CommandMenuDescription({ className, ...props }: CommandMenuDescriptionProps) {\n  return <MenuDescription className={cn(\"col-start-3 row-start-1 ms-auto\", className)} {...props} />\n}\n\nconst renderer: CollectionRenderer = {\n  CollectionRoot(props) {\n    if (props.collection.size === 0) {\n      return (\n        <div className=\"col-span-full p-4 text-center text-muted-foreground text-sm\">\n          No results found.\n        </div>\n      )\n    }\n    return <DefaultCollectionRenderer.CollectionRoot {...props} />\n  },\n  CollectionBranch: DefaultCollectionRenderer.CollectionBranch,\n}\n\nexport function CommandMenuSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof MenuSeparator>) {\n  return <MenuSeparator className={cn(\"-mx-2\", className)} {...props} />\n}\n\nexport function CommandMenuFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      className={cn(\n        \"col-span-full flex-none border-t px-2 py-1.5 text-muted-foreground text-sm\",\n        \"*:[kbd]:inset-ring *:[kbd]:inset-ring-foreground/10 *:[kbd]:mx-1 *:[kbd]:inline-grid *:[kbd]:h-4 *:[kbd]:min-w-4 *:[kbd]:place-content-center *:[kbd]:rounded-xs *:[kbd]:bg-secondary\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport const CommandMenuLabel = MenuLabel\nexport function CommandMenuShortcut({\n  className,\n  ...props\n}: React.ComponentProps<typeof DropdownKeyboard>) {\n  return (\n    <DropdownKeyboard\n      className={cn(\n        \"gap-0.5 font-sans text-[10.5px] uppercase *:inset-ring *:inset-ring-muted-foreground/20 *:grid *:size-5.5 *:place-content-center *:rounded-xs *:bg-background\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "cssVars": {
    "theme": {
      "color-overlay": "var(--overlay)",
      "color-overlay-foreground": "var(--overlay-foreground)"
    },
    "light": {
      "overlay": "oklch(1 0 0)",
      "overlay-foreground": "oklch(0.141 0.005 285.823)"
    },
    "dark": {
      "overlay": "oklch(0.210 0.006 285.885)",
      "overlay-foreground": "oklch(0.985 0 0)"
    }
  },
  "type": "registry:ui"
}