{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "feature-flags-table",
  "title": "Feature Flags Table",
  "description": "Flag management with env chips, rollout meters and a live spring-animated switch per row.",
  "registryDependencies": [
    "@spectrumui/data-table"
  ],
  "files": [
    {
      "path": "components/spectrumui/blocks/tables/feature-flags-table.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { motion } from 'motion/react';\nimport { DataTable, type DataTableColumn } from '@/components/spectrumui/data-table';\n\ninterface Flag {\n  id: string;\n  name: string;\n  key: string;\n  envs: string[];\n  rollout: number;\n  updated: string;\n  defaultOn: boolean;\n}\n\nconst FLAGS: Flag[] = [\n  {\n    id: 'f1',\n    name: 'New onboarding flow',\n    key: 'onboarding_v3',\n    envs: ['Production', 'Staging'],\n    rollout: 100,\n    updated: '2 hours ago',\n    defaultOn: true,\n  },\n  {\n    id: 'f2',\n    name: 'Usage-based billing',\n    key: 'metered_billing',\n    envs: ['Staging'],\n    rollout: 25,\n    updated: 'Yesterday',\n    defaultOn: true,\n  },\n  {\n    id: 'f3',\n    name: 'AI summaries',\n    key: 'ai_summaries',\n    envs: ['Production', 'Staging'],\n    rollout: 50,\n    updated: '3 days ago',\n    defaultOn: true,\n  },\n  {\n    id: 'f4',\n    name: 'Command palette v2',\n    key: 'cmdk_v2',\n    envs: ['Staging'],\n    rollout: 10,\n    updated: 'Sep 4',\n    defaultOn: false,\n  },\n  {\n    id: 'f5',\n    name: 'Legacy export path',\n    key: 'legacy_export',\n    envs: ['Production'],\n    rollout: 100,\n    updated: 'Aug 18',\n    defaultOn: false,\n  },\n];\n\nfunction Toggle({\n  on,\n  onChange,\n  label,\n}: {\n  on: boolean;\n  onChange: (next: boolean) => void;\n  label: string;\n}) {\n  return (\n    <button\n      type=\"button\"\n      role=\"switch\"\n      aria-checked={on}\n      aria-label={label}\n      onClick={() => onChange(!on)}\n      className={`relative h-5 w-9 rounded-full transition-colors duration-150 ease-out focus-visible:ring-1 focus-visible:ring-neutral-950 focus-visible:ring-offset-2 focus-visible:outline-hidden dark:focus-visible:ring-neutral-300 ${\n        on ? 'bg-neutral-900 dark:bg-neutral-100' : 'bg-neutral-200 dark:bg-neutral-700'\n      }`}\n    >\n      <motion.span\n        aria-hidden=\"true\"\n        className=\"absolute start-0.5 top-0.5 size-4 rounded-full bg-white shadow-sm dark:bg-neutral-900\"\n        initial={false}\n        animate={{ x: on ? 16 : 0 }}\n        transition={{ type: 'spring', stiffness: 500, damping: 28 }}\n      />\n    </button>\n  );\n}\n\nexport function FeatureFlagsTable({\n  variant = 'Comfortable',\n}: {\n  variant?: 'Comfortable' | 'Compact';\n}) {\n  const [enabled, setEnabled] = React.useState<Record<string, boolean>>(() =>\n    Object.fromEntries(FLAGS.map((flag) => [flag.id, flag.defaultOn])),\n  );\n\n  const columns = React.useMemo<DataTableColumn<Flag>[]>(\n    () => [\n      {\n        id: 'name',\n        header: 'Flag',\n        sortable: true,\n        value: (row) => row.name,\n        cell: (row) => (\n          <span className=\"block 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.key}\n            </span>\n          </span>\n        ),\n      },\n      {\n        id: 'envs',\n        header: 'Environments',\n        hideBelow: 'sm',\n        value: (row) => row.envs.join(' '),\n        cell: (row) => (\n          <span className=\"flex gap-1\">\n            {row.envs.map((env) => (\n              <span\n                key={env}\n                className=\"inline-flex rounded-full bg-neutral-100 px-2 py-0.5 text-xs font-medium text-neutral-600 ring-1 ring-inset ring-neutral-500/15 dark:bg-neutral-100/10 dark:text-neutral-300 dark:ring-white/15\"\n              >\n                {env}\n              </span>\n            ))}\n          </span>\n        ),\n      },\n      {\n        id: 'rollout',\n        header: 'Rollout',\n        sortable: true,\n        numeric: true,\n        value: (row) => row.rollout,\n        cell: (row) => (\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 bg-neutral-900 dark:bg-neutral-100\"\n                style={{ width: `${row.rollout}%` }}\n              />\n            </span>\n            <span className=\"w-9 tabular-nums\">{row.rollout}%</span>\n          </span>\n        ),\n      },\n      { id: 'updated', header: 'Updated', hideBelow: 'md', value: (row) => row.updated },\n      {\n        id: 'toggle',\n        header: 'Enabled',\n        align: 'end',\n        value: (row) => (enabled[row.id] ? 'on' : 'off'),\n        cell: (row) => (\n          <Toggle\n            on={enabled[row.id]}\n            onChange={(next) => setEnabled((state) => ({ ...state, [row.id]: next }))}\n            label={`${enabled[row.id] ? 'Disable' : 'Enable'} ${row.name}`}\n          />\n        ),\n      },\n    ],\n    [enabled],\n  );\n\n  return (\n    <div className=\"mx-auto w-full max-w-4xl px-4 py-10 sm:px-6\">\n      <DataTable\n        data={FLAGS}\n        columns={columns}\n        rowId={(row) => row.id}\n        rowLabel={(row) => row.name}\n        caption=\"Feature flags with environment coverage, rollout percentage and a live toggle.\"\n        density={variant === 'Compact' ? 'compact' : 'default'}\n        title=\"Feature flags\"\n      />\n    </div>\n  );\n}\n",
      "type": "registry:block",
      "target": "components/spectrumui/blocks/tables/feature-flags-table.tsx"
    }
  ],
  "type": "registry:block"
}
