{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "shortcut-cheatsheet",
  "title": "Shortcut Cheatsheet",
  "description": "A searchable overlay that lists keyboard shortcuts by section, opened with a key.",
  "registryDependencies": [
    "dialog",
    "input",
    "utils",
    "@drift-ui/shortcut-recorder",
    "@drift-ui/use-controllable-state"
  ],
  "files": [
    {
      "path": "registry/default/ui/shortcut-cheatsheet.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/registry/default/lib/utils\"\nimport {\n  filterSections,\n  matchesTrigger,\n  type CheatsheetSection,\n} from \"@/registry/default/lib/shortcut-cheatsheet\"\nimport { useControllableState } from \"@/registry/default/hooks/use-controllable-state\"\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n} from \"@/registry/default/ui/dialog\"\nimport { Input } from \"@/registry/default/ui/input\"\nimport { ShortcutKeys } from \"@/registry/default/ui/shortcut-recorder\"\n\nfunction ShortcutCheatsheet({\n  sections,\n  trigger = \"?\",\n  open,\n  defaultOpen = false,\n  onOpenChange,\n  className,\n  ...props\n}: React.ComponentProps<typeof DialogContent> & {\n  sections: CheatsheetSection[]\n  trigger?: string\n  open?: boolean\n  defaultOpen?: boolean\n  onOpenChange?: (open: boolean) => void\n}) {\n  const { value: isOpen, setValue: setIsOpen } = useControllableState({\n    value: open,\n    defaultValue: defaultOpen,\n    onChange: onOpenChange,\n  })\n\n  React.useEffect(() => {\n    function handleKeyDown(event: KeyboardEvent) {\n      const isMac = /Mac|iPhone|iPad|iPod/.test(navigator.userAgent)\n      if (event.defaultPrevented || !matchesTrigger(event, trigger, isMac))\n        return\n      event.preventDefault()\n      setIsOpen(true)\n    }\n\n    window.addEventListener(\"keydown\", handleKeyDown)\n    return () => window.removeEventListener(\"keydown\", handleKeyDown)\n  }, [trigger, setIsOpen])\n\n  React.useEffect(() => {\n    if (!isOpen) return\n    const opener = document.activeElement\n    return () => {\n      if (opener instanceof HTMLElement) opener.focus({ preventScroll: true })\n    }\n  }, [isOpen])\n\n  return (\n    <Dialog open={isOpen} onOpenChange={setIsOpen}>\n      <DialogContent\n        data-slot=\"shortcut-cheatsheet\"\n        className={cn(\"sm:max-w-xl\", className)}\n        {...props}\n      >\n        <DialogHeader>\n          <DialogTitle>Keyboard shortcuts</DialogTitle>\n          <DialogDescription className=\"sr-only\">\n            Search by action or section. Press Escape to close.\n          </DialogDescription>\n        </DialogHeader>\n        <ShortcutCheatsheetResults sections={sections} />\n      </DialogContent>\n    </Dialog>\n  )\n}\n\nfunction ShortcutCheatsheetResults({\n  sections,\n}: {\n  sections: CheatsheetSection[]\n}) {\n  const [query, setQuery] = React.useState(\"\")\n  const visibleSections = filterSections(sections, query)\n  const count = visibleSections.reduce(\n    (total, section) => total + section.shortcuts.length,\n    0\n  )\n\n  return (\n    <>\n      <Input\n        type=\"search\"\n        aria-label=\"Search shortcuts\"\n        placeholder=\"Search shortcuts\"\n        value={query}\n        onChange={(event) => setQuery(event.target.value)}\n        onKeyDown={(event) => {\n          if (event.repeat && !query) event.preventDefault()\n        }}\n      />\n      <div\n        role=\"region\"\n        aria-label=\"Shortcuts\"\n        tabIndex={0}\n        data-slot=\"shortcut-cheatsheet-sections\"\n        className=\"flex max-h-[60vh] flex-col gap-5 overflow-y-auto rounded-md outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\"\n      >\n        {visibleSections.map((section, sectionIndex) => (\n          <section key={`${section.title}-${sectionIndex}`}>\n            <h3 className=\"mb-1 text-xs font-medium text-muted-foreground\">\n              {section.title}\n            </h3>\n            <dl>\n              {section.shortcuts.map((shortcut, shortcutIndex) => (\n                <div\n                  key={`${shortcut.label}-${shortcutIndex}`}\n                  className=\"flex items-center justify-between gap-4 py-1 text-sm\"\n                >\n                  <dt>{shortcut.label}</dt>\n                  <dd>\n                    <ShortcutKeys shortcut={shortcut.keys} />\n                  </dd>\n                </div>\n              ))}\n            </dl>\n          </section>\n        ))}\n        <p\n          role=\"status\"\n          className={cn(\n            \"py-6 text-center text-sm text-muted-foreground\",\n            count > 0 && \"sr-only\"\n          )}\n        >\n          {count === 0 && \"No shortcuts found\"}\n          {count === 1 && \"1 shortcut\"}\n          {count > 1 && `${count} shortcuts`}\n        </p>\n      </div>\n    </>\n  )\n}\n\nexport { ShortcutCheatsheet }\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/default/lib/shortcut-cheatsheet.ts",
      "content": "import { matchesShortcut } from \"@/registry/default/lib/shortcut\"\n\nexport type CheatsheetShortcut = {\n  keys: string\n  label: string\n}\n\nexport type CheatsheetSection = {\n  title: string\n  shortcuts: CheatsheetShortcut[]\n}\n\nconst NON_TEXT_INPUT_TYPES = new Set([\n  \"button\",\n  \"checkbox\",\n  \"color\",\n  \"file\",\n  \"image\",\n  \"radio\",\n  \"range\",\n  \"reset\",\n  \"submit\",\n])\n\nexport function filterSections(sections: CheatsheetSection[], query: string) {\n  const needle = query.trim().toLowerCase()\n  if (!needle) return sections\n\n  return sections.flatMap((section) => {\n    if (section.title.toLowerCase().includes(needle)) return [section]\n    const shortcuts = section.shortcuts.filter(({ label }) =>\n      label.toLowerCase().includes(needle)\n    )\n    return shortcuts.length > 0 ? [{ ...section, shortcuts }] : []\n  })\n}\n\nfunction isTextEntry(target: EventTarget | null) {\n  if (target instanceof HTMLInputElement)\n    return !NON_TEXT_INPUT_TYPES.has(target.type)\n  if (!(target instanceof Element)) return false\n  if (target.closest(\"select,textarea\")) return true\n  const editable = target.closest(\"[contenteditable]\")\n  return (\n    editable !== null && editable.getAttribute(\"contenteditable\") !== \"false\"\n  )\n}\n\nfunction isCharacterTrigger(trigger: string) {\n  return trigger.length === 1 && trigger === trigger.toLowerCase()\n}\n\nfunction producesCharacter(event: KeyboardEvent, isMac: boolean) {\n  if (event.metaKey) return false\n  if (event.getModifierState(\"AltGraph\")) return true\n  return !event.ctrlKey && (!event.altKey || isMac)\n}\n\nexport function matchesTrigger(\n  event: KeyboardEvent,\n  trigger: string,\n  isMac: boolean\n) {\n  const [target = event.target] = event.composedPath()\n  if (!trigger || isTextEntry(target)) return false\n  if (matchesShortcut(event, trigger, isMac)) return true\n  return (\n    isCharacterTrigger(trigger) &&\n    event.key === trigger &&\n    producesCharacter(event, isMac)\n  )\n}\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:ui"
}