{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "bucket-column",
  "title": "Bucket column",
  "description": "A single inventory bucket: a collapsible labeled header with a capacity counter, an optional equipped slot, and the stored items in an ItemGrid.",
  "registryDependencies": [
    "@engram/cn",
    "@engram/collapsible-section",
    "@engram/item-grid",
    "@engram/tokens"
  ],
  "files": [
    {
      "path": "src/components/bucket-column.tsx",
      "content": "\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn.js\";\nimport { CollapsibleSection } from \"./collapsible-section.js\";\nimport { ItemGrid } from \"./item-grid.js\";\n\nexport interface BucketColumnProps {\n  /** Bucket name (e.g. \"Kinetic Weapons\", \"Helmet\"). */\n  title: ReactNode;\n  /** The equipped item, rendered above the stored grid. */\n  equipped?: ReactNode;\n  /** Stored item count (the filled slots). */\n  count?: number;\n  /** Bucket capacity — shown as `count / capacity`; turns \"bad\" when over. */\n  capacity?: number;\n  /** Whether the column collapses. Default true. */\n  collapsible?: boolean;\n  /** Initial open state when collapsible. Default true. */\n  defaultOpen?: boolean;\n  /** Grid columns (passthrough to {@link ItemGrid}). */\n  columns?: number;\n  /** Responsive min tile width (passthrough to {@link ItemGrid}). */\n  min?: number;\n  /** Grid gap (passthrough to {@link ItemGrid}). */\n  gap?: number;\n  /** The stored item tiles. */\n  children?: ReactNode;\n  className?: string;\n}\n\nfunction Capacity({ count, capacity }: { count?: number; capacity?: number }) {\n  if (count == null) return null;\n  const over = capacity != null && count > capacity;\n  return (\n    <span className={cn(\"tabular-nums\", over && \"text-engram-bad\")}>\n      {count}\n      {capacity != null ? ` / ${capacity}` : null}\n    </span>\n  );\n}\n\n/**\n * A single inventory bucket: a collapsible labeled header with a capacity\n * counter, an optional equipped slot, and the stored items in an {@link ItemGrid}.\n * The column unit assembled into vault/character/postmaster views — pass item\n * tiles as `children`; the consumer decides what's equipped vs stored.\n */\nexport function BucketColumn({\n  title,\n  equipped,\n  count,\n  capacity,\n  collapsible = true,\n  defaultOpen = true,\n  columns,\n  min,\n  gap,\n  children,\n  className,\n}: BucketColumnProps) {\n  const body = (\n    <div className=\"flex flex-col gap-2\">\n      {equipped ? <div className=\"flex\">{equipped}</div> : null}\n      {children ? (\n        <ItemGrid columns={columns} min={min} gap={gap}>\n          {children}\n        </ItemGrid>\n      ) : null}\n    </div>\n  );\n\n  if (!collapsible) {\n    return (\n      <div className={cn(\"flex flex-col\", className)}>\n        <div className=\"flex items-center gap-2 py-1.5 text-engram-muted\">\n          <span className=\"font-engram-display font-semibold text-[11px] uppercase tracking-engram-label\">\n            {title}\n          </span>\n          <span className=\"ml-auto font-engram-display text-[11px] text-engram-faint\">\n            <Capacity count={count} capacity={capacity} />\n          </span>\n        </div>\n        <div className=\"pt-1\">{body}</div>\n      </div>\n    );\n  }\n\n  return (\n    <CollapsibleSection\n      title={title}\n      count={<Capacity count={count} capacity={capacity} />}\n      defaultOpen={defaultOpen}\n      className={className}\n    >\n      {body}\n    </CollapsibleSection>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/engram/bucket-column.tsx"
    }
  ],
  "meta": {
    "level": "component"
  },
  "docs": "Extend without forking: edit the copied source, use `asChild` (Radix Slot) to change the rendered element, pass the typed `annotations` prop for curated data (verdict/tags/per-plug), or use slot / render-prop props for arbitrary content. Requires the @engram/tokens theme (--engram-* CSS variables).",
  "categories": [
    "inventory"
  ],
  "type": "registry:component"
}