{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-table-7",
  "type": "registry:component",
  "title": "DataTable 7",
  "description": "DataTable 7. A component for displaying and managing tabular data.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "dropdown-menu",
    "table"
  ],
  "files": [
    {
      "path": "components/watermelon/data-table-7.tsx",
      "type": "registry:component",
      "content": "'use client'\n\nimport type { CSSProperties } from 'react'\nimport { useMemo, useState } from 'react'\n\nimport { ArrowLeftFromLineIcon, ArrowRightFromLineIcon, EllipsisIcon, PinOffIcon } from 'lucide-react'\n\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger\n} from '@/components/base-ui/dropdown-menu'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/base-ui/table'\n\ntype Discontinued = 'no' | 'yes'\n\ntype ProductRow = {\n  category: string\n  discontinued: Discontinued\n  price: number\n  productId: number\n  productName: string\n  stockQuantity: number\n  supplier: string\n}\n\ntype ColumnKey = 'category' | 'discontinued' | 'price' | 'productName' | 'stockQuantity' | 'supplier'\n\ntype PinSide = false | 'left' | 'right'\n\ntype ColumnConfig = {\n  key: ColumnKey\n  label: string\n  width: number\n}\n\ntype PinnedState = Record<ColumnKey, PinSide>\n\nconst data: readonly ProductRow[] = [\n  {\n    productId: 1,\n    productName: 'Apple iPhone 14',\n    category: 'Smartphones',\n    stockQuantity: 4550,\n    price: 1500,\n    supplier: 'Dixon Electronics',\n    discontinued: 'no'\n  },\n  {\n    productId: 2,\n    productName: 'Metal Frame Table',\n    category: 'Furniture',\n    stockQuantity: 150,\n    price: 540,\n    supplier: 'Milton Furniture',\n    discontinued: 'no'\n  },\n  {\n    productId: 3,\n    productName: 'Xiaomi A Series',\n    category: 'Electronics',\n    stockQuantity: 1500,\n    price: 2200,\n    supplier: 'Xiaomi Electronics',\n    discontinued: 'yes'\n  },\n  {\n    productId: 4,\n    productName: 'RC Monster Truck',\n    category: 'Toys',\n    stockQuantity: 10500,\n    price: 250,\n    supplier: 'Lego Toys',\n    discontinued: 'no'\n  },\n  {\n    productId: 5,\n    productName: 'Glass Water Bottle',\n    category: 'Kitchenware',\n    stockQuantity: 5503,\n    price: 69,\n    supplier: 'Kitchen Essentials',\n    discontinued: 'no'\n  },\n  {\n    productId: 6,\n    productName: 'BenQ Monitor 24',\n    category: 'Electronics',\n    stockQuantity: 600,\n    price: 1000,\n    supplier: 'BenQ Electronics',\n    discontinued: 'yes'\n  }\n] as const\n\nconst columns: readonly ColumnConfig[] = [\n  { key: 'productName', label: 'Product Name', width: 220 },\n  { key: 'category', label: 'Category', width: 150 },\n  { key: 'stockQuantity', label: 'Stock Quantity', width: 150 },\n  { key: 'price', label: 'Price', width: 120 },\n  { key: 'supplier', label: 'Supplier', width: 190 },\n  { key: 'discontinued', label: 'Discontinued', width: 130 }\n] as const\n\nconst defaultPinnedState: PinnedState = {\n  productName: false,\n  category: false,\n  stockQuantity: false,\n  price: false,\n  supplier: false,\n  discontinued: false\n}\n\nconst formatCurrency = (price: number) =>\n  new Intl.NumberFormat('en-US', {\n    style: 'currency',\n    currency: 'USD'\n  }).format(price)\n\nconst DataTable7 = () => {\n  const [pinned, setPinned] = useState<PinnedState>(defaultPinnedState)\n\n  const leftPinnedColumns = useMemo(\n    () => columns.filter((column) => pinned[column.key] === 'left'),\n    [pinned]\n  )\n\n  const rightPinnedColumns = useMemo(\n    () => columns.filter((column) => pinned[column.key] === 'right'),\n    [pinned]\n  )\n\n  const leftOffsets = useMemo(() => {\n    return leftPinnedColumns\n      .reduce(\n        (acc, column) => {\n          acc.offsets[column.key] = acc.offset\n          return {\n            offsets: acc.offsets,\n            offset: acc.offset + column.width\n          }\n        },\n        { offsets: {} as Record<ColumnKey, number>, offset: 0 }\n      )\n      .offsets\n  }, [leftPinnedColumns])\n\n  const rightOffsets = useMemo(() => {\n    return [...rightPinnedColumns]\n      .reverse()\n      .reduce(\n        (acc, column) => {\n          acc.offsets[column.key] = acc.offset\n          return {\n            offsets: acc.offsets,\n            offset: acc.offset + column.width\n          }\n        },\n        { offsets: {} as Record<ColumnKey, number>, offset: 0 }\n      )\n      .offsets\n  }, [rightPinnedColumns])\n\n  const setPin = (key: ColumnKey, side: PinSide) => {\n    setPinned((current) => ({\n      ...current,\n      [key]: side\n    }))\n  }\n\n  const getPinnedStyles = (column: ColumnConfig): CSSProperties => {\n    const pinSide = pinned[column.key]\n\n    if (pinSide === 'left') {\n      return {\n        position: 'sticky',\n        left: leftOffsets[column.key],\n        width: column.width,\n        minWidth: column.width,\n        maxWidth: column.width,\n        zIndex: 2\n      }\n    }\n\n    if (pinSide === 'right') {\n      return {\n        position: 'sticky',\n        right: rightOffsets[column.key],\n        width: column.width,\n        minWidth: column.width,\n        maxWidth: column.width,\n        zIndex: 2\n      }\n    }\n\n    return {\n      width: column.width,\n      minWidth: column.width,\n      maxWidth: column.width\n    }\n  }\n\n  const renderCell = (row: ProductRow, key: ColumnKey) => {\n    switch (key) {\n      case 'productName':\n        return <div className='font-medium'>{row.productName}</div>\n      case 'category':\n        return row.category\n      case 'stockQuantity':\n        return row.stockQuantity.toLocaleString('en-US')\n      case 'price':\n        return formatCurrency(row.price)\n      case 'supplier':\n        return row.supplier\n      case 'discontinued':\n        return <span className='capitalize'>{row.discontinued}</span>\n    }\n  }\n\n  return (\n    <div className='w-60 sm:w-100 md:w-120 lg:w-160 2xl:w-240 mx-auto'>\n      <div className='overflow-hidden rounded-xl border border-border/60 bg-background shadow-sm'>\n        <Table className='border-separate border-spacing-0 table-fixed w-60 sm:w-100 md:w-120 lg:w-160 2xl:w-240 mx-auto'>\n          <TableHeader>\n            <TableRow className='[&>th]:border-b [&>th]:border-border/60'>\n              {columns.map((column) => {\n                const pinSide = pinned[column.key]\n\n                return (\n                  <TableHead\n                    key={column.key}\n                    className='relative h-12 bg-muted/20 text-[13px] font-medium tracking-[0.08em] text-muted-foreground'\n                    style={getPinnedStyles(column)}\n                    data-pinned={pinSide || undefined}\n                  >\n                    <div className='flex items-center justify-between gap-2'>\n                      <span className='truncate'>{column.label}</span>\n\n                      {pinSide ? (\n                        <button\n                          type='button'\n                          className='inline-flex size-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-background hover:text-foreground'\n                          onClick={() => setPin(column.key, false)}\n                          aria-label={`Unpin ${column.label} column`}\n                          title={`Unpin ${column.label} column`}\n                        >\n                          <PinOffIcon className='size-4 opacity-70' aria-hidden='true' />\n                        </button>\n                      ) : (\n                        <DropdownMenu>\n                          <DropdownMenuTrigger className='inline-flex size-7 items-center justify-center rounded-md text-muted-foreground outline-none transition-colors hover:bg-background hover:text-foreground'>\n                            <EllipsisIcon className='size-4 opacity-70' aria-hidden='true' />\n                          </DropdownMenuTrigger>\n                          <DropdownMenuContent align='end'>\n                            <DropdownMenuItem onClick={() => setPin(column.key, 'left')}>\n                              <ArrowLeftFromLineIcon className='size-4 opacity-70' aria-hidden='true' />\n                              Stick to left\n                            </DropdownMenuItem>\n                            <DropdownMenuItem onClick={() => setPin(column.key, 'right')}>\n                              <ArrowRightFromLineIcon className='size-4 opacity-70' aria-hidden='true' />\n                              Stick to right\n                            </DropdownMenuItem>\n                          </DropdownMenuContent>\n                        </DropdownMenu>\n                      )}\n                    </div>\n                  </TableHead>\n                )\n              })}\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            {data.map((row) => (\n              <TableRow key={row.productId} className='[&>td]:border-b [&>td]:border-border/60 hover:bg-muted/10'>\n                {columns.map((column) => {\n                  const pinSide = pinned[column.key]\n\n                  return (\n                    <TableCell\n                      key={column.key}\n                      className='truncate bg-background py-3.5'\n                      style={getPinnedStyles(column)}\n                      data-pinned={pinSide || undefined}\n                    >\n                      {renderCell(row, column.key)}\n                    </TableCell>\n                  )\n                })}\n              </TableRow>\n            ))}\n          </TableBody>\n        </Table>\n      </div>\n    </div>\n  )\n}\n\nexport default DataTable7\n"
    }
  ]
}
