{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ink/drawer",
  "title": "Drawer",
  "description": "Slide-in panel from any edge",
  "dependencies": [
    "ink"
  ],
  "registryDependencies": [
    "https://termcn.dev/r/ink/interaction.json",
    "https://termcn.dev/r/ink/terminal-style.json",
    "https://termcn.dev/r/ink/use-theme.json",
    "https://termcn.dev/r/ink/use-unicode.json"
  ],
  "files": [
    {
      "path": "registry/ui/drawer.tsx",
      "content": "import { Box, Text } from \"ink\";\nimport { useState } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { FocusScope } from \"@/hooks/use-interaction\";\nimport { useTheme } from \"@/hooks/use-theme\";\nimport { useUnicode } from \"@/hooks/use-unicode\";\nimport { resolveBorderStyle } from \"@/lib/terminal-style\";\n\nexport type DrawerEdge = \"left\" | \"right\" | \"top\" | \"bottom\";\n\nexport interface DrawerProps {\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  isOpen?: boolean;\n  edge?: DrawerEdge;\n  title?: string;\n  children: ReactNode;\n  onClose?: () => void;\n  width?: number;\n  height?: number;\n  initialFocusId?: string;\n  returnFocusId?: string;\n  \"aria-label\"?: string;\n}\n\nexport const Drawer = ({\n  open: controlledOpen,\n  defaultOpen = false,\n  onOpenChange,\n  isOpen,\n  edge = \"right\",\n  title,\n  children,\n  onClose,\n  width = 40,\n  height = 10,\n  initialFocusId,\n  returnFocusId,\n  \"aria-label\": ariaLabel,\n}: DrawerProps) => {\n  const unicode = useUnicode();\n  const theme = useTheme();\n  const [internalOpen, setInternalOpen] = useState(defaultOpen);\n  const open = controlledOpen ?? isOpen ?? internalOpen;\n\n  const close = () => {\n    if (controlledOpen === undefined && isOpen === undefined) {\n      setInternalOpen(false);\n    }\n    onOpenChange?.(false);\n    onClose?.();\n  };\n\n  if (!open) {\n    return null;\n  }\n\n  const isHorizontal = edge === \"left\" || edge === \"right\";\n\n  return (\n    <FocusScope\n      active={open}\n      initialFocusId={initialFocusId}\n      returnFocusId={returnFocusId}\n      onEscapeKey={close}\n    >\n      <Box\n        flexDirection=\"column\"\n        borderStyle={resolveBorderStyle(\"single\", unicode)}\n        borderColor={theme.colors.border}\n        width={isHorizontal ? width : undefined}\n        height={isHorizontal ? undefined : height}\n        paddingX={1}\n        paddingY={0}\n      >\n        <Box justifyContent=\"space-between\" marginBottom={1}>\n          <Text\n            aria-label={ariaLabel ?? `Drawer: ${title ?? edge}`}\n            bold={Boolean(title)}\n            color={theme.colors.primary}\n          >\n            {title ?? \"\"}\n          </Text>\n          <Text aria-hidden color={theme.colors.mutedForeground} dimColor>\n            Esc to close\n          </Text>\n        </Box>\n        <Box flexDirection=\"column\" flexGrow={1}>\n          {children}\n        </Box>\n      </Box>\n    </FocusScope>\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "overlays"
  ],
  "type": "registry:ui"
}