{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "author": "Lopifi (https://lopifi.com)",
  "categories": [
    "system-states",
    "finance",
    "accounting"
  ],
  "dependencies": [
    "vaul"
  ],
  "description": "Vaul, configured. The mobile primary overlay.",
  "files": [
    {
      "content": "\"use client\";\n\nimport type * as React from \"react\";\nimport { Drawer } from \"vaul\";\nimport { cn } from \"@/lib/ledger/cn\";\nimport { XMarkIcon } from \"@/components/ledger/icons\";\n\nexport interface SheetProps {\n  children: React.ReactNode;\n  description?: string;\n  footer?: React.ReactNode;\n  onOpenChange: (open: boolean) => void;\n  open: boolean;\n  side?: \"bottom\" | \"right\";\n  /** Partial heights. The first is the resting snap. */\n  snapPoints?: (number | string)[];\n  title: string;\n}\n\n/**\n * The primary overlay on phone — a sheet enters from the thumb zone, where\n * a centred dialog puts its actions in the middle of the screen.\n *\n * 320ms ease-drawer in, 225ms out, 1:1 finger tracking with velocity-aware\n * dismissal handled by Vaul. The footer pads to the safe area.\n */\nexport function Sheet({\n  open,\n  onOpenChange,\n  title,\n  description,\n  children,\n  footer,\n  snapPoints,\n  side = \"bottom\",\n}: SheetProps) {\n  return (\n    <Drawer.Root direction={side} onOpenChange={onOpenChange} open={open} snapPoints={snapPoints}>\n      <Drawer.Portal>\n        <Drawer.Overlay className=\"fixed inset-0 z-overlay bg-[oklch(0.21_0.02_265/0.4)]\" />\n        <Drawer.Content\n          className={cn(\n            \"fixed z-dialog flex flex-col bg-surface-raised outline-none\",\n            side === \"bottom\"\n              ? \"inset-x-0 bottom-0 max-h-[92dvh] rounded-t-xl border-t border-border\"\n              : \"inset-y-0 right-0 h-dvh w-full max-w-[480px] border-l border-border\",\n          )}\n          style={{ overscrollBehavior: \"contain\" }}\n        >\n          {side === \"bottom\" ? (\n            <div\n              aria-hidden=\"true\"\n              className=\"mx-auto mt-3 h-1 w-10 shrink-0 rounded-full bg-border-strong\"\n            />\n          ) : null}\n          <div className=\"flex items-start justify-between gap-4 px-6 pb-4 pt-5\">\n            <div>\n              <Drawer.Title className=\"text-title-md font-medium\">{title}</Drawer.Title>\n              {description ? (\n                <Drawer.Description className=\"mt-1 text-body text-text-secondary\">\n                  {description}\n                </Drawer.Description>\n              ) : (\n                <Drawer.Description className=\"sr-only\">{title}</Drawer.Description>\n              )}\n            </div>\n            <button\n              aria-label=\"Close\"\n              className=\"press grid size-8 place-items-center rounded-sm text-text-tertiary hover:bg-surface-hover\"\n              onClick={() => onOpenChange(false)}\n              type=\"button\"\n            >\n              <XMarkIcon aria-hidden=\"true\" className=\"size-4\" />\n            </button>\n          </div>\n          <div className=\"flex-1 overflow-y-auto px-6 pb-6 scrollbar-thin\">{children}</div>\n          {footer ? (\n            <div\n              className=\"border-t border-border-subtle px-6 pt-4\"\n              style={{ paddingBottom: \"max(24px, env(safe-area-inset-bottom))\" }}\n            >\n              {footer}\n            </div>\n          ) : null}\n        </Drawer.Content>\n      </Drawer.Portal>\n    </Drawer.Root>\n  );\n}\n",
      "path": "components/ledger/sheet.tsx",
      "target": "components/ledger/sheet.tsx",
      "type": "registry:component"
    }
  ],
  "name": "sheet",
  "registryDependencies": [
    "@lopifi/theme",
    "@lopifi/cn",
    "@lopifi/icons"
  ],
  "title": "Sheet",
  "type": "registry:component"
}
