{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "cell-grid",
  "title": "Cell Grid",
  "description": "Cell Grid from the Get IT Done design system.",
  "dependencies": [],
  "registryDependencies": [
    "https://zero-design.itdone.de/r/utils.json",
    "https://zero-design.itdone.de/r/theme.json"
  ],
  "files": [
    {
      "path": "registry/ui/cell-grid.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\n\nimport { cn } from '@/lib/utils';\n\nconst cellGridColumns = {\n  1: 'grid-cols-1',\n  2: 'grid-cols-1 sm:grid-cols-2',\n  3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',\n  4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',\n} as const;\n\n// Per-breakpoint maps keep every class literal so Tailwind can generate them.\nconst cellGridBase = { 1: 'grid-cols-1', 2: 'grid-cols-2', 3: 'grid-cols-3', 4: 'grid-cols-4' } as const;\nconst cellGridSm = { 1: 'sm:grid-cols-1', 2: 'sm:grid-cols-2', 3: 'sm:grid-cols-3', 4: 'sm:grid-cols-4' } as const;\nconst cellGridMd = { 1: 'md:grid-cols-1', 2: 'md:grid-cols-2', 3: 'md:grid-cols-3', 4: 'md:grid-cols-4' } as const;\nconst cellGridLg = { 1: 'lg:grid-cols-1', 2: 'lg:grid-cols-2', 3: 'lg:grid-cols-3', 4: 'lg:grid-cols-4' } as const;\n\nconst cellGridPadding = { sm: 'p-4', md: 'p-6', lg: 'p-8' } as const;\nconst cellGridPaddingMd = { sm: 'md:p-4', md: 'md:p-6', lg: 'md:p-8' } as const;\nconst cellGridPaddingLg = { sm: 'lg:p-4', md: 'lg:p-6', lg: 'lg:p-8' } as const;\n\n// Hairline colour for frame and cell borders. subtle is the quieter border-subtle role.\nconst cellGridHairline = {\n  default: { frame: 'border-hairline', cell: 'border-hairline' },\n  subtle: { frame: 'border-border-subtle', cell: 'border-border-subtle' },\n} as const;\n\n// Cell fill. none leaves the cell transparent so the page or a parent surface shows through.\nconst cellGridSurface = { background: 'bg-background', card: 'bg-card', none: 'bg-transparent' } as const;\n\nexport type CellGridPadding = keyof typeof cellGridPadding;\nexport type CellGridResponsivePadding = { base?: CellGridPadding; md?: CellGridPadding; lg?: CellGridPadding };\n\nconst resolvePadding = (padding: CellGridPadding | CellGridResponsivePadding) => {\n  if (typeof padding === 'string') return cellGridPadding[padding];\n  const { base = 'md', md, lg } = padding;\n  return cn(cellGridPadding[base], md && cellGridPaddingMd[md], lg && cellGridPaddingLg[lg]);\n};\n\nexport type CellGridColumnCount = keyof typeof cellGridBase;\nexport type CellGridResponsiveColumns = { base?: CellGridColumnCount; sm?: CellGridColumnCount; md?: CellGridColumnCount; lg?: CellGridColumnCount };\n\nconst resolveColumns = (columns: CellGridColumnCount | CellGridResponsiveColumns) => {\n  if (typeof columns === 'number') return cellGridColumns[columns];\n  const { base = 1, sm, md, lg } = columns;\n  return cn(cellGridBase[base], sm && cellGridSm[sm], md && cellGridMd[md], lg && cellGridLg[lg]);\n};\n\nconst CellGridContext = React.createContext<{ comp: 'ul' | 'div'; padding: CellGridPadding | CellGridResponsivePadding; hairline: keyof typeof cellGridHairline; surface: keyof typeof cellGridSurface }>({\n  comp: 'div',\n  padding: 'md',\n  hairline: 'default',\n  surface: 'background',\n});\n\nexport interface CellGridItem {\n  id: string;\n  content: React.ReactNode;\n}\n\nexport interface CellGridProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n  // A number keeps the preset ramp (single column on mobile). An object sets columns per breakpoint, e.g. { base: 2, md: 4 }.\n  columns?: CellGridColumnCount | CellGridResponsiveColumns;\n  // false drops the own rounded frame and border so the grid sits flush in existing page hairlines.\n  framed?: boolean;\n  // Cell padding from spacing tokens. An object sets it per breakpoint, e.g. { base: 'sm', md: 'lg' }.\n  padding?: CellGridPadding | CellGridResponsivePadding;\n  // Hairline colour. subtle uses the quieter border-subtle role for frame and cell borders.\n  hairline?: keyof typeof cellGridHairline;\n  // Cell fill. background is the default, card uses the card surface, none keeps cells transparent.\n  surface?: keyof typeof cellGridSurface;\n  // Data-driven cells. Renders a list. Use `children` with CellGridCell for custom cells.\n  items?: CellGridItem[];\n  children?: React.ReactNode;\n}\n\n// Cells separated by hairlines. The hairlines are cell borders clipped by the frame, so incomplete last rows stay clean.\nconst CellGrid = React.forwardRef<HTMLElement, CellGridProps>(({ className, columns = 3, framed = true, padding = 'md', hairline = 'default', surface = 'background', items, children, ...props }, ref) => {\n  const Comp = items ? 'ul' : 'div';\n  return (\n    <div className={cn('overflow-hidden', framed && cn('rounded-surface border border-solid', cellGridHairline[hairline].frame), className)} ref={ref as React.Ref<HTMLDivElement>} {...(props as React.HTMLAttributes<HTMLDivElement>)}>\n      <CellGridContext.Provider value={{ comp: Comp, padding, hairline, surface }}>\n        <Comp className={cn('-ml-px -mt-px mb-0 mr-0 grid list-none p-0', resolveColumns(columns))}>\n          {items ? items.map((item) => <CellGridCell key={item.id}>{item.content}</CellGridCell>) : children}\n        </Comp>\n      </CellGridContext.Provider>\n    </div>\n  );\n});\nCellGrid.displayName = 'CellGrid';\n\nexport type CellGridCellProps = React.HTMLAttributes<HTMLElement>;\n\nconst CellGridCell = React.forwardRef<HTMLElement, CellGridCellProps>(({ className, ...props }, ref) => {\n  const { comp, padding, hairline, surface } = React.useContext(CellGridContext);\n  const Comp = comp === 'ul' ? 'li' : 'div';\n  return (\n    <Comp\n      ref={ref as React.Ref<HTMLDivElement & HTMLLIElement>}\n      className={cn('flex min-w-0 flex-col gap-2 border-l border-t border-solid text-text-default', cellGridHairline[hairline].cell, cellGridSurface[surface], resolvePadding(padding), className)}\n      {...props}\n    />\n  );\n});\nCellGridCell.displayName = 'CellGridCell';\n\nexport { CellGrid, CellGridCell };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}