{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "customers-table",
  "title": "Customers Table",
  "description": "Accounts ranked by MRR with plan badges, churn-risk indicators and owner avatars.",
  "registryDependencies": [
    "@spectrumui/data-table"
  ],
  "files": [
    {
      "path": "components/spectrumui/blocks/tables/customers-table.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { DataTable, type DataTableColumn } from '@/components/spectrumui/data-table';\n\ntype Risk = 'low' | 'medium' | 'high';\n\ninterface Customer {\n  id: string;\n  company: string;\n  owner: string;\n  avatar: string;\n  plan: 'Enterprise' | 'Scale' | 'Team' | 'Starter';\n  mrr: number;\n  risk: Risk;\n  since: string;\n}\n\nconst CUSTOMERS: Customer[] = [\n  {\n    id: 'c1',\n    company: 'Driftlab',\n    owner: 'Freya Lindgren',\n    avatar: '/avatars/people/01.jpg',\n    plan: 'Enterprise',\n    mrr: 4200,\n    risk: 'low',\n    since: 'Jan 2024',\n  },\n  {\n    id: 'c2',\n    company: 'Keelworks',\n    owner: 'Mateo Alvarez',\n    avatar: '/avatars/people/03.jpg',\n    plan: 'Scale',\n    mrr: 1840,\n    risk: 'low',\n    since: 'Mar 2024',\n  },\n  {\n    id: 'c3',\n    company: 'Lumenshift',\n    owner: 'Aiko Watanabe',\n    avatar: '/avatars/people/06.jpg',\n    plan: 'Scale',\n    mrr: 1420,\n    risk: 'medium',\n    since: 'Nov 2024',\n  },\n  {\n    id: 'c4',\n    company: 'Fernwerk',\n    owner: 'Jonas Keller',\n    avatar: '/avatars/people/09.jpg',\n    plan: 'Team',\n    mrr: 640,\n    risk: 'high',\n    since: 'Feb 2025',\n  },\n  {\n    id: 'c5',\n    company: 'Copperline',\n    owner: 'Zara Osei',\n    avatar: '/avatars/people/12.jpg',\n    plan: 'Team',\n    mrr: 520,\n    risk: 'low',\n    since: 'Jun 2025',\n  },\n  {\n    id: 'c6',\n    company: 'Havenpoint',\n    owner: 'Nils Bakker',\n    avatar: '/avatars/people/13.jpg',\n    plan: 'Starter',\n    mrr: 96,\n    risk: 'medium',\n    since: 'Apr 2026',\n  },\n  {\n    id: 'c7',\n    company: 'Sable & Co',\n    owner: 'Leila Haddad',\n    avatar: '/avatars/people/05.jpg',\n    plan: 'Enterprise',\n    mrr: 3600,\n    risk: 'low',\n    since: 'Sep 2023',\n  },\n];\n\nconst RISK_STYLE: Record<Risk, string> = {\n  low: 'text-emerald-700 dark:text-emerald-300',\n  medium: 'text-amber-700 dark:text-amber-300',\n  high: 'text-rose-700 dark:text-rose-300',\n};\n\nconst RISK_RANK: Record<Risk, number> = { low: 0, medium: 1, high: 2 };\n\nconst money = new Intl.NumberFormat('en-US', {\n  style: 'currency',\n  currency: 'USD',\n  maximumFractionDigits: 0,\n});\n\nconst columns: DataTableColumn<Customer>[] = [\n  {\n    id: 'company',\n    header: 'Customer',\n    sortable: true,\n    value: (row) => row.company,\n    cell: (row) => (\n      <div className=\"flex items-center gap-2.5\">\n        {/* eslint-disable-next-line @next/next/no-img-element */}\n        <img\n          src={row.avatar}\n          alt=\"\"\n          loading=\"lazy\"\n          width={28}\n          height={28}\n          className=\"size-7 shrink-0 rounded-full object-cover outline outline-1 -outline-offset-1 outline-black/10 dark:outline-white/10\"\n        />\n        <span className=\"min-w-0\">\n          <span className=\"block truncate\">{row.company}</span>\n          <span className=\"block truncate text-xs font-normal text-neutral-500 dark:text-neutral-400\">\n            {row.owner}\n          </span>\n        </span>\n      </div>\n    ),\n  },\n  {\n    id: 'plan',\n    header: 'Plan',\n    sortable: true,\n    value: (row) => row.plan,\n    cell: (row) => (\n      <span className=\"inline-flex rounded-full bg-neutral-100 px-2 py-0.5 text-xs font-medium text-neutral-700 ring-1 ring-inset ring-neutral-500/15 dark:bg-neutral-100/10 dark:text-neutral-300 dark:ring-white/15\">\n        {row.plan}\n      </span>\n    ),\n  },\n  {\n    id: 'mrr',\n    header: 'MRR',\n    sortable: true,\n    numeric: true,\n    value: (row) => row.mrr,\n    formatTotal: (sum) => money.format(sum),\n    cell: (row) => (\n      <span className=\"font-medium text-neutral-900 dark:text-neutral-100\">\n        {money.format(row.mrr)}\n      </span>\n    ),\n  },\n  {\n    id: 'risk',\n    header: 'Churn risk',\n    sortable: true,\n    hideBelow: 'sm',\n    value: (row) => RISK_RANK[row.risk],\n    cell: (row) => (\n      <span\n        className={`inline-flex items-center gap-1.5 font-medium capitalize ${RISK_STYLE[row.risk]}`}\n      >\n        <span aria-hidden=\"true\" className=\"size-1.5 rounded-full bg-current\" />\n        {row.risk}\n      </span>\n    ),\n  },\n  { id: 'since', header: 'Since', hideBelow: 'lg', value: (row) => row.since },\n];\n\nexport function CustomersTable({\n  variant = 'Comfortable',\n}: {\n  variant?: 'Comfortable' | 'Compact';\n}) {\n  return (\n    <div className=\"mx-auto w-full max-w-4xl px-4 py-10 sm:px-6\">\n      <DataTable\n        data={CUSTOMERS}\n        columns={columns}\n        rowId={(row) => row.id}\n        rowLabel={(row) => row.company}\n        caption=\"Customers ranked by monthly recurring revenue, with plan and churn risk.\"\n        density={variant === 'Compact' ? 'compact' : 'default'}\n        title=\"Customers\"\n        quickFilter={{ columnId: 'plan', label: 'Filter by plan', getValue: (row) => row.plan }}\n        totals={['mrr']}\n        defaultSort={{ columnId: 'mrr', direction: 'desc' }}\n      />\n    </div>\n  );\n}\n",
      "type": "registry:block",
      "target": "components/spectrumui/blocks/tables/customers-table.tsx"
    }
  ],
  "type": "registry:block"
}
