{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "inventory-table",
  "title": "Inventory Table",
  "description": "Stock management with SKU tiles, capacity meters that change color at thresholds and status labels.",
  "registryDependencies": [
    "@spectrumui/data-table"
  ],
  "files": [
    {
      "path": "components/spectrumui/blocks/tables/inventory-table.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { DataTable, type DataTableColumn } from '@/components/spectrumui/data-table';\n\ntype IconProps = React.SVGProps<SVGSVGElement>;\n\nfunction IconBag(props: IconProps) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n      <path\n        transform=\"translate(2.5, 2)\"\n        d=\"M9.51,0 C11.929,0 13.889,2 13.918,4.47 L13.918,4.47 L14.123,4.47 C16.815,4.47 19,6.72 19,9.48 L19,9.48 L19,15 C19,17.76 16.815,20 14.123,20 L14.123,20 L4.877,20 C2.185,20 0,17.76 0,15 L0,15 L0,9.48 C0,6.72 2.185,4.47 4.877,4.47 L4.877,4.47 L5.082,4.47 C5.101,3.27 5.56,2.15 6.389,1.31 C7.227,0.46 8.3,0.03 9.51,0 Z M13.206,5.66 C12.806,5.66 12.475,6 12.475,6.41 L12.475,6.41 L12.475,7.57 C12.475,7.98 12.806,8.32 13.206,8.32 C13.616,8.32 13.938,7.98 13.938,7.57 L13.938,7.57 L13.938,6.41 C13.938,6 13.616,5.66 13.206,5.66 Z M5.706,5.66 C5.306,5.66 4.974,6 4.974,6.41 L4.974,6.41 L4.974,7.57 C4.974,7.98 5.306,8.32 5.706,8.32 C6.116,8.32 6.437,7.98 6.437,7.57 L6.437,7.57 L6.437,6.41 C6.437,6 6.116,5.66 5.706,5.66 Z M9.51,1.5 C8.759,1.5 7.978,1.81 7.413,2.38 C6.867,2.94 6.564,3.68 6.545,4.47 L6.545,4.47 L12.455,4.47 C12.426,2.83 11.119,1.5 9.51,1.5 Z\"\n      />\n    </svg>\n  );\n}\n\ntype Stock = 'in' | 'low' | 'out';\n\ninterface Product {\n  id: string;\n  name: string;\n  sku: string;\n  category: string;\n  stock: number;\n  capacity: number;\n  price: number;\n}\n\nconst PRODUCTS: Product[] = [\n  {\n    id: 'p1',\n    name: 'Field jacket — moss',\n    sku: 'FJ-MOSS-M',\n    category: 'Outerwear',\n    stock: 184,\n    capacity: 200,\n    price: 148,\n  },\n  {\n    id: 'p2',\n    name: 'Wool overshirt — charcoal',\n    sku: 'WO-CHAR-S',\n    category: 'Outerwear',\n    stock: 32,\n    capacity: 150,\n    price: 189,\n  },\n  {\n    id: 'p3',\n    name: 'Down parka — ink',\n    sku: 'DP-INK-M',\n    category: 'Outerwear',\n    stock: 0,\n    capacity: 120,\n    price: 420,\n  },\n  {\n    id: 'p4',\n    name: 'Trail socks — 3 pack',\n    sku: 'TS-3PK',\n    category: 'Accessories',\n    stock: 412,\n    capacity: 500,\n    price: 44,\n  },\n  {\n    id: 'p5',\n    name: 'Beanie — rust',\n    sku: 'BN-RUST',\n    category: 'Accessories',\n    stock: 18,\n    capacity: 240,\n    price: 38,\n  },\n  {\n    id: 'p6',\n    name: 'Canvas tote — natural',\n    sku: 'CT-NAT',\n    category: 'Bags',\n    stock: 96,\n    capacity: 160,\n    price: 89,\n  },\n];\n\nfunction stockState(row: Product): Stock {\n  if (row.stock === 0) return 'out';\n  if (row.stock / row.capacity < 0.2) return 'low';\n  return 'in';\n}\n\nconst STOCK_META: Record<Stock, { label: string; text: string; bar: string }> = {\n  in: {\n    label: 'In stock',\n    text: 'text-neutral-500 dark:text-neutral-400',\n    bar: 'bg-emerald-600 dark:bg-emerald-400',\n  },\n  low: {\n    label: 'Low stock',\n    text: 'text-amber-700 dark:text-amber-300',\n    bar: 'bg-amber-500 dark:bg-amber-400',\n  },\n  out: {\n    label: 'Out of stock',\n    text: 'text-rose-700 dark:text-rose-300',\n    bar: 'bg-rose-500 dark:bg-rose-400',\n  },\n};\n\nconst money = new Intl.NumberFormat('en-US', {\n  style: 'currency',\n  currency: 'USD',\n  maximumFractionDigits: 0,\n});\n\nconst columns: DataTableColumn<Product>[] = [\n  {\n    id: 'name',\n    header: 'Product',\n    sortable: true,\n    value: (row) => row.name,\n    cell: (row) => (\n      <span className=\"flex items-center gap-2.5\">\n        <span\n          aria-hidden=\"true\"\n          className=\"grid size-8 shrink-0 place-items-center rounded-[10px] bg-neutral-100 text-neutral-500 dark:bg-neutral-800 dark:text-neutral-400\"\n        >\n          <IconBag className=\"size-4\" />\n        </span>\n        <span className=\"min-w-0\">\n          <span className=\"block truncate\">{row.name}</span>\n          <span className=\"block font-mono text-xs font-normal text-neutral-500 dark:text-neutral-400\">\n            {row.sku}\n          </span>\n        </span>\n      </span>\n    ),\n  },\n  {\n    id: 'category',\n    header: 'Category',\n    sortable: true,\n    hideBelow: 'md',\n    value: (row) => row.category,\n  },\n  {\n    id: 'stock',\n    header: 'Stock',\n    sortable: true,\n    numeric: true,\n    value: (row) => row.stock,\n    formatTotal: (sum) => `${Math.round(sum).toLocaleString('en-US')} units`,\n    cell: (row) => {\n      const state = stockState(row);\n      return (\n        <span className=\"flex items-center justify-end gap-2\">\n          <span\n            aria-hidden=\"true\"\n            className=\"h-1.5 w-16 overflow-hidden rounded-full bg-neutral-100 dark:bg-neutral-800\"\n          >\n            <span\n              className={`block h-full rounded-full ${STOCK_META[state].bar}`}\n              style={{ width: `${Math.min(100, (row.stock / row.capacity) * 100)}%` }}\n            />\n          </span>\n          <span className=\"w-8 tabular-nums\">{row.stock}</span>\n        </span>\n      );\n    },\n  },\n  {\n    id: 'state',\n    header: 'Status',\n    sortable: true,\n    hideBelow: 'sm',\n    value: (row) => stockState(row),\n    cell: (row) => {\n      const state = stockState(row);\n      return (\n        <span className={`inline-flex items-center gap-1.5 font-medium ${STOCK_META[state].text}`}>\n          <span aria-hidden=\"true\" className=\"size-1.5 rounded-full bg-current\" />\n          {STOCK_META[state].label}\n        </span>\n      );\n    },\n  },\n  {\n    id: 'price',\n    header: 'Price',\n    sortable: true,\n    numeric: true,\n    value: (row) => row.price,\n    cell: (row) => money.format(row.price),\n  },\n];\n\nexport function InventoryTable({\n  variant = 'Comfortable',\n}: {\n  variant?: 'Comfortable' | 'Bordered';\n}) {\n  return (\n    <div className=\"mx-auto w-full max-w-4xl px-4 py-10 sm:px-6\">\n      <DataTable\n        data={PRODUCTS}\n        columns={columns}\n        rowId={(row) => row.id}\n        rowLabel={(row) => row.name}\n        caption=\"Inventory levels with stock bars, thresholds and pricing.\"\n        variant={variant === 'Bordered' ? 'bordered' : 'default'}\n        title=\"Inventory\"\n        totals={['stock']}\n        searchable\n        searchPlaceholder=\"Search products\"\n        defaultSort={{ columnId: 'stock', direction: 'asc' }}\n      />\n    </div>\n  );\n}\n",
      "type": "registry:block",
      "target": "components/spectrumui/blocks/tables/inventory-table.tsx"
    }
  ],
  "type": "registry:block"
}
