{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "command",
  "title": "Command",
  "description": "Command palette with search, groups, items, shortcuts and a dialog form, built on cmdk.",
  "dependencies": [
    "cmdk@^1.1.1",
    "lucide-react@^1.27.0"
  ],
  "registryDependencies": [
    "@pestoui/dialog",
    "@pestoui/input-group",
    "@pestoui/style",
    "@pestoui/utils"
  ],
  "files": [
    {
      "path": "pestoui/ui/command.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Command as CommandPrimitive } from \"cmdk\"\n\nimport { cn } from \"@/lib/utils\"\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n} from \"@/components/ui/dialog\"\nimport {\n  InputGroup,\n  InputGroupAddon,\n} from \"@/components/ui/input-group\"\nimport { SearchIcon, CheckIcon } from \"lucide-react\"\n\n/* How long the item cascade stays armed after the palette mounts. Covers the\n   longest beat (the capped delay plus one item's own run) with a little slack. */\nconst COMMAND_ENTER_WINDOW = 500\n\nfunction Command({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive>) {\n  /* The cascade below is a \"the palette opened\" cue, and it has to be gated to\n     say only that. Filtering unmounts the items that no longer match and moves\n     the survivors to re-rank them, and both of those restart an enter animation\n     — ungated, every keystroke would re-run the whole cascade. So the window is\n     armed on mount and closed once, and descendants opt in through it. */\n  const [entering, setEntering] = React.useState(true)\n\n  React.useEffect(() => {\n    const id = window.setTimeout(() => setEntering(false), COMMAND_ENTER_WINDOW)\n    return () => window.clearTimeout(id)\n  }, [])\n\n  return (\n    <CommandPrimitive\n      data-slot=\"command\"\n      data-entering={entering ? \"true\" : undefined}\n      className={cn(\n        \"group/command flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-2 text-popover-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandDialog({\n  title = \"Command Palette\",\n  description = \"Search for a command to run...\",\n  children,\n  className,\n  showCloseButton = false,\n  ...props\n}: React.ComponentProps<typeof Dialog> & {\n  title?: string\n  description?: string\n  className?: string\n  showCloseButton?: boolean\n}) {\n  return (\n    <Dialog {...props}>\n      <DialogHeader className=\"sr-only\">\n        <DialogTitle>{title}</DialogTitle>\n        <DialogDescription>{description}</DialogDescription>\n      </DialogHeader>\n      <DialogContent\n        className={cn(\n          \"top-1/3 translate-y-0 overflow-hidden rounded-xl! p-0\",\n          className\n        )}\n        showCloseButton={showCloseButton}\n      >\n        {children}\n      </DialogContent>\n    </Dialog>\n  )\n}\n\nfunction CommandInput({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Input>) {\n  return (\n    <div data-slot=\"command-input-wrapper\" className=\"p-1 pb-2\">\n      <InputGroup className=\"h-12! rounded-[12px]! border-transparent bg-secondary/60 shadow-none! *:data-[slot=input-group-addon]:pl-3!\">\n        <CommandPrimitive.Input\n          data-slot=\"command-input\"\n          className={cn(\n            \"w-full text-body outline-hidden disabled:cursor-not-allowed disabled:opacity-50\",\n            className\n          )}\n          {...props}\n        />\n        <InputGroupAddon>\n          <SearchIcon className=\"size-4 shrink-0 opacity-50\" />\n        </InputGroupAddon>\n      </InputGroup>\n    </div>\n  )\n}\n\nfunction CommandList({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.List>) {\n  return (\n    <CommandPrimitive.List\n      data-slot=\"command-list\"\n      className={cn(\n        \"no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandEmpty({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Empty>) {\n  return (\n    <CommandPrimitive.Empty\n      data-slot=\"command-empty\"\n      className={cn(\n        \"py-8 text-center text-body text-muted-foreground\",\n        /* Only ever an enter: this mounts the moment a search goes cold, and\n           replacing a list of results with a flat line of text is abrupt\n           without one. Ungated on purpose — it should say \"nothing matched\"\n           every time that becomes true, not just on open. */\n        \"animate-in fade-in-0 slide-in-from-top-[3px] anim-base ease-out-expo\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandGroup({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Group>) {\n  return (\n    <CommandPrimitive.Group\n      data-slot=\"command-group\"\n      className={cn(\n        \"overflow-hidden p-1 text-foreground **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction CommandSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Separator>) {\n  return (\n    /* cmdk hard-codes role=\"separator\", and a listbox may own only options\n       and groups — so the rule is decorative here and kept out of the tree. */\n    <CommandPrimitive.Separator\n      data-slot=\"command-separator\"\n      aria-hidden=\"true\"\n      className={cn(\"-mx-1 h-px bg-border\", className)}\n      {...props}\n    />\n  )\n}\n\n/* Highlight tracks the pointer and the arrow keys, so it has to land under the\n   cursor rather than chase it — 75ms is one of the few places in the system\n   where fast beats smooth. */\nconst commandItemHighlight = \"transition-colors duration-instant ease-out-expo\"\n\n/* Rows materialise in sequence, but only inside the window `Command` opens — a\n   palette is a place you arrive at, not a place you watch redraw. Capped at\n   eight beats so a long list cannot turn into a slow wipe; everything past the\n   cap shares the last delay. The delay properties sit outside the gate because\n   they are inert with no animation to delay. Counting restarts inside each\n   group, which is what you want: groups cascade alongside each other, not one\n   after the other. */\nconst commandItemEnter = [\n  \"group-data-[entering=true]/command:animate-in group-data-[entering=true]/command:fade-in-0 group-data-[entering=true]/command:slide-in-from-top-[4px] group-data-[entering=true]/command:blur-in-[3px]\",\n  \"group-data-[entering=true]/command:fill-mode-backwards group-data-[entering=true]/command:anim-base group-data-[entering=true]/command:ease-out-expo\",\n  \"nth-2:[--tw-animation-delay:calc(1*var(--stagger-tight))]\",\n  \"nth-3:[--tw-animation-delay:calc(2*var(--stagger-tight))]\",\n  \"nth-4:[--tw-animation-delay:calc(3*var(--stagger-tight))]\",\n  \"nth-5:[--tw-animation-delay:calc(4*var(--stagger-tight))]\",\n  \"nth-6:[--tw-animation-delay:calc(5*var(--stagger-tight))]\",\n  \"nth-7:[--tw-animation-delay:calc(6*var(--stagger-tight))]\",\n  \"nth-[n+8]:[--tw-animation-delay:calc(7*var(--stagger-tight))]\",\n].join(\" \")\n\nfunction CommandItem({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof CommandPrimitive.Item>) {\n  return (\n    <CommandPrimitive.Item\n      data-slot=\"command-item\"\n      className={cn(\n        \"group/command-item relative flex cursor-default items-center gap-2.5 rounded-[10px] px-2.5 py-2 text-body outline-hidden select-none in-data-[slot=dialog-content]:rounded-[10px]! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-accent data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground\",\n        commandItemHighlight,\n        commandItemEnter,\n        className\n      )}\n      {...props}\n    >\n      {children}\n      {/* Presses in on the press spring, leaves on the shorter tween. */}\n      <CheckIcon className=\"ml-auto scale-90 opacity-0 transition-[opacity,scale] duration-exit ease-out-expo group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:scale-100 group-data-[checked=true]/command-item:opacity-100 group-data-[checked=true]/command-item:duration-spring-press group-data-[checked=true]/command-item:ease-spring-press\" />\n    </CommandPrimitive.Item>\n  )\n}\n\nfunction CommandShortcut({\n  className,\n  ...props\n}: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"command-shortcut\"\n      className={cn(\n        \"ml-auto text-xs tracking-widest text-muted-foreground group-data-selected/command-item:text-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Command,\n  CommandDialog,\n  CommandInput,\n  CommandList,\n  CommandEmpty,\n  CommandGroup,\n  CommandItem,\n  CommandShortcut,\n  CommandSeparator,\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}