{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "top-pages-table",
  "title": "Top Pages Table",
  "description": "An analytics table with mono paths, share-of-traffic bars and signed week-over-week deltas.",
  "registryDependencies": [
    "@spectrumui/data-table"
  ],
  "files": [
    {
      "path": "components/spectrumui/blocks/tables/top-pages-table.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { DataTable, type DataTableColumn } from '@/components/spectrumui/data-table';\n\nfunction DeltaChevron({ up, ...props }: { up: boolean } & React.SVGProps<SVGSVGElement>) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n      <path\n        transform={up ? 'rotate(180 12 12) translate(6, 7)' : 'translate(6, 7)'}\n        d=\"M4.869,9.631 C4.811,9.574 4.563,9.361 4.359,9.162 C3.076,7.997 0.976,4.958 0.335,3.367 C0.232,3.125 0.014,2.514 0,2.188 C0,1.875 0.072,1.577 0.218,1.293 C0.422,0.938 0.743,0.654 1.122,0.498 C1.385,0.397 2.172,0.242 2.186,0.242 C3.047,0.086 4.446,0 5.992,0 C7.465,0 8.807,0.086 9.681,0.213 C9.695,0.228 10.673,0.384 11.008,0.554 C11.62,0.867 12,1.478 12,2.132 L12,2.188 C11.985,2.614 11.605,3.509 11.591,3.509 C10.949,5.014 8.952,7.983 7.625,9.177 C7.625,9.177 7.284,9.513 7.071,9.659 C6.765,9.887 6.386,10 6.007,10 C5.584,10 5.19,9.872 4.869,9.631\"\n      />\n    </svg>\n  );\n}\n\ninterface Page {\n  id: string;\n  path: string;\n  visitors: number;\n  change: number;\n  avgTime: string;\n}\n\nconst PAGES: Page[] = [\n  { id: 'p1', path: '/', visitors: 48210, change: 12.4, avgTime: '1m 42s' },\n  { id: 'p2', path: '/pricing', visitors: 19340, change: 8.1, avgTime: '2m 08s' },\n  { id: 'p3', path: '/docs/getting-started', visitors: 12880, change: -3.2, avgTime: '4m 31s' },\n  { id: 'p4', path: '/blog/launch-week-recap', visitors: 9640, change: 64.9, avgTime: '3m 12s' },\n  { id: 'p5', path: '/changelog', visitors: 5220, change: 4.6, avgTime: '1m 05s' },\n  { id: 'p6', path: '/docs/api/webhooks', visitors: 3980, change: -1.8, avgTime: '5m 44s' },\n  { id: 'p7', path: '/templates', visitors: 2410, change: 22.7, avgTime: '2m 51s' },\n];\n\nconst MAX_VISITORS = Math.max(...PAGES.map((page) => page.visitors));\n\nfunction buildColumns(bars: boolean): DataTableColumn<Page>[] {\n  return [\n    {\n      id: 'path',\n      header: 'Page',\n      sortable: true,\n      value: (row) => row.path,\n      cell: (row) => <span className=\"font-mono text-[13px]\">{row.path}</span>,\n    },\n    {\n      id: 'visitors',\n      header: 'Visitors',\n      sortable: true,\n      numeric: true,\n      value: (row) => row.visitors,\n      formatTotal: (sum) => Math.round(sum).toLocaleString('en-US'),\n      cell: (row) =>\n        bars ? (\n          <span className=\"flex items-center justify-end gap-3\">\n            <span\n              aria-hidden=\"true\"\n              className=\"h-1.5 w-24 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: `${Math.max(4, (row.visitors / MAX_VISITORS) * 100)}%` }}\n              />\n            </span>\n            <span className=\"w-14 font-medium text-neutral-900 dark:text-neutral-100\">\n              {row.visitors.toLocaleString('en-US')}\n            </span>\n          </span>\n        ) : (\n          <span className=\"font-medium text-neutral-900 dark:text-neutral-100\">\n            {row.visitors.toLocaleString('en-US')}\n          </span>\n        ),\n    },\n    {\n      id: 'change',\n      header: 'Change',\n      sortable: true,\n      numeric: true,\n      value: (row) => row.change,\n      cell: (row) => (\n        <span\n          className={`inline-flex items-center gap-1 font-medium tabular-nums ${\n            row.change >= 0\n              ? 'text-emerald-700 dark:text-emerald-300'\n              : 'text-rose-700 dark:text-rose-300'\n          }`}\n        >\n          <DeltaChevron up={row.change >= 0} className=\"size-3\" />\n          {Math.abs(row.change).toFixed(1)}%\n        </span>\n      ),\n    },\n    {\n      id: 'avgTime',\n      header: 'Avg. time',\n      numeric: true,\n      hideBelow: 'sm',\n      value: (row) => row.avgTime,\n    },\n  ];\n}\n\nexport function TopPagesTable({ variant = 'Bars' }: { variant?: 'Bars' | 'Plain' }) {\n  const columns = React.useMemo(() => buildColumns(variant === 'Bars'), [variant]);\n\n  return (\n    <div className=\"mx-auto w-full max-w-3xl px-4 py-10 sm:px-6\">\n      <DataTable\n        data={PAGES}\n        columns={columns}\n        rowId={(row) => row.id}\n        rowLabel={(row) => row.path}\n        caption=\"Most visited pages in the last 30 days, with share bars and week-over-week change.\"\n        variant=\"minimal\"\n        density=\"compact\"\n        title=\"Top pages\"\n        totals={['visitors']}\n        defaultSort={{ columnId: 'visitors', direction: 'desc' }}\n      />\n    </div>\n  );\n}\n",
      "type": "registry:block",
      "target": "components/spectrumui/blocks/tables/top-pages-table.tsx"
    }
  ],
  "type": "registry:block"
}
