{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notification-matrix",
  "title": "Notification Matrix",
  "description": "Notification Matrix from the Get IT Done design system.",
  "dependencies": [],
  "registryDependencies": [
    "https://zero-design.itdone.de/r/chip.json",
    "https://zero-design.itdone.de/r/labels-context.json",
    "https://zero-design.itdone.de/r/switch.json",
    "https://zero-design.itdone.de/r/table.json",
    "https://zero-design.itdone.de/r/utils.json",
    "https://zero-design.itdone.de/r/theme.json"
  ],
  "files": [
    {
      "path": "registry/ui/notification-matrix.tsx",
      "content": "'use client';\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { Chip } from '@/components/ui/chip';\nimport { Switch } from '@/components/ui/switch';\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';\nimport { useLabels, usePreset } from '@/components/ui/labels-context';\n\nexport interface NotificationMatrixProps extends HTMLAttributes<HTMLTableElement> {\n  'aria-label': string;\n  // Channel columns, e.g. In-app, Email.\n  columns: string[];\n  rowHeaderLabel?: ReactNode;\n  // NotificationMatrixRow elements.\n  children?: ReactNode;\n}\n\n// The selected state uses the prototype row tint instead of the neutral table selection.\nconst selectedRow = 'bg-background-selected-row hover:bg-background-selected-row active:bg-background-selected-row [--table-pin-tint:theme(colors.background-selected-row)]';\nconst selectedCell = 'bg-background-selected-row';\n\n// Notification preferences: events as rows, channels as columns, one switch per cell.\nconst NotificationMatrix = forwardRef<HTMLTableElement, NotificationMatrixProps>(\n  ({ className, columns, rowHeaderLabel: rowHeaderLabelProp, children, ...props }, ref) => {\n    const l = useLabels();\n    const rowHeaderLabel = rowHeaderLabelProp ?? l.eventColumn;\n    // Zero: the header row is a muted band like the DataGrid head.\n    const zero = usePreset() === 'zero';\n    return (\n    <Table ref={ref} stickyHeader={false} headerTone={zero ? 'muted' : 'default'} className={className} {...props}>\n      <TableHeader>\n        <TableRow>\n          <TableHead>{rowHeaderLabel}</TableHead>\n          {columns.map((c) => (\n            <TableHead key={c} className=\"text-center\">\n              {c}\n            </TableHead>\n          ))}\n        </TableRow>\n      </TableHeader>\n      <TableBody>{children}</TableBody>\n    </Table>\n  );\n  },\n);\nNotificationMatrix.displayName = 'NotificationMatrix';\n\nexport interface NotificationMatrixRowProps extends Omit<HTMLAttributes<HTMLTableRowElement>, 'children'> {\n  label: ReactNode;\n  description?: ReactNode;\n  // Adds a \"Required\" chip. Combine with readOnly cells for always on events.\n  required?: boolean;\n  requiredLabel?: string;\n  // Selected row: brand container tint (bg-background-selected-row) with AA secondary text.\n  selected?: boolean;\n  // NotificationMatrixCell elements, one per column.\n  children?: ReactNode;\n}\n\nconst NotificationMatrixRow = forwardRef<HTMLTableRowElement, NotificationMatrixRowProps>(\n  ({ className, label, description, required, requiredLabel: requiredLabelProp, selected, children, ...props }, ref) => {\n    const l = useLabels();\n    const requiredLabel = requiredLabelProp ?? l.required;\n    return (\n    <TableRow ref={ref} selected={selected} className={cn(selected && selectedRow, className)} {...props}>\n      <TableCell role=\"rowheader\" className=\"font-normal\">\n        <div className=\"flex items-center gap-2\">\n          <div className=\"flex min-w-0 flex-col\">\n            <span className=\"typography-ui-medium truncate\">{label}</span>\n            {description ? <span className=\"typography-text-extra-small truncate text-muted-foreground [[data-state=selected]_&]:text-text-subtle-on-selected\">{description}</span> : null}\n          </div>\n          {required ? <Chip variant=\"warning\" size=\"small\" label={requiredLabel} /> : null}\n        </div>\n      </TableCell>\n      {children}\n    </TableRow>\n  );\n  },\n);\nNotificationMatrixRow.displayName = 'NotificationMatrixRow';\n\nexport interface NotificationMatrixCellProps {\n  // Accessible name, e.g. \"Quote accepted, Email\".\n  label: string;\n  checked?: boolean;\n  defaultChecked?: boolean;\n  onCheckedChange?: (checked: boolean) => void;\n  // Fixed value that the user cannot change (required events). Stays focusable and announced.\n  readOnly?: boolean;\n  disabled?: boolean;\n  // Standalone selected wash for the cell, same role as a selected row.\n  selected?: boolean;\n  className?: string;\n}\n\nconst NotificationMatrixCell = forwardRef<HTMLButtonElement, NotificationMatrixCellProps>(\n  ({ label, checked, defaultChecked, onCheckedChange, readOnly, disabled, selected, className }, ref) => (\n    <TableCell selected={selected} className={cn('text-center', selected && selectedCell, className)}>\n      <Switch\n        ref={ref}\n        size=\"sm\"\n        aria-label={label}\n        readOnly={readOnly}\n        checked={checked}\n        defaultChecked={defaultChecked}\n        disabled={disabled}\n        onCheckedChange={onCheckedChange}\n      />\n    </TableCell>\n  ),\n);\nNotificationMatrixCell.displayName = 'NotificationMatrixCell';\n\nexport { NotificationMatrix, NotificationMatrixCell, NotificationMatrixRow };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}