{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "api-keys-table",
  "title": "API Keys Table",
  "description": "Key management with masked secrets in mono, scope chips, usage counts and a revoke action.",
  "registryDependencies": [
    "@spectrumui/data-table"
  ],
  "files": [
    {
      "path": "components/spectrumui/blocks/tables/api-keys-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 IconDelete(props: IconProps) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n      <path\n        transform=\"translate(3, 2)\"\n        d=\"M15.939,6.697 C16.138,6.697 16.319,6.784 16.462,6.931 C16.596,7.088 16.663,7.283 16.643,7.489 C16.643,7.557 16.11,14.297 15.806,17.134 C15.615,18.875 14.493,19.932 12.809,19.961 C11.515,19.99 10.25,20 9.004,20 C7.681,20 6.388,19.99 5.132,19.961 C3.505,19.922 2.382,18.846 2.201,17.134 C1.888,14.287 1.364,7.557 1.355,7.489 C1.345,7.283 1.411,7.088 1.545,6.931 C1.678,6.784 1.868,6.697 2.069,6.697 L15.939,6.697 Z M11.065,0 C11.949,0 12.738,0.617 12.967,1.497 L12.967,1.497 L13.13,2.227 C13.263,2.822 13.778,3.243 14.371,3.243 L14.371,3.243 L17.287,3.243 C17.676,3.243 18,3.566 18,3.977 L18,3.977 L18,4.357 C18,4.758 17.676,5.091 17.287,5.091 L17.287,5.091 L0.714,5.091 C0.324,5.091 0,4.758 0,4.357 L0,4.357 L0,3.977 C0,3.566 0.324,3.243 0.714,3.243 L0.714,3.243 L3.63,3.243 C4.222,3.243 4.737,2.822 4.871,2.228 L4.871,2.228 L5.023,1.546 C5.261,0.617 6.041,0 6.935,0 L6.935,0 Z\"\n      />\n    </svg>\n  );\n}\n\ninterface ApiKey {\n  id: string;\n  name: string;\n  prefix: string;\n  secret: string;\n  scopes: string[];\n  lastUsed: string;\n  calls: number;\n}\n\nconst KEYS: ApiKey[] = [\n  {\n    id: 'k1',\n    name: 'Production',\n    prefix: 'sk_live_',\n    secret: '4tR8wq2Zx9Lm',\n    scopes: ['read', 'write'],\n    lastUsed: '2 min ago',\n    calls: 84210,\n  },\n  {\n    id: 'k2',\n    name: 'Staging',\n    prefix: 'sk_test_',\n    secret: 'Jd83kPq0Nv1c',\n    scopes: ['read', 'write'],\n    lastUsed: '3 hours ago',\n    calls: 6120,\n  },\n  {\n    id: 'k3',\n    name: 'CI runner',\n    prefix: 'sk_test_',\n    secret: 'Vc29mTx7Qw4e',\n    scopes: ['read'],\n    lastUsed: 'Yesterday',\n    calls: 1408,\n  },\n  {\n    id: 'k4',\n    name: 'Analytics export',\n    prefix: 'sk_live_',\n    secret: 'Bn61sYh3Kf8u',\n    scopes: ['read'],\n    lastUsed: '4 days ago',\n    calls: 340,\n  },\n  {\n    id: 'k5',\n    name: 'Zapier',\n    prefix: 'sk_live_',\n    secret: 'Gp05dRw6Mz2a',\n    scopes: ['read'],\n    lastUsed: 'Aug 22',\n    calls: 92,\n  },\n];\n\nfunction buildColumns(revealed: boolean): DataTableColumn<ApiKey>[] {\n  return [\n    { id: 'name', header: 'Name', sortable: true, value: (row) => row.name },\n    {\n      id: 'secret',\n      header: 'Key',\n      value: (row) => row.prefix + row.secret,\n      cell: (row) => (\n        <code className=\"rounded-[6px] bg-neutral-100 px-1.5 py-0.5 font-mono text-xs text-neutral-700 dark:bg-neutral-100/10 dark:text-neutral-300\">\n          {row.prefix}\n          {revealed ? row.secret : '••••••••••••'}\n        </code>\n      ),\n    },\n    {\n      id: 'scopes',\n      header: 'Scopes',\n      hideBelow: 'sm',\n      value: (row) => row.scopes.join(' '),\n      cell: (row) => (\n        <span className=\"flex gap-1\">\n          {row.scopes.map((scope) => (\n            <span\n              key={scope}\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              {scope}\n            </span>\n          ))}\n        </span>\n      ),\n    },\n    { id: 'lastUsed', header: 'Last used', hideBelow: 'md', value: (row) => row.lastUsed },\n    {\n      id: 'calls',\n      header: 'Calls (30d)',\n      sortable: true,\n      numeric: true,\n      value: (row) => row.calls,\n      cell: (row) => row.calls.toLocaleString('en-US'),\n    },\n  ];\n}\n\nexport function ApiKeysTable({ variant = 'Masked' }: { variant?: 'Masked' | 'Revealed' }) {\n  const columns = React.useMemo(() => buildColumns(variant === 'Revealed'), [variant]);\n  const [keys, setKeys] = React.useState(KEYS);\n  const removed = KEYS.length - keys.length;\n\n  return (\n    <div className=\"mx-auto w-full max-w-4xl px-4 py-10 sm:px-6\">\n      <DataTable\n        data={keys}\n        columns={columns}\n        rowId={(row) => row.id}\n        rowLabel={(row) => `${row.name} key`}\n        caption=\"API keys with masked secrets, scopes and recent usage.\"\n        variant=\"panel\"\n        density=\"compact\"\n        title=\"API keys\"\n        onDelete={(ids) => setKeys((current) => current.filter((row) => !ids.includes(row.id)))}\n        toolbar={\n          removed > 0 ? (\n            <button\n              type=\"button\"\n              onClick={() => setKeys(KEYS)}\n              className=\"rounded-full px-2 text-sm font-medium text-neutral-500 underline underline-offset-2 transition-colors duration-100 ease-out hover:text-neutral-900 focus-visible:ring-1 focus-visible:ring-neutral-950 focus-visible:outline-hidden dark:text-neutral-400 dark:hover:text-neutral-100 dark:focus-visible:ring-neutral-300\"\n            >\n              Restore {removed}\n            </button>\n          ) : null\n        }\n        rowActions={(row, { remove }) => (\n          <button\n            type=\"button\"\n            onClick={remove}\n            aria-label={`Revoke ${row.name} key`}\n            className=\"grid size-8 place-items-center rounded-xl text-neutral-400 transition-colors duration-100 ease-out hover:bg-rose-50 hover:text-rose-700 focus-visible:ring-1 focus-visible:ring-neutral-950 focus-visible:outline-hidden dark:hover:bg-rose-400/10 dark:hover:text-rose-300 dark:focus-visible:ring-neutral-300\"\n          >\n            <IconDelete className=\"size-4\" />\n          </button>\n        )}\n      />\n    </div>\n  );\n}\n",
      "type": "registry:block",
      "target": "components/spectrumui/blocks/tables/api-keys-table.tsx"
    }
  ],
  "type": "registry:block"
}
