From fd8b392ce6c157a29dcd104f992089a28752bf1f Mon Sep 17 00:00:00 2001
From: pasqualevitiello
Date: Sun, 6 Sep 2026 10:38:32 +0200
Subject: [PATCH 1/3] feat: migrate TanStack Table to v9
---
.../members/members-page-client.tsx | 68 ++++++++++----
.../[id]/members/team-members-page-client.tsx | 33 +++++--
apps/examples/calcom/package.json | 2 +-
apps/origin/package.json | 2 +-
apps/origin/public/r/comp-477.json | 2 +-
apps/origin/public/r/comp-478.json | 2 +-
apps/origin/public/r/comp-479.json | 2 +-
apps/origin/public/r/comp-480.json | 2 +-
apps/origin/public/r/comp-481.json | 2 +-
apps/origin/public/r/comp-482.json | 2 +-
apps/origin/public/r/comp-483.json | 2 +-
apps/origin/public/r/comp-484.json | 2 +-
apps/origin/public/r/comp-485.json | 2 +-
.../registry/default/components/comp-477.tsx | 17 +++-
.../registry/default/components/comp-478.tsx | 75 +++++++++------
.../registry/default/components/comp-479.tsx | 33 +++++--
.../registry/default/components/comp-480.tsx | 91 ++++++++++++-------
.../registry/default/components/comp-481.tsx | 42 +++++++--
.../registry/default/components/comp-482.tsx | 23 +++--
.../registry/default/components/comp-483.tsx | 49 +++++++---
.../registry/default/components/comp-484.tsx | 46 +++++++---
.../registry/default/components/comp-485.tsx | 76 +++++++++++-----
apps/ui/package.json | 2 +-
apps/ui/public/r/p-table-3.json | 2 +-
apps/ui/public/r/p-table-4.json | 2 +-
apps/ui/public/r/p-table-6.json | 2 +-
apps/ui/public/r/p-table-8.json | 2 +-
.../registry/default/particles/p-table-3.tsx | 18 ++--
.../registry/default/particles/p-table-4.tsx | 47 +++++++---
.../registry/default/particles/p-table-6.tsx | 18 ++--
.../registry/default/particles/p-table-8.tsx | 47 +++++++---
bun.lock | 18 ++--
32 files changed, 500 insertions(+), 233 deletions(-)
diff --git a/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx b/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx
index 21d01890d..d84dbfece 100644
--- a/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx
+++ b/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx
@@ -42,11 +42,20 @@ import {
type Column,
type ColumnDef,
type ColumnSizingState,
+ columnFilteringFeature,
+ columnPinningFeature,
+ columnResizingFeature,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ createSortedRowModel,
flexRender,
- getCoreRowModel,
- getSortedRowModel,
+ rowSelectionFeature,
+ rowSortingFeature,
type SortingState,
- useReactTable,
+ sortFn_alphanumeric,
+ sortFn_text,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import {
ArrowUpRightIcon,
@@ -127,6 +136,21 @@ type Member = {
avatarUrl?: string;
};
+const features = tableFeatures({
+ columnFilteringFeature,
+ columnPinningFeature,
+ columnSizingFeature,
+ columnResizingFeature,
+ columnVisibilityFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
const members: Member[] = [
{
avatarUrl:
@@ -352,25 +376,30 @@ function OptionalBadge({ value }: { value?: string }) {
const FILLER_EXCLUDED_COLUMN_IDS = new Set(["select", "actions"]);
const INITIAL_COLUMN_PINNING = {
- left: ["select", "name"],
- right: ["actions"],
+ end: ["actions"],
+ start: ["select", "name"],
};
-function getPinningStyles(column: Column): CSSProperties {
+function getPinningStyles(
+ column: Column,
+): CSSProperties {
const isPinned = column.getIsPinned();
return {
- "--pinned-left-offset":
- isPinned === "left" ? `${column.getStart("left")}px` : undefined,
- left: undefined,
- position: isPinned === "right" ? "sticky" : undefined,
- right: isPinned === "right" ? `${column.getAfter("right")}px` : undefined,
+ "--pinned-start-offset":
+ isPinned === "start" ? `${column.getStart("start")}px` : undefined,
+ insetInlineEnd:
+ isPinned === "end" ? `${column.getAfter("end")}px` : undefined,
+ insetInlineStart: undefined,
+ position: isPinned === "end" ? "sticky" : undefined,
zIndex: isPinned ? 1 : 0,
} as CSSProperties;
}
-function getPinnedDataAttribute(column: Column): {
- "data-pinned"?: "left" | "right";
+function getPinnedDataAttribute(
+ column: Column,
+): {
+ "data-pinned"?: "end" | "start";
} {
const isPinned = column.getIsPinned();
return isPinned ? { "data-pinned": isPinned } : {};
@@ -421,8 +450,8 @@ function getColumnDisplayWidth({
function getColumns(
columnVisibility: Record,
-): ColumnDef[] {
- const cols: ColumnDef[] = [
+): ColumnDef[] {
+ const cols: ColumnDef[] = [
{
cell: ({ row }) => (
@@ -663,15 +692,14 @@ export function MembersPageClient() {
return () => observer.disconnect();
}, []);
- const table = useReactTable({
+ const table = useTable({
columnResizeMode: "onChange",
columns,
data: filteredMembers,
enableRowSelection: true,
enableSortingRemoval: false,
- getCoreRowModel: getCoreRowModel(),
+ features,
getRowId: (row) => row.id,
- getSortedRowModel: getSortedRowModel(),
initialState: {
columnPinning: INITIAL_COLUMN_PINNING,
},
@@ -832,7 +860,7 @@ export function MembersPageClient() {
? "descending"
: "none"
}
- className="relative z-1 select-none bg-[color-mix(in_srgb,var(--color-black)_3%,var(--background))] before:pointer-events-none before:absolute before:inset-y-0 before:z-1 not-data-pinned:before:hidden before:w-4 before:from-[color-mix(in_srgb,var(--color-black)_3%,var(--background))] before:to-transparent data-[pinned=left]:before:start-full data-[pinned=right]:before:end-full in-data-overflow-x-end:data-[pinned=right]:before:bg-linear-to-l last:*:data-[slot=column-resize-handle]:opacity-0 data-[pinned=left]:max-md:before:hidden data-[pinned=left]:md:sticky data-[pinned=left]:md:left-(--pinned-left-offset) in-data-overflow-x-start:data-[pinned=left]:md:before:bg-linear-to-r dark:bg-[color-mix(in_srgb,var(--color-white)_4.6%,var(--background))] dark:before:from-[color-mix(in_srgb,var(--color-white)_4.6%,var(--background))]"
+ className="relative z-1 select-none bg-[color-mix(in_srgb,var(--color-black)_3%,var(--background))] before:pointer-events-none before:absolute before:inset-y-0 before:z-1 not-data-pinned:before:hidden before:w-4 before:from-[color-mix(in_srgb,var(--color-black)_3%,var(--background))] before:to-transparent data-[pinned=start]:before:start-full data-[pinned=end]:before:end-full in-data-overflow-x-end:data-[pinned=end]:before:bg-linear-to-l last:*:data-[slot=column-resize-handle]:opacity-0 data-[pinned=start]:max-md:before:hidden data-[pinned=start]:md:sticky data-[pinned=start]:md:start-(--pinned-start-offset) in-data-overflow-x-start:data-[pinned=start]:md:before:bg-linear-to-r dark:bg-[color-mix(in_srgb,var(--color-white)_4.6%,var(--background))] dark:before:from-[color-mix(in_srgb,var(--color-white)_4.6%,var(--background))]"
colSpan={header.colSpan}
key={header.id}
{...getPinnedDataAttribute(header.column)}
@@ -919,7 +947,7 @@ export function MembersPageClient() {
>
{row.getVisibleCells().map((cell) => (
[] {
- const cols: ColumnDef[] = [
+}): ColumnDef[] {
+ const cols: ColumnDef[] = [
{
cell: ({ row }) => (
@@ -389,14 +407,13 @@ export function TeamMembersPageClient() {
});
}, [showLastActiveColumn, showRoleColumn]);
- const table = useReactTable({
+ const table = useTable({
columns,
data: filteredMembers,
enableRowSelection: true,
enableSortingRemoval: false,
- getCoreRowModel: getCoreRowModel(),
+ features,
getRowId: (row) => row.id,
- getSortedRowModel: getSortedRowModel(),
onRowSelectionChange: setRowSelection,
onSortingChange: setSorting,
state: {
diff --git a/apps/examples/calcom/package.json b/apps/examples/calcom/package.json
index e776f33fa..1ffc54080 100644
--- a/apps/examples/calcom/package.json
+++ b/apps/examples/calcom/package.json
@@ -7,7 +7,7 @@
"@dnd-kit/utilities": "^3.2.2",
"@hugeicons/core-free-icons": "^2.0.0",
"@hugeicons/react": "^1.1.1",
- "@tanstack/react-table": "^8.21.3",
+ "@tanstack/react-table": "^9.2.4",
"dompurify": "^3.3.1",
"lucide-react": "^0.555.0",
"marked": "^17.0.1",
diff --git a/apps/origin/package.json b/apps/origin/package.json
index a0a2f461b..22756e999 100644
--- a/apps/origin/package.json
+++ b/apps/origin/package.json
@@ -10,7 +10,7 @@
"@origin-space/image-cropper": "^0.1.9",
"@radix-ui/react-icons": "^1.3.2",
"@remixicon/react": "^4.7.0",
- "@tanstack/react-table": "^8.21.3",
+ "@tanstack/react-table": "^9.2.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "1.1.1",
diff --git a/apps/origin/public/r/comp-477.json b/apps/origin/public/r/comp-477.json
index 73fe24bb1..2b81959e8 100644
--- a/apps/origin/public/r/comp-477.json
+++ b/apps/origin/public/r/comp-477.json
@@ -13,7 +13,7 @@
"files": [
{
"path": "registry/default/components/comp-477.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { useEffect, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef- [] = [\n {\n cell: ({ row }) => (\n
row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n getCoreRowModel: getCoreRowModel(),\n });\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total \n \n {new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(data.reduce((total, item) => total + item.balance, 0))}\n \n \n \n
\n
\n Basic data table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnVisibilityFeature,\n type ColumnDef,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n features,\n });\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total \n \n {new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(data.reduce((total, item) => total + item.balance, 0))}\n \n \n \n
\n
\n Basic data table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-478.json b/apps/origin/public/r/comp-478.json
index c20953dbf..5087227f0 100644
--- a/apps/origin/public/r/comp-478.json
+++ b/apps/origin/public/r/comp-478.json
@@ -15,7 +15,7 @@
"files": [
{
"path": "registry/default/components/comp-478.tsx",
- "content": "\"use client\";\n\nimport {\n type Column,\n type ColumnDef,\n type ColumnFiltersState,\n flexRender,\n getCoreRowModel,\n getFacetedMinMaxValues,\n getFacetedRowModel,\n getFacetedUniqueValues,\n getFilteredRowModel,\n getSortedRowModel,\n type RowData,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronUpIcon,\n ExternalLinkIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ndeclare module \"@tanstack/react-table\" {\n //allows us to define custom properties for our columns\n // Type parameters TData and TValue must match TanStack Table's declaration exactly\n // biome-ignore lint: Type parameters required for module augmentation compatibility\n interface ColumnMeta {\n filterVariant?: \"text\" | \"range\" | \"select\";\n }\n}\n\ntype Item = {\n id: string;\n keyword: string;\n intents: Array<\n \"Informational\" | \"Navigational\" | \"Commercial\" | \"Transactional\"\n >;\n volume: number;\n cpc: number;\n traffic: number;\n link: string;\n};\n\nconst columns: ColumnDef- [] = [\n {\n cell: ({ row }) => (\n
row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"keyword\",\n cell: ({ row }) => (\n {row.getValue(\"keyword\")}
\n ),\n header: \"Keyword\",\n },\n {\n accessorKey: \"intents\",\n cell: ({ row }) => {\n const intents = row.getValue(\"intents\") as string[];\n return (\n \n {intents.map((intent) => {\n const styles = {\n Commercial: \"bg-amber-400/20 text-amber-500\",\n Informational: \"bg-indigo-400/20 text-indigo-500\",\n Navigational: \"bg-emerald-400/20 text-emerald-500\",\n Transactional: \"bg-rose-400/20 text-rose-500\",\n }[intent];\n\n return (\n
\n {intent.charAt(0)}\n
\n );\n })}\n
\n );\n },\n enableSorting: false,\n filterFn: (row, id, filterValue) => {\n const rowValue = row.getValue(id);\n return Array.isArray(rowValue) && rowValue.includes(filterValue);\n },\n header: \"Intents\",\n meta: {\n filterVariant: \"select\",\n },\n },\n {\n accessorKey: \"volume\",\n cell: ({ row }) => {\n const volume = Number.parseInt(row.getValue(\"volume\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(volume);\n },\n header: \"Volume\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"cpc\",\n cell: ({ row }) => ${row.getValue(\"cpc\")}
,\n header: \"CPC\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"traffic\",\n cell: ({ row }) => {\n const traffic = Number.parseInt(row.getValue(\"traffic\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(traffic);\n },\n header: \"Traffic\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"link\",\n cell: ({ row }) => (\n \n {row.getValue(\"link\")} \n \n ),\n enableSorting: false,\n header: \"Link\",\n },\n];\n\nconst items: Item[] = [\n {\n cpc: 2.5,\n id: \"1\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react components\",\n link: \"https://coss.com/origin\",\n traffic: 88,\n volume: 2507,\n },\n {\n cpc: 4.75,\n id: \"2\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"buy react templates\",\n link: \"https://coss.com/origin/input\",\n traffic: 65,\n volume: 1850,\n },\n {\n cpc: 3.25,\n id: \"3\",\n intents: [\"Informational\", \"Commercial\"],\n keyword: \"react ui library\",\n link: \"https://coss.com/origin/badge\",\n traffic: 112,\n volume: 3200,\n },\n {\n cpc: 1.95,\n id: \"4\",\n intents: [\"Transactional\"],\n keyword: \"tailwind components download\",\n link: \"https://coss.com/origin/alert\",\n traffic: 45,\n volume: 890,\n },\n {\n cpc: 5.5,\n id: \"5\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react dashboard template free\",\n link: \"https://coss.com/origin/tabs\",\n traffic: 156,\n volume: 4100,\n },\n {\n cpc: 1.25,\n id: \"6\",\n intents: [\"Informational\"],\n keyword: \"how to use react components\",\n link: \"https://coss.com/origin/table\",\n traffic: 42,\n volume: 1200,\n },\n {\n cpc: 6.8,\n id: \"7\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react ui kit premium\",\n link: \"https://coss.com/origin/avatar\",\n traffic: 28,\n volume: 760,\n },\n {\n cpc: 1.8,\n id: \"8\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react component documentation\",\n link: \"https://coss.com/origin\",\n traffic: 35,\n volume: 950,\n },\n];\n\nexport default function Component() {\n const [columnFilters, setColumnFilters] = useState([]);\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"traffic\",\n },\n ]);\n\n const table = useReactTable({\n columns,\n data: items,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getFacetedMinMaxValues: getFacetedMinMaxValues(), // generate min/max values for range filter\n getFacetedRowModel: getFacetedRowModel(), // client-side faceting\n getFacetedUniqueValues: getFacetedUniqueValues(), // generate unique values for select filter/autocomplete\n getFilteredRowModel: getFilteredRowModel(), //client-side filtering\n getSortedRowModel: getSortedRowModel(),\n onColumnFiltersChange: setColumnFilters,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n sorting,\n },\n });\n\n const keywordColumn = table.getColumn(\"keyword\");\n const intentsColumn = table.getColumn(\"intents\");\n const volumeColumn = table.getColumn(\"volume\");\n const cpcColumn = table.getColumn(\"cpc\");\n const trafficColumn = table.getColumn(\"traffic\");\n\n return (\n \n {/* Filters */}\n
\n {/* Search input */}\n {keywordColumn && (\n
\n \n
\n )}\n {/* Intents select */}\n {intentsColumn && (\n
\n \n
\n )}\n {/* Volume inputs */}\n {volumeColumn && (\n
\n \n
\n )}\n {/* CPC inputs */}\n {cpcColumn && (\n
\n \n
\n )}\n {/* Traffic inputs */}\n {trafficColumn && (\n
\n \n
\n )}\n
\n\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Data table with filters made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction Filter({ column }: { column: Column- }) {\n const id = useId();\n const columnFilterValue = column.getFilterValue();\n const { filterVariant } = column.columnDef.meta ?? {};\n const columnHeader =\n typeof column.columnDef.header === \"string\" ? column.columnDef.header : \"\";\n const sortedUniqueValues = useMemo(() => {\n if (filterVariant === \"range\") return [];\n\n // Get all unique values from the column\n const values = Array.from(column.getFacetedUniqueValues().keys());\n\n // If the values are arrays, flatten them and get unique items\n const flattenedValues = values.reduce((acc: string[], curr) => {\n if (Array.isArray(curr)) {\n acc.push(...curr);\n } else {\n acc.push(curr);\n }\n return acc;\n }, []);\n\n // Get unique values and sort them\n return Array.from(new Set(flattenedValues)).sort();\n }, [column, filterVariant]);\n\n if (filterVariant === \"range\") {\n return (\n \n );\n }\n\n if (filterVariant === \"select\") {\n return (\n
\n {columnHeader} \n {\n column.setFilterValue(value === \"all\" ? undefined : value);\n }}\n value={columnFilterValue?.toString() ?? \"all\"}\n >\n \n \n \n \n All \n {sortedUniqueValues.map((value) => (\n \n {String(value)}\n \n ))}\n \n \n
\n );\n }\n\n return (\n \n
{columnHeader} \n
\n
column.setFilterValue(e.target.value)}\n placeholder={`Search ${columnHeader.toLowerCase()}`}\n type=\"text\"\n value={(columnFilterValue ?? \"\") as string}\n />\n
\n \n
\n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnFacetingFeature,\n columnFilteringFeature,\n columnVisibilityFeature,\n type Column,\n type ColumnDef,\n type ColumnFiltersState,\n createFacetedMinMaxValues,\n createFacetedRowModel,\n createFacetedUniqueValues,\n createFilteredRowModel,\n createSortedRowModel,\n filterFn_includesString,\n filterFn_inNumberRange,\n flexRender,\n metaHelper,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronUpIcon,\n ExternalLinkIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n keyword: string;\n intents: Array<\n \"Informational\" | \"Navigational\" | \"Commercial\" | \"Transactional\"\n >;\n volume: number;\n cpc: number;\n traffic: number;\n link: string;\n};\n\nconst features = tableFeatures({\n columnFilteringFeature,\n columnFacetingFeature,\n columnVisibilityFeature,\n facetedMinMaxValues: createFacetedMinMaxValues(),\n facetedRowModel: createFacetedRowModel(),\n facetedUniqueValues: createFacetedUniqueValues(),\n filteredRowModel: createFilteredRowModel(),\n filterFns: {\n includesString: filterFn_includesString,\n inNumberRange: filterFn_inNumberRange,\n },\n columnMeta: metaHelper<{\n filterVariant?: \"text\" | \"range\" | \"select\";\n }>(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"keyword\",\n cell: ({ row }) => (\n {row.getValue(\"keyword\")}
\n ),\n header: \"Keyword\",\n },\n {\n accessorKey: \"intents\",\n cell: ({ row }) => {\n const intents = row.getValue(\"intents\") as string[];\n return (\n \n {intents.map((intent) => {\n const styles = {\n Commercial: \"bg-amber-400/20 text-amber-500\",\n Informational: \"bg-indigo-400/20 text-indigo-500\",\n Navigational: \"bg-emerald-400/20 text-emerald-500\",\n Transactional: \"bg-rose-400/20 text-rose-500\",\n }[intent];\n\n return (\n
\n {intent.charAt(0)}\n
\n );\n })}\n
\n );\n },\n enableSorting: false,\n filterFn: (row, id, filterValue) => {\n const rowValue = row.getValue(id);\n return Array.isArray(rowValue) && rowValue.includes(filterValue);\n },\n header: \"Intents\",\n meta: {\n filterVariant: \"select\",\n },\n },\n {\n accessorKey: \"volume\",\n cell: ({ row }) => {\n const volume = Number.parseInt(row.getValue(\"volume\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(volume);\n },\n header: \"Volume\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"cpc\",\n cell: ({ row }) => ${row.getValue(\"cpc\")}
,\n header: \"CPC\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"traffic\",\n cell: ({ row }) => {\n const traffic = Number.parseInt(row.getValue(\"traffic\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(traffic);\n },\n header: \"Traffic\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"link\",\n cell: ({ row }) => (\n \n {row.getValue(\"link\")} \n \n ),\n enableSorting: false,\n header: \"Link\",\n },\n];\n\nconst items: Item[] = [\n {\n cpc: 2.5,\n id: \"1\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react components\",\n link: \"https://coss.com/origin\",\n traffic: 88,\n volume: 2507,\n },\n {\n cpc: 4.75,\n id: \"2\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"buy react templates\",\n link: \"https://coss.com/origin/input\",\n traffic: 65,\n volume: 1850,\n },\n {\n cpc: 3.25,\n id: \"3\",\n intents: [\"Informational\", \"Commercial\"],\n keyword: \"react ui library\",\n link: \"https://coss.com/origin/badge\",\n traffic: 112,\n volume: 3200,\n },\n {\n cpc: 1.95,\n id: \"4\",\n intents: [\"Transactional\"],\n keyword: \"tailwind components download\",\n link: \"https://coss.com/origin/alert\",\n traffic: 45,\n volume: 890,\n },\n {\n cpc: 5.5,\n id: \"5\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react dashboard template free\",\n link: \"https://coss.com/origin/tabs\",\n traffic: 156,\n volume: 4100,\n },\n {\n cpc: 1.25,\n id: \"6\",\n intents: [\"Informational\"],\n keyword: \"how to use react components\",\n link: \"https://coss.com/origin/table\",\n traffic: 42,\n volume: 1200,\n },\n {\n cpc: 6.8,\n id: \"7\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react ui kit premium\",\n link: \"https://coss.com/origin/avatar\",\n traffic: 28,\n volume: 760,\n },\n {\n cpc: 1.8,\n id: \"8\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react component documentation\",\n link: \"https://coss.com/origin\",\n traffic: 35,\n volume: 950,\n },\n];\n\nexport default function Component() {\n const [columnFilters, setColumnFilters] = useState([]);\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"traffic\",\n },\n ]);\n\n const table = useTable({\n columns,\n data: items,\n enableSortingRemoval: false,\n features,\n onColumnFiltersChange: setColumnFilters,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n sorting,\n },\n });\n\n const keywordColumn = table.getColumn(\"keyword\");\n const intentsColumn = table.getColumn(\"intents\");\n const volumeColumn = table.getColumn(\"volume\");\n const cpcColumn = table.getColumn(\"cpc\");\n const trafficColumn = table.getColumn(\"traffic\");\n\n return (\n \n {/* Filters */}\n
\n {/* Search input */}\n {keywordColumn && (\n
\n \n
\n )}\n {/* Intents select */}\n {intentsColumn && (\n
\n \n
\n )}\n {/* Volume inputs */}\n {volumeColumn && (\n
\n \n
\n )}\n {/* CPC inputs */}\n {cpcColumn && (\n
\n \n
\n )}\n {/* Traffic inputs */}\n {trafficColumn && (\n
\n \n
\n )}\n
\n\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Data table with filters made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction Filter({\n column,\n}: {\n column: Column;\n}) {\n const id = useId();\n const columnFilterValue = column.getFilterValue();\n const { filterVariant } = column.columnDef.meta ?? {};\n const columnHeader =\n typeof column.columnDef.header === \"string\" ? column.columnDef.header : \"\";\n const sortedUniqueValues = useMemo(() => {\n if (filterVariant === \"range\") return [];\n\n // Get all unique values from the column\n const values = Array.from(column.getFacetedUniqueValues().keys());\n\n // If the values are arrays, flatten them and get unique items\n const flattenedValues = values.reduce((acc: string[], curr) => {\n if (Array.isArray(curr)) {\n acc.push(...curr);\n } else {\n acc.push(curr);\n }\n return acc;\n }, []);\n\n // Get unique values and sort them\n return Array.from(new Set(flattenedValues)).sort();\n }, [column, filterVariant]);\n\n if (filterVariant === \"range\") {\n return (\n \n );\n }\n\n if (filterVariant === \"select\") {\n return (\n \n {columnHeader} \n {\n column.setFilterValue(value === \"all\" ? undefined : value);\n }}\n value={columnFilterValue?.toString() ?? \"all\"}\n >\n \n \n \n \n All \n {sortedUniqueValues.map((value) => (\n \n {String(value)}\n \n ))}\n \n \n
\n );\n }\n\n return (\n \n
{columnHeader} \n
\n
column.setFilterValue(e.target.value)}\n placeholder={`Search ${columnHeader.toLowerCase()}`}\n type=\"text\"\n value={(columnFilterValue ?? \"\") as string}\n />\n
\n \n
\n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-479.json b/apps/origin/public/r/comp-479.json
index 9aa20c08b..aaf05cde6 100644
--- a/apps/origin/public/r/comp-479.json
+++ b/apps/origin/public/r/comp-479.json
@@ -11,7 +11,7 @@
"files": [
{
"path": "registry/default/components/comp-479.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Excellent\" | \"Good\" | \"Average\" | \"Poor\";\n};\n\nconst columns: ColumnDef- [] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n \n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n .cursor-col-resize]:opacity-0\"\n key={header.id}\n {...{\n colSpan: header.colSpan,\n style: {\n width: header.getSize(),\n },\n }}\n >\n {header.isPlaceholder ? null : (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n )}\n {header.column.getCanResize() && (\n header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Resizable and sortable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnResizingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n type ColumnDef,\n flexRender,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Excellent\" | \"Good\" | \"Average\" | \"Poor\";\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnResizingFeature,\n columnVisibilityFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n \n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n .cursor-col-resize]:opacity-0\"\n key={header.id}\n {...{\n colSpan: header.colSpan,\n style: {\n width: header.getSize(),\n },\n }}\n >\n {header.isPlaceholder ? null : (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n )}\n {header.column.getCanResize() && (\n header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Resizable and sortable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-480.json b/apps/origin/public/r/comp-480.json
index 3cc3a68fa..f8da1643a 100644
--- a/apps/origin/public/r/comp-480.json
+++ b/apps/origin/public/r/comp-480.json
@@ -13,7 +13,7 @@
"files": [
{
"path": "registry/default/components/comp-480.tsx",
- "content": "\"use client\";\n\nimport {\n type Column,\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ArrowLeftToLineIcon,\n ArrowRightToLineIcon,\n EllipsisIcon,\n PinOffIcon,\n} from \"lucide-react\";\nimport { type CSSProperties, useEffect, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Good\" | \"Very Good\" | \"Excellent\" | \"Outstanding\";\n};\n\n// Helper function to compute pinning styles for columns\nconst getPinningStyles = (column: Column- ): CSSProperties => {\n const isPinned = column.getIsPinned();\n return {\n left: isPinned === \"left\" ? `${column.getStart(\"left\")}px` : undefined,\n position: isPinned ? \"sticky\" : \"relative\",\n right: isPinned === \"right\" ? `${column.getAfter(\"right\")}px` : undefined,\n width: column.getSize(),\n zIndex: isPinned ? 1 : 0,\n };\n};\n\nconst columns: ColumnDef
- [] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n \n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const { column } = header;\n const isPinned = column.getIsPinned();\n const isLastLeftPinned =\n isPinned === \"left\" && column.getIsLastColumn(\"left\");\n const isFirstRightPinned =\n isPinned === \"right\" && column.getIsFirstColumn(\"right\");\n\n return (\n \n \n
\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {/* Pin/Unpin column controls with enhanced accessibility */}\n {!header.isPlaceholder &&\n header.column.getCanPin() &&\n (header.column.getIsPinned() ? (\n
header.column.pin(false)}\n size=\"icon\"\n title={`Unpin ${header.column.columnDef.header as string} column`}\n variant=\"ghost\"\n >\n \n \n ) : (\n
\n \n \n \n \n \n \n header.column.pin(\"left\")}\n >\n \n Stick to left\n \n header.column.pin(\"right\")}\n >\n \n Stick to right\n \n \n \n ))}\n {header.column.getCanResize() && (\n
header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n
\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => {\n const { column } = cell;\n const isPinned = column.getIsPinned();\n const isLastLeftPinned =\n isPinned === \"left\" && column.getIsLastColumn(\"left\");\n const isFirstRightPinned =\n isPinned === \"right\" && column.getIsFirstColumn(\"right\");\n\n return (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n );\n })}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Pinnable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnOrderingFeature,\n columnPinningFeature,\n columnResizingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n type Column,\n type ColumnDef,\n flexRender,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ArrowLeftToLineIcon,\n ArrowRightToLineIcon,\n EllipsisIcon,\n PinOffIcon,\n} from \"lucide-react\";\nimport { type CSSProperties, useEffect, useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Good\" | \"Very Good\" | \"Excellent\" | \"Outstanding\";\n};\n\nconst features = tableFeatures({\n columnOrderingFeature,\n columnPinningFeature,\n columnSizingFeature,\n columnResizingFeature,\n columnVisibilityFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\n// Helper function to compute pinning styles for columns\nconst getPinningStyles = (\n column: Column,\n): CSSProperties => {\n const isPinned = column.getIsPinned();\n return {\n insetInlineEnd:\n isPinned === \"end\" ? `${column.getAfter(\"end\")}px` : undefined,\n insetInlineStart:\n isPinned === \"start\" ? `${column.getStart(\"start\")}px` : undefined,\n position: isPinned ? \"sticky\" : \"relative\",\n width: column.getSize(),\n zIndex: isPinned ? 1 : 0,\n };\n};\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n \n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const { column } = header;\n const isPinned = column.getIsPinned();\n const isLastStartPinned =\n isPinned === \"start\" && column.getIsLastColumn(\"start\");\n const isFirstEndPinned =\n isPinned === \"end\" && column.getIsFirstColumn(\"end\");\n\n return (\n \n \n
\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {/* Pin/Unpin column controls with enhanced accessibility */}\n {!header.isPlaceholder &&\n header.column.getCanPin() &&\n (header.column.getIsPinned() ? (\n
header.column.pin(false)}\n size=\"icon\"\n title={`Unpin ${header.column.columnDef.header as string} column`}\n variant=\"ghost\"\n >\n \n \n ) : (\n
\n \n \n \n \n \n \n header.column.pin(\"start\")}\n >\n \n Stick to start\n \n header.column.pin(\"end\")}\n >\n \n Stick to end\n \n \n \n ))}\n {header.column.getCanResize() && (\n
header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n
\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => {\n const { column } = cell;\n const isPinned = column.getIsPinned();\n const isLastStartPinned =\n isPinned === \"start\" && column.getIsLastColumn(\"start\");\n const isFirstEndPinned =\n isPinned === \"end\" && column.getIsFirstColumn(\"end\");\n\n return (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n );\n })}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Pinnable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-481.json b/apps/origin/public/r/comp-481.json
index 0b3c33e18..72b7b175b 100644
--- a/apps/origin/public/r/comp-481.json
+++ b/apps/origin/public/r/comp-481.json
@@ -17,7 +17,7 @@
"files": [
{
"path": "registry/default/components/comp-481.tsx",
- "content": "\"use client\";\n\nimport {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n MouseSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { restrictToHorizontalAxis } from \"@dnd-kit/modifiers\";\nimport {\n arrayMove,\n horizontalListSortingStrategy,\n SortableContext,\n useSortable,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport {\n type Cell,\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n type Header,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, GripVerticalIcon } from \"lucide-react\";\nimport { type CSSProperties, useEffect, useId, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef- [] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n id: \"name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n id: \"email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n id: \"location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n id: \"status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n id: \"balance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([]);\n const [columnOrder, setColumnOrder] = useState(\n columns.map((column) => column.id as string),\n );\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onColumnOrderChange: setColumnOrder,\n onSortingChange: setSorting,\n state: {\n columnOrder,\n sorting,\n },\n });\n\n // reorder columns after drag & drop\n function handleDragEnd(event: DragEndEvent) {\n const { active, over } = event;\n if (active && over && active.id !== over.id) {\n setColumnOrder((columnOrder) => {\n const oldIndex = columnOrder.indexOf(active.id as string);\n const newIndex = columnOrder.indexOf(over.id as string);\n return arrayMove(columnOrder, oldIndex, newIndex); //this is just a splice util\n });\n }\n }\n\n const sensors = useSensors(\n useSensor(MouseSensor, {}),\n useSensor(TouchSensor, {}),\n useSensor(KeyboardSensor, {}),\n );\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n \n {headerGroup.headers.map((header) => (\n \n ))}\n \n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n \n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n Draggable columns made with{\" \"}\n \n TanStack Table\n {\" \"}\n and{\" \"}\n \n dnd kit\n \n
\n \n );\n}\n\nconst DraggableTableHeader = ({\n header,\n}: {\n header: Header- ;\n}) => {\n const {\n attributes,\n isDragging,\n listeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({\n id: header.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n whiteSpace: \"nowrap\",\n width: header.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n
\n \n \n \n \n \n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n \n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n size=\"icon\"\n variant=\"ghost\"\n >\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n \n
\n \n );\n};\n\nconst DragAlongCell = ({ cell }: { cell: Cell- }) => {\n const { isDragging, setNodeRef, transform, transition } = useSortable({\n id: cell.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n width: cell.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n
\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n );\n};\n",
+ "content": "\"use client\";\n\nimport {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n MouseSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { restrictToHorizontalAxis } from \"@dnd-kit/modifiers\";\nimport {\n arrayMove,\n horizontalListSortingStrategy,\n SortableContext,\n useSortable,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport {\n columnOrderingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n type Cell,\n type ColumnDef,\n flexRender,\n type Header,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, GripVerticalIcon } from \"lucide-react\";\nimport { type CSSProperties, useEffect, useId, useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnOrderingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n id: \"name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n id: \"email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n id: \"location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n id: \"status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n id: \"balance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([]);\n const [columnOrder, setColumnOrder] = useState(\n columns.map((column) => column.id as string),\n );\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onColumnOrderChange: setColumnOrder,\n onSortingChange: setSorting,\n state: {\n columnOrder,\n sorting,\n },\n });\n\n // reorder columns after drag & drop\n function handleDragEnd(event: DragEndEvent) {\n const { active, over } = event;\n if (active && over && active.id !== over.id) {\n setColumnOrder((columnOrder) => {\n const oldIndex = columnOrder.indexOf(active.id as string);\n const newIndex = columnOrder.indexOf(over.id as string);\n return arrayMove(columnOrder, oldIndex, newIndex); //this is just a splice util\n });\n }\n }\n\n const sensors = useSensors(\n useSensor(MouseSensor, {}),\n useSensor(TouchSensor, {}),\n useSensor(KeyboardSensor, {}),\n );\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n \n {headerGroup.headers.map((header) => (\n \n ))}\n \n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n \n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n Draggable columns made with{\" \"}\n \n TanStack Table\n {\" \"}\n and{\" \"}\n \n dnd kit\n \n
\n \n );\n}\n\nconst DraggableTableHeader = ({\n header,\n}: {\n header: Header;\n}) => {\n const {\n attributes,\n isDragging,\n listeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({\n id: header.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n whiteSpace: \"nowrap\",\n width: header.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n \n \n \n \n \n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n \n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n size=\"icon\"\n variant=\"ghost\"\n >\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n \n
\n \n );\n};\n\nconst DragAlongCell = ({\n cell,\n}: {\n cell: Cell;\n}) => {\n const { isDragging, setNodeRef, transform, transition } = useSortable({\n id: cell.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n width: cell.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n );\n};\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-482.json b/apps/origin/public/r/comp-482.json
index d3c576275..bc3ebda73 100644
--- a/apps/origin/public/r/comp-482.json
+++ b/apps/origin/public/r/comp-482.json
@@ -14,7 +14,7 @@
"files": [
{
"path": "registry/default/components/comp-482.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getExpandedRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, InfoIcon } from \"lucide-react\";\nimport { Fragment, useEffect, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n note?: string;\n};\n\nconst columns: ColumnDef- [] = [\n {\n cell: ({ row }) => {\n return row.getCanExpand() ? (\n
\n {row.getIsExpanded() ? (\n \n ) : (\n \n )}\n \n ) : undefined;\n },\n header: () => null,\n id: \"expander\",\n },\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n getCoreRowModel: getCoreRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n getRowCanExpand: (row) => Boolean(row.original.note),\n });\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n {row.getIsExpanded() && (\n \n \n \n
\n \n \n
{row.original.note}
\n
\n \n \n )}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Expanding sub-row made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnVisibilityFeature,\n createExpandedRowModel,\n type ColumnDef,\n flexRender,\n rowExpandingFeature,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, InfoIcon } from \"lucide-react\";\nimport { Fragment, useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n note?: string;\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowExpandingFeature,\n expandedRowModel: createExpandedRowModel(),\n rowSelectionFeature,\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => {\n return row.getCanExpand() ? (\n \n {row.getIsExpanded() ? (\n \n ) : (\n \n )}\n \n ) : undefined;\n },\n header: () => null,\n id: \"expander\",\n },\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n features,\n getRowCanExpand: (row) => Boolean(row.original.note),\n });\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n {row.getIsExpanded() && (\n \n \n \n
\n \n \n
{row.original.note}
\n
\n \n \n )}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Expanding sub-row made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-483.json b/apps/origin/public/r/comp-483.json
index 78825b091..139a9bea6 100644
--- a/apps/origin/public/r/comp-483.json
+++ b/apps/origin/public/r/comp-483.json
@@ -17,7 +17,7 @@
"files": [
{
"path": "registry/default/components/comp-483.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef- [] = [\n {\n cell: ({ row }) => (\n
row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 5,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData([...data, ...data]);\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.getState().pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n table.getState().pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Paginated table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n type ColumnDef,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 5,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData([...data, ...data]);\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n table.state.pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Paginated table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-484.json b/apps/origin/public/r/comp-484.json
index b0c1a7ee5..76e48760f 100644
--- a/apps/origin/public/r/comp-484.json
+++ b/apps/origin/public/r/comp-484.json
@@ -16,7 +16,7 @@
"files": [
{
"path": "registry/default/components/comp-484.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef- [] = [\n {\n cell: ({ row }) => (\n
row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const pageSize = 5;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage: table.getState().pagination.pageIndex + 1,\n paginationItemsToDisplay: 5,\n totalPages: table.getPageCount(),\n });\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Page number information */}\n
\n Page{\" \"}\n \n {table.getState().pagination.pageIndex + 1}\n {\" \"}\n of {table.getPageCount()} \n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number buttons */}\n {pages.map((page) => {\n const isActive =\n page === table.getState().pagination.pageIndex + 1;\n return (\n \n table.setPageIndex(page - 1)}\n size=\"icon\"\n variant={`${isActive ? \"outline\" : \"ghost\"}`}\n >\n {page}\n \n \n );\n })}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n\n {/* Results per page */}\n
\n {\n table.setPageSize(Number(value));\n }}\n value={table.getState().pagination.pageSize.toString()}\n >\n \n \n \n \n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize} / page\n \n ))}\n \n \n
\n
\n
\n Numeric pagination made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n type ColumnDef,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const pageSize = 5;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage: table.state.pagination.pageIndex + 1,\n paginationItemsToDisplay: 5,\n totalPages: table.getPageCount(),\n });\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Page number information */}\n
\n Page{\" \"}\n \n {table.state.pagination.pageIndex + 1}\n {\" \"}\n of {table.getPageCount()} \n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number buttons */}\n {pages.map((page) => {\n const isActive = page === table.state.pagination.pageIndex + 1;\n return (\n \n table.setPageIndex(page - 1)}\n size=\"icon\"\n variant={`${isActive ? \"outline\" : \"ghost\"}`}\n >\n {page}\n \n \n );\n })}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n\n {/* Results per page */}\n
\n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n \n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize} / page\n \n ))}\n \n \n
\n
\n
\n Numeric pagination made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
},
{
diff --git a/apps/origin/public/r/comp-485.json b/apps/origin/public/r/comp-485.json
index 62bbc1eaa..a269a8a76 100644
--- a/apps/origin/public/r/comp-485.json
+++ b/apps/origin/public/r/comp-485.json
@@ -21,7 +21,7 @@
"files": [
{
"path": "registry/default/components/comp-485.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n type ColumnFiltersState,\n type FilterFn,\n flexRender,\n getCoreRowModel,\n getFacetedUniqueValues,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type Row,\n type SortingState,\n useReactTable,\n type VisibilityState,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleAlertIcon,\n CircleXIcon,\n Columns3Icon,\n EllipsisIcon,\n FilterIcon,\n ListFilterIcon,\n PlusIcon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\n// Custom filter function for multi-column searching\nconst multiColumnFilterFn: FilterFn- = (row, _columnId, filterValue) => {\n const searchableRowContent =\n `${row.original.name} ${row.original.email}`.toLowerCase();\n const searchTerm = (filterValue ?? \"\").toLowerCase();\n return searchableRowContent.includes(searchTerm);\n};\n\nconst statusFilterFn: FilterFn
- = (\n row,\n columnId,\n filterValue: string[],\n) => {\n if (!filterValue?.length) return true;\n const status = row.getValue(columnId) as string;\n return filterValue.includes(status);\n};\n\nconst columns: ColumnDef
- [] = [\n {\n cell: ({ row }) => (\n
row.toggleSelected(!!value)}\n />\n ),\n enableHiding: false,\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n enableHiding: false,\n filterFn: multiColumnFilterFn,\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 220,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n filterFn: statusFilterFn,\n header: \"Status\",\n size: 100,\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n {\n cell: ({ row }) => ,\n enableHiding: false,\n header: () => Actions ,\n id: \"actions\",\n size: 60,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [columnFilters, setColumnFilters] = useState([]);\n const [columnVisibility, setColumnVisibility] = useState({});\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 10,\n });\n const inputRef = useRef(null);\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const handleDeleteRows = () => {\n const selectedRows = table.getSelectedRowModel().rows;\n const updatedData = data.filter(\n (item) => !selectedRows.some((row) => row.original.id === item.id),\n );\n setData(updatedData);\n table.resetRowSelection();\n };\n\n const table = useReactTable({\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getFacetedUniqueValues: getFacetedUniqueValues(),\n getFilteredRowModel: getFilteredRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onColumnFiltersChange: setColumnFilters,\n onColumnVisibilityChange: setColumnVisibility,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n columnVisibility,\n pagination,\n sorting,\n },\n });\n\n // Get unique status values\n const uniqueStatusValues = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n\n if (!statusColumn) return [];\n\n const values = Array.from(statusColumn.getFacetedUniqueValues().keys());\n\n return values.sort();\n }, [table.getColumn]);\n\n // Get counts for each status\n const statusCounts = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n if (!statusColumn) return new Map();\n return statusColumn.getFacetedUniqueValues();\n }, [table]);\n\n const selectedStatuses = useMemo(() => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n return filterValue ?? [];\n }, [table]);\n\n const handleStatusChange = (checked: boolean, value: string) => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n const newFilterValue = filterValue ? [...filterValue] : [];\n\n if (checked) {\n newFilterValue.push(value);\n } else {\n const index = newFilterValue.indexOf(value);\n if (index > -1) {\n newFilterValue.splice(index, 1);\n }\n }\n\n table\n .getColumn(\"status\")\n ?.setFilterValue(newFilterValue.length ? newFilterValue : undefined);\n };\n\n return (\n
\n {/* Filters */}\n
\n
\n {/* Filter by name or email */}\n
\n
\n table.getColumn(\"name\")?.setFilterValue(e.target.value)\n }\n placeholder=\"Filter by name or email...\"\n ref={inputRef}\n type=\"text\"\n value={\n (table.getColumn(\"name\")?.getFilterValue() ?? \"\") as string\n }\n />\n
\n \n
\n {Boolean(table.getColumn(\"name\")?.getFilterValue()) && (\n
{\n table.getColumn(\"name\")?.setFilterValue(\"\");\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }}\n type=\"button\"\n >\n \n \n )}\n
\n {/* Filter by status */}\n
\n \n \n \n Status\n {selectedStatuses.length > 0 && (\n \n {selectedStatuses.length}\n \n )}\n \n \n \n \n
\n Filters\n
\n
\n {uniqueStatusValues.map((value, i) => (\n
\n \n handleStatusChange(checked, value)\n }\n />\n \n {value}{\" \"}\n \n {statusCounts.get(value)}\n \n \n
\n ))}\n
\n
\n \n \n {/* Toggle columns visibility */}\n
\n \n \n \n View\n \n \n \n Toggle columns \n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n \n column.toggleVisibility(!!value)\n }\n onSelect={(event) => event.preventDefault()}\n >\n {column.id}\n \n );\n })}\n \n \n
\n
\n {/* Delete button */}\n {table.getSelectedRowModel().rows.length > 0 && (\n
\n \n \n \n Delete\n \n {table.getSelectedRowModel().rows.length}\n \n \n \n \n \n
\n \n
\n
\n \n Are you absolutely sure?\n \n \n This action cannot be undone. This will permanently delete{\" \"}\n {table.getSelectedRowModel().rows.length} selected{\" \"}\n {table.getSelectedRowModel().rows.length === 1\n ? \"row\"\n : \"rows\"}\n .\n \n \n
\n \n Cancel \n \n Delete\n \n \n \n \n )}\n {/* Add user button */}\n
\n \n Add user\n \n
\n
\n\n {/* Table */}\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.getState().pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n table.getState().pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Example of a more complex table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction RowActions({ row: _row }: { row: Row- }) {\n return (\n
\n \n \n \n \n \n
\n \n \n \n \n Edit \n ⌘E \n \n \n Duplicate \n ⌘D \n \n \n \n \n \n Archive \n ⌘A \n \n \n More \n \n \n Move to project \n Move to folder \n \n Advanced options \n \n \n \n \n \n \n Share \n Add to favorites \n \n \n \n Delete \n ⌘⌫ \n \n \n \n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n columnFacetingFeature,\n columnFilteringFeature,\n columnSizingFeature,\n type ColumnVisibilityState,\n columnVisibilityFeature,\n createFacetedUniqueValues,\n createFilteredRowModel,\n createPaginatedRowModel,\n createSortedRowModel,\n type ColumnDef,\n type ColumnFiltersState,\n type FilterFn,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n type Row,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleAlertIcon,\n CircleXIcon,\n Columns3Icon,\n EllipsisIcon,\n FilterIcon,\n ListFilterIcon,\n PlusIcon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnFilteringFeature,\n columnFacetingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n facetedUniqueValues: createFacetedUniqueValues(),\n filteredRowModel: createFilteredRowModel(),\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\n// Custom filter function for multi-column searching\nconst multiColumnFilterFn: FilterFn = (\n row,\n _columnId,\n filterValue,\n) => {\n const searchableRowContent =\n `${row.original.name} ${row.original.email}`.toLowerCase();\n const searchTerm = (filterValue ?? \"\").toLowerCase();\n return searchableRowContent.includes(searchTerm);\n};\n\nconst statusFilterFn: FilterFn = (\n row,\n columnId,\n filterValue: string[],\n) => {\n if (!filterValue?.length) return true;\n const status = row.getValue(columnId) as string;\n return filterValue.includes(status);\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableHiding: false,\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n enableHiding: false,\n filterFn: multiColumnFilterFn,\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 220,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n filterFn: statusFilterFn,\n header: \"Status\",\n size: 100,\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n {\n cell: ({ row }) => ,\n enableHiding: false,\n header: () => Actions ,\n id: \"actions\",\n size: 60,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [columnFilters, setColumnFilters] = useState([]);\n const [columnVisibility, setColumnVisibility] =\n useState({});\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 10,\n });\n const inputRef = useRef(null);\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const handleDeleteRows = () => {\n const selectedRows = table.getSelectedRowModel().rows;\n const updatedData = data.filter(\n (item) => !selectedRows.some((row) => row.original.id === item.id),\n );\n setData(updatedData);\n table.resetRowSelection();\n };\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onColumnFiltersChange: setColumnFilters,\n onColumnVisibilityChange: setColumnVisibility,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n columnVisibility,\n pagination,\n sorting,\n },\n });\n\n // Get unique status values\n const uniqueStatusValues = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n\n if (!statusColumn) return [];\n\n const values = Array.from(statusColumn.getFacetedUniqueValues().keys());\n\n return values.sort();\n }, [table.getColumn]);\n\n // Get counts for each status\n const statusCounts = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n if (!statusColumn) return new Map();\n return statusColumn.getFacetedUniqueValues();\n }, [table]);\n\n const selectedStatuses = useMemo(() => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n return filterValue ?? [];\n }, [table]);\n\n const handleStatusChange = (checked: boolean, value: string) => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n const newFilterValue = filterValue ? [...filterValue] : [];\n\n if (checked) {\n newFilterValue.push(value);\n } else {\n const index = newFilterValue.indexOf(value);\n if (index > -1) {\n newFilterValue.splice(index, 1);\n }\n }\n\n table\n .getColumn(\"status\")\n ?.setFilterValue(newFilterValue.length ? newFilterValue : undefined);\n };\n\n return (\n
\n {/* Filters */}\n
\n
\n {/* Filter by name or email */}\n
\n
\n table.getColumn(\"name\")?.setFilterValue(e.target.value)\n }\n placeholder=\"Filter by name or email...\"\n ref={inputRef}\n type=\"text\"\n value={\n (table.getColumn(\"name\")?.getFilterValue() ?? \"\") as string\n }\n />\n
\n \n
\n {Boolean(table.getColumn(\"name\")?.getFilterValue()) && (\n
{\n table.getColumn(\"name\")?.setFilterValue(\"\");\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }}\n type=\"button\"\n >\n \n \n )}\n
\n {/* Filter by status */}\n
\n \n \n \n Status\n {selectedStatuses.length > 0 && (\n \n {selectedStatuses.length}\n \n )}\n \n \n \n \n
\n Filters\n
\n
\n {uniqueStatusValues.map((value, i) => (\n
\n \n handleStatusChange(checked, value)\n }\n />\n \n {value}{\" \"}\n \n {statusCounts.get(value)}\n \n \n
\n ))}\n
\n
\n \n \n {/* Toggle columns visibility */}\n
\n \n \n \n View\n \n \n \n Toggle columns \n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n \n column.toggleVisibility(!!value)\n }\n onSelect={(event) => event.preventDefault()}\n >\n {column.id}\n \n );\n })}\n \n \n
\n
\n {/* Delete button */}\n {table.getSelectedRowModel().rows.length > 0 && (\n
\n \n \n \n Delete\n \n {table.getSelectedRowModel().rows.length}\n \n \n \n \n \n
\n \n
\n
\n \n Are you absolutely sure?\n \n \n This action cannot be undone. This will permanently delete{\" \"}\n {table.getSelectedRowModel().rows.length} selected{\" \"}\n {table.getSelectedRowModel().rows.length === 1\n ? \"row\"\n : \"rows\"}\n .\n \n \n
\n \n Cancel \n \n Delete\n \n \n \n \n )}\n {/* Add user button */}\n
\n \n Add user\n \n
\n
\n\n {/* Table */}\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n table.state.pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Example of a more complex table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction RowActions({ row: _row }: { row: Row }) {\n return (\n \n \n \n \n \n \n
\n \n \n \n \n Edit \n ⌘E \n \n \n Duplicate \n ⌘D \n \n \n \n \n \n Archive \n ⌘A \n \n \n More \n \n \n Move to project \n Move to folder \n \n Advanced options \n \n \n \n \n \n \n Share \n Add to favorites \n \n \n \n Delete \n ⌘⌫ \n \n \n \n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/registry/default/components/comp-477.tsx b/apps/origin/registry/default/components/comp-477.tsx
index 85ab73cd4..b0670a79d 100644
--- a/apps/origin/registry/default/components/comp-477.tsx
+++ b/apps/origin/registry/default/components/comp-477.tsx
@@ -2,9 +2,11 @@
import {
type ColumnDef,
+ columnVisibilityFeature,
flexRender,
- getCoreRowModel,
- useReactTable,
+ rowSelectionFeature,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import { useEffect, useState } from "react";
import { cn } from "@/registry/default/lib/utils";
@@ -30,7 +32,12 @@ type Item = {
balance: number;
};
-const columns: ColumnDef- [] = [
+const features = tableFeatures({
+ columnVisibilityFeature,
+ rowSelectionFeature,
+});
+
+const columns: ColumnDef
[] = [
{
cell: ({ row }) => (
{
- filterVariant?: "text" | "range" | "select";
- }
-}
-
type Item = {
id: string;
keyword: string;
@@ -63,7 +63,31 @@ type Item = {
link: string;
};
-const columns: ColumnDef- [] = [
+const features = tableFeatures({
+ columnFilteringFeature,
+ columnFacetingFeature,
+ columnVisibilityFeature,
+ facetedMinMaxValues: createFacetedMinMaxValues(),
+ facetedRowModel: createFacetedRowModel(),
+ facetedUniqueValues: createFacetedUniqueValues(),
+ filteredRowModel: createFilteredRowModel(),
+ filterFns: {
+ includesString: filterFn_includesString,
+ inNumberRange: filterFn_inNumberRange,
+ },
+ columnMeta: metaHelper<{
+ filterVariant?: "text" | "range" | "select";
+ }>(),
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
+const columns: ColumnDef
[] = [
{
cell: ({ row }) => (
}) {
+function Filter({
+ column,
+}: {
+ column: Column;
+}) {
const id = useId();
const columnFilterValue = column.getFilterValue();
const { filterVariant } = column.columnDef.meta ?? {};
diff --git a/apps/origin/registry/default/components/comp-479.tsx b/apps/origin/registry/default/components/comp-479.tsx
index 6473143a8..28eed82c4 100644
--- a/apps/origin/registry/default/components/comp-479.tsx
+++ b/apps/origin/registry/default/components/comp-479.tsx
@@ -2,11 +2,18 @@
import {
type ColumnDef,
+ columnResizingFeature,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ createSortedRowModel,
flexRender,
- getCoreRowModel,
- getSortedRowModel,
+ rowSelectionFeature,
+ rowSortingFeature,
type SortingState,
- useReactTable,
+ sortFn_alphanumeric,
+ sortFn_text,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
import { useEffect, useState } from "react";
@@ -35,7 +42,20 @@ type Item = {
performance: "Excellent" | "Good" | "Average" | "Poor";
};
-const columns: ColumnDef- [] = [
+const features = tableFeatures({
+ columnSizingFeature,
+ columnResizingFeature,
+ columnVisibilityFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
+const columns: ColumnDef
[] = [
{
accessorKey: "name",
cell: ({ row }) => (
@@ -117,13 +137,12 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useReactTable({
+ const table = useTable({
columnResizeMode: "onChange",
columns,
data,
enableSortingRemoval: false,
- getCoreRowModel: getCoreRowModel(),
- getSortedRowModel: getSortedRowModel(),
+ features,
onSortingChange: setSorting,
state: {
sorting,
diff --git a/apps/origin/registry/default/components/comp-480.tsx b/apps/origin/registry/default/components/comp-480.tsx
index a858a0311..7f89ef0a8 100644
--- a/apps/origin/registry/default/components/comp-480.tsx
+++ b/apps/origin/registry/default/components/comp-480.tsx
@@ -3,11 +3,20 @@
import {
type Column,
type ColumnDef,
+ columnOrderingFeature,
+ columnPinningFeature,
+ columnResizingFeature,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ createSortedRowModel,
flexRender,
- getCoreRowModel,
- getSortedRowModel,
+ rowSelectionFeature,
+ rowSortingFeature,
type SortingState,
- useReactTable,
+ sortFn_alphanumeric,
+ sortFn_text,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import {
ArrowLeftToLineIcon,
@@ -47,19 +56,38 @@ type Item = {
performance: "Good" | "Very Good" | "Excellent" | "Outstanding";
};
+const features = tableFeatures({
+ columnOrderingFeature,
+ columnPinningFeature,
+ columnSizingFeature,
+ columnResizingFeature,
+ columnVisibilityFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
// Helper function to compute pinning styles for columns
-const getPinningStyles = (column: Column- ): CSSProperties => {
+const getPinningStyles = (
+ column: Column
,
+): CSSProperties => {
const isPinned = column.getIsPinned();
return {
- left: isPinned === "left" ? `${column.getStart("left")}px` : undefined,
+ insetInlineEnd:
+ isPinned === "end" ? `${column.getAfter("end")}px` : undefined,
+ insetInlineStart:
+ isPinned === "start" ? `${column.getStart("start")}px` : undefined,
position: isPinned ? "sticky" : "relative",
- right: isPinned === "right" ? `${column.getAfter("right")}px` : undefined,
width: column.getSize(),
zIndex: isPinned ? 1 : 0,
};
};
-const columns: ColumnDef- [] = [
+const columns: ColumnDef
[] = [
{
accessorKey: "name",
cell: ({ row }) => (
@@ -134,13 +162,12 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useReactTable({
+ const table = useTable({
columnResizeMode: "onChange",
columns,
data,
enableSortingRemoval: false,
- getCoreRowModel: getCoreRowModel(),
- getSortedRowModel: getSortedRowModel(),
+ features,
onSortingChange: setSorting,
state: {
sorting,
@@ -161,20 +188,20 @@ export default function Component() {
{headerGroup.headers.map((header) => {
const { column } = header;
const isPinned = column.getIsPinned();
- const isLastLeftPinned =
- isPinned === "left" && column.getIsLastColumn("left");
- const isFirstRightPinned =
- isPinned === "right" && column.getIsFirstColumn("right");
+ const isLastStartPinned =
+ isPinned === "start" && column.getIsLastColumn("start");
+ const isFirstEndPinned =
+ isPinned === "end" && column.getIsFirstColumn("end");
return (
header.column.pin("left")}
+ onClick={() => header.column.pin("start")}
>
- Stick to left
+ Stick to start
header.column.pin("right")}
+ onClick={() => header.column.pin("end")}
>
- Stick to right
+ Stick to end
@@ -277,19 +304,19 @@ export default function Component() {
{row.getVisibleCells().map((cell) => {
const { column } = cell;
const isPinned = column.getIsPinned();
- const isLastLeftPinned =
- isPinned === "left" && column.getIsLastColumn("left");
- const isFirstRightPinned =
- isPinned === "right" && column.getIsFirstColumn("right");
+ const isLastStartPinned =
+ isPinned === "start" && column.getIsLastColumn("start");
+ const isFirstEndPinned =
+ isPinned === "end" && column.getIsFirstColumn("end");
return (
[] = [
+const features = tableFeatures({
+ columnOrderingFeature,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
+const columns: ColumnDef[] = [
{
accessorKey: "name",
cell: ({ row }) => (
@@ -115,13 +135,11 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useReactTable({
- columnResizeMode: "onChange",
+ const table = useTable({
columns,
data,
enableSortingRemoval: false,
- getCoreRowModel: getCoreRowModel(),
- getSortedRowModel: getSortedRowModel(),
+ features,
onColumnOrderChange: setColumnOrder,
onSortingChange: setSorting,
state: {
@@ -220,7 +238,7 @@ export default function Component() {
const DraggableTableHeader = ({
header,
}: {
- header: Header- ;
+ header: Header
;
}) => {
const {
attributes,
@@ -320,7 +338,11 @@ const DraggableTableHeader = ({
);
};
-const DragAlongCell = ({ cell }: { cell: Cell- }) => {
+const DragAlongCell = ({
+ cell,
+}: {
+ cell: Cell
;
+}) => {
const { isDragging, setNodeRef, transform, transition } = useSortable({
id: cell.column.id,
});
diff --git a/apps/origin/registry/default/components/comp-482.tsx b/apps/origin/registry/default/components/comp-482.tsx
index 4d0fe53e8..2685438de 100644
--- a/apps/origin/registry/default/components/comp-482.tsx
+++ b/apps/origin/registry/default/components/comp-482.tsx
@@ -2,10 +2,13 @@
import {
type ColumnDef,
+ columnVisibilityFeature,
+ createExpandedRowModel,
flexRender,
- getCoreRowModel,
- getExpandedRowModel,
- useReactTable,
+ rowExpandingFeature,
+ rowSelectionFeature,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import { ChevronDownIcon, ChevronUpIcon, InfoIcon } from "lucide-react";
import { Fragment, useEffect, useState } from "react";
@@ -33,7 +36,14 @@ type Item = {
note?: string;
};
-const columns: ColumnDef- [] = [
+const features = tableFeatures({
+ columnVisibilityFeature,
+ rowExpandingFeature,
+ expandedRowModel: createExpandedRowModel(),
+ rowSelectionFeature,
+});
+
+const columns: ColumnDef
[] = [
{
cell: ({ row }) => {
return row.getCanExpand() ? (
@@ -151,11 +161,10 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useReactTable({
+ const table = useTable({
columns,
data,
- getCoreRowModel: getCoreRowModel(),
- getExpandedRowModel: getExpandedRowModel(),
+ features,
getRowCanExpand: (row) => Boolean(row.original.note),
});
diff --git a/apps/origin/registry/default/components/comp-483.tsx b/apps/origin/registry/default/components/comp-483.tsx
index 088f1167f..ca175d228 100644
--- a/apps/origin/registry/default/components/comp-483.tsx
+++ b/apps/origin/registry/default/components/comp-483.tsx
@@ -2,13 +2,20 @@
import {
type ColumnDef,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ createPaginatedRowModel,
+ createSortedRowModel,
flexRender,
- getCoreRowModel,
- getPaginationRowModel,
- getSortedRowModel,
type PaginationState,
+ rowPaginationFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
type SortingState,
- useReactTable,
+ sortFn_alphanumeric,
+ sortFn_text,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import {
ChevronDownIcon,
@@ -55,7 +62,21 @@ type Item = {
balance: number;
};
-const columns: ColumnDef- [] = [
+const features = tableFeatures({
+ columnSizingFeature,
+ columnVisibilityFeature,
+ rowPaginationFeature,
+ paginatedRowModel: createPaginatedRowModel(),
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
+const columns: ColumnDef
[] = [
{
cell: ({ row }) => (
{
table.setPageSize(Number(value));
}}
- value={table.getState().pagination.pageSize.toString()}
+ value={table.state.pagination.pageSize.toString()}
>
@@ -302,15 +321,15 @@ export default function Component() {
className="whitespace-nowrap text-muted-foreground text-sm"
>
- {table.getState().pagination.pageIndex *
- table.getState().pagination.pageSize +
+ {table.state.pagination.pageIndex *
+ table.state.pagination.pageSize +
1}
-
{Math.min(
Math.max(
- table.getState().pagination.pageIndex *
- table.getState().pagination.pageSize +
- table.getState().pagination.pageSize,
+ table.state.pagination.pageIndex *
+ table.state.pagination.pageSize +
+ table.state.pagination.pageSize,
0,
),
table.getRowCount(),
diff --git a/apps/origin/registry/default/components/comp-484.tsx b/apps/origin/registry/default/components/comp-484.tsx
index 5b3590636..a4abee11d 100644
--- a/apps/origin/registry/default/components/comp-484.tsx
+++ b/apps/origin/registry/default/components/comp-484.tsx
@@ -2,13 +2,20 @@
import {
type ColumnDef,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ createPaginatedRowModel,
+ createSortedRowModel,
flexRender,
- getCoreRowModel,
- getPaginationRowModel,
- getSortedRowModel,
type PaginationState,
+ rowPaginationFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
type SortingState,
- useReactTable,
+ sortFn_alphanumeric,
+ sortFn_text,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import {
ChevronDownIcon,
@@ -54,7 +61,21 @@ type Item = {
balance: number;
};
-const columns: ColumnDef- [] = [
+const features = tableFeatures({
+ columnSizingFeature,
+ columnVisibilityFeature,
+ rowPaginationFeature,
+ paginatedRowModel: createPaginatedRowModel(),
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
+const columns: ColumnDef
[] = [
{
cell: ({ row }) => (
Page{" "}
- {table.getState().pagination.pageIndex + 1}
+ {table.state.pagination.pageIndex + 1}
{" "}
of {table.getPageCount()}
@@ -317,8 +336,7 @@ export default function Component() {
{/* Page number buttons */}
{pages.map((page) => {
- const isActive =
- page === table.getState().pagination.pageIndex + 1;
+ const isActive = page === table.state.pagination.pageIndex + 1;
return (
{
table.setPageSize(Number(value));
}}
- value={table.getState().pagination.pageSize.toString()}
+ value={table.state.pagination.pageSize.toString()}
>
= (row, _columnId, filterValue) => {
+const multiColumnFilterFn: FilterFn = (
+ row,
+ _columnId,
+ filterValue,
+) => {
const searchableRowContent =
`${row.original.name} ${row.original.email}`.toLowerCase();
const searchTerm = (filterValue ?? "").toLowerCase();
return searchableRowContent.includes(searchTerm);
};
-const statusFilterFn: FilterFn- = (
+const statusFilterFn: FilterFn
= (
row,
columnId,
filterValue: string[],
@@ -119,7 +150,7 @@ const statusFilterFn: FilterFn- = (
return filterValue.includes(status);
};
-const columns: ColumnDef
- [] = [
+const columns: ColumnDef
[] = [
{
cell: ({ row }) => (
[] = [
export default function Component() {
const id = useId();
const [columnFilters, setColumnFilters] = useState([]);
- const [columnVisibility, setColumnVisibility] = useState({});
+ const [columnVisibility, setColumnVisibility] =
+ useState({});
const [pagination, setPagination] = useState({
pageIndex: 0,
pageSize: 10,
@@ -249,15 +281,11 @@ export default function Component() {
table.resetRowSelection();
};
- const table = useReactTable({
+ const table = useTable({
columns,
data,
enableSortingRemoval: false,
- getCoreRowModel: getCoreRowModel(),
- getFacetedUniqueValues: getFacetedUniqueValues(),
- getFilteredRowModel: getFilteredRowModel(),
- getPaginationRowModel: getPaginationRowModel(),
- getSortedRowModel: getSortedRowModel(),
+ features,
onColumnFiltersChange: setColumnFilters,
onColumnVisibilityChange: setColumnVisibility,
onPaginationChange: setPagination,
@@ -603,7 +631,7 @@ export default function Component() {
onValueChange={(value) => {
table.setPageSize(Number(value));
}}
- value={table.getState().pagination.pageSize.toString()}
+ value={table.state.pagination.pageSize.toString()}
>
@@ -624,15 +652,15 @@ export default function Component() {
className="whitespace-nowrap text-muted-foreground text-sm"
>
- {table.getState().pagination.pageIndex *
- table.getState().pagination.pageSize +
+ {table.state.pagination.pageIndex *
+ table.state.pagination.pageSize +
1}
-
{Math.min(
Math.max(
- table.getState().pagination.pageIndex *
- table.getState().pagination.pageSize +
- table.getState().pagination.pageSize,
+ table.state.pagination.pageIndex *
+ table.state.pagination.pageSize +
+ table.state.pagination.pageSize,
0,
),
table.getRowCount(),
@@ -720,7 +748,7 @@ export default function Component() {
);
}
-function RowActions({ row: _row }: { row: Row- }) {
+function RowActions({ row: _row }: { row: Row
}) {
return (
diff --git a/apps/ui/package.json b/apps/ui/package.json
index 9f5723b5a..25b16bd95 100644
--- a/apps/ui/package.json
+++ b/apps/ui/package.json
@@ -6,7 +6,7 @@
"@hugeicons/core-free-icons": "^2.0.0",
"@hugeicons/react": "^1.1.1",
"@remixicon/react": "^4.7.0",
- "@tanstack/react-table": "^8.21.3",
+ "@tanstack/react-table": "^9.2.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
diff --git a/apps/ui/public/r/p-table-3.json b/apps/ui/public/r/p-table-3.json
index fe51cb4f9..248ed0b2b 100644
--- a/apps/ui/public/r/p-table-3.json
+++ b/apps/ui/public/r/p-table-3.json
@@ -14,7 +14,7 @@
"files": [
{
"path": "registry/default/particles/p-table-3.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame } from \"@/registry/default/ui/frame\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst getColumns = (): ColumnDef[] => [\n {\n cell: ({ row }) => {\n const toggleHandler = row.getToggleSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n const toggleHandler = table.getToggleAllPageRowsSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nexport default function Particle() {\n const [tableData] = useState(data);\n const [rowSelection, setRowSelection] = useState({});\n\n const columns = useMemo(() => getColumns(), []);\n\n const table = useReactTable({\n columns,\n data: tableData,\n enableRowSelection: true,\n getCoreRowModel: getCoreRowModel(),\n onRowSelectionChange: setRowSelection,\n state: {\n rowSelection,\n },\n });\n\n const totalBudget = tableData.reduce(\n (sum, project) => sum + project.budget,\n 0,\n );\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame } from \"@/registry/default/ui/frame\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst getColumns = (): ColumnDef[] => [\n {\n cell: ({ row }) => {\n const toggleHandler = row.getToggleSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n const toggleHandler = table.getToggleAllPageRowsSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nexport default function Particle() {\n const [tableData] = useState(data);\n const [rowSelection, setRowSelection] = useState({});\n\n const columns = useMemo(() => getColumns(), []);\n\n const table = useTable({\n columns,\n data: tableData,\n enableRowSelection: true,\n features,\n onRowSelectionChange: setRowSelection,\n state: {\n rowSelection,\n },\n });\n\n const totalBudget = tableData.reduce(\n (sum, project) => sum + project.budget,\n 0,\n );\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/public/r/p-table-4.json b/apps/ui/public/r/p-table-4.json
index 34dc508a6..3909b5a11 100644
--- a/apps/ui/public/r/p-table-4.json
+++ b/apps/ui/public/r/p-table-4.json
@@ -18,7 +18,7 @@
"files": [
{
"path": "registry/default/particles/p-table-4.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame, FrameFooter } from \"@/registry/default/ui/frame\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"departureTime\",\n },\n ]);\n\n const table = useReactTable({\n columns,\n data: flights,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.getState().pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.getState().pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.getState().pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.getState().pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.getState().pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n type SortingState,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame, FrameFooter } from \"@/registry/default/ui/frame\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"departureTime\",\n },\n ]);\n\n const table = useTable({\n columns,\n data: flights,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.state.pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/public/r/p-table-6.json b/apps/ui/public/r/p-table-6.json
index 71cbff9a3..106de9dd9 100644
--- a/apps/ui/public/r/p-table-6.json
+++ b/apps/ui/public/r/p-table-6.json
@@ -14,7 +14,7 @@
"files": [
{
"path": "registry/default/particles/p-table-6.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { CardFrame } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst getColumns = (): ColumnDef[] => [\n {\n cell: ({ row }) => {\n const toggleHandler = row.getToggleSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n const toggleHandler = table.getToggleAllPageRowsSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nexport default function Particle() {\n const [tableData] = useState(data);\n const [rowSelection, setRowSelection] = useState({});\n\n const columns = useMemo(() => getColumns(), []);\n\n const table = useReactTable({\n columns,\n data: tableData,\n enableRowSelection: true,\n getCoreRowModel: getCoreRowModel(),\n onRowSelectionChange: setRowSelection,\n state: {\n rowSelection,\n },\n });\n\n const totalBudget = tableData.reduce(\n (sum, project) => sum + project.budget,\n 0,\n );\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { CardFrame } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst getColumns = (): ColumnDef[] => [\n {\n cell: ({ row }) => {\n const toggleHandler = row.getToggleSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n const toggleHandler = table.getToggleAllPageRowsSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nexport default function Particle() {\n const [tableData] = useState(data);\n const [rowSelection, setRowSelection] = useState({});\n\n const columns = useMemo(() => getColumns(), []);\n\n const table = useTable({\n columns,\n data: tableData,\n enableRowSelection: true,\n features,\n onRowSelectionChange: setRowSelection,\n state: {\n rowSelection,\n },\n });\n\n const totalBudget = tableData.reduce(\n (sum, project) => sum + project.budget,\n 0,\n );\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/public/r/p-table-8.json b/apps/ui/public/r/p-table-8.json
index a0c2e9fc5..4f4c50180 100644
--- a/apps/ui/public/r/p-table-8.json
+++ b/apps/ui/public/r/p-table-8.json
@@ -18,7 +18,7 @@
"files": [
{
"path": "registry/default/particles/p-table-8.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { CardFrame, CardFrameFooter } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"departureTime\",\n },\n ]);\n\n const table = useReactTable({\n columns,\n data: flights,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.getState().pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.getState().pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.getState().pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.getState().pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.getState().pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n type SortingState,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { CardFrame, CardFrameFooter } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"departureTime\",\n },\n ]);\n\n const table = useTable({\n columns,\n data: flights,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.state.pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/registry/default/particles/p-table-3.tsx b/apps/ui/registry/default/particles/p-table-3.tsx
index 07f1e0c00..9ab526ef6 100644
--- a/apps/ui/registry/default/particles/p-table-3.tsx
+++ b/apps/ui/registry/default/particles/p-table-3.tsx
@@ -2,9 +2,11 @@
import {
type ColumnDef,
+ columnVisibilityFeature,
flexRender,
- getCoreRowModel,
- useReactTable,
+ rowSelectionFeature,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import type React from "react";
import { useMemo, useState } from "react";
@@ -89,7 +91,12 @@ const getStatusColor = (status: Project["status"]) => {
}
};
-const getColumns = (): ColumnDef[] => [
+const features = tableFeatures({
+ columnVisibilityFeature,
+ rowSelectionFeature,
+});
+
+const getColumns = (): ColumnDef[] => [
{
cell: ({ row }) => {
const toggleHandler = row.getToggleSelectedHandler();
@@ -108,7 +115,6 @@ const getColumns = (): ColumnDef[] => [
/>
);
},
- enableSorting: false,
header: ({ table }) => {
const isAllSelected = table.getIsAllPageRowsSelected();
const isSomeSelected = table.getIsSomePageRowsSelected();
@@ -179,11 +185,11 @@ export default function Particle() {
const columns = useMemo(() => getColumns(), []);
- const table = useReactTable({
+ const table = useTable({
columns,
data: tableData,
enableRowSelection: true,
- getCoreRowModel: getCoreRowModel(),
+ features,
onRowSelectionChange: setRowSelection,
state: {
rowSelection,
diff --git a/apps/ui/registry/default/particles/p-table-4.tsx b/apps/ui/registry/default/particles/p-table-4.tsx
index 7f09c9dd8..d05cdccf2 100644
--- a/apps/ui/registry/default/particles/p-table-4.tsx
+++ b/apps/ui/registry/default/particles/p-table-4.tsx
@@ -2,13 +2,20 @@
import {
type ColumnDef,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ createPaginatedRowModel,
+ createSortedRowModel,
flexRender,
- getCoreRowModel,
- getPaginationRowModel,
- getSortedRowModel,
type PaginationState,
+ rowPaginationFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
type SortingState,
- useReactTable,
+ sortFn_alphanumeric,
+ sortFn_text,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from "lucide-react";
import { useState } from "react";
@@ -67,7 +74,21 @@ const getStatusColor = (status: Flight["status"]) => {
}
};
-const columns: ColumnDef[] = [
+const features = tableFeatures({
+ columnSizingFeature,
+ columnVisibilityFeature,
+ rowPaginationFeature,
+ paginatedRowModel: createPaginatedRowModel(),
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
+const columns: ColumnDef[] = [
{
cell: ({ row }) => (
Viewing
{
- const start = i * table.getState().pagination.pageSize + 1;
+ const start = i * table.state.pagination.pageSize + 1;
const end = Math.min(
- (i + 1) * table.getState().pagination.pageSize,
+ (i + 1) * table.state.pagination.pageSize,
table.getRowCount(),
);
const pageNum = i + 1;
@@ -313,7 +332,7 @@ export default function Particle() {
onValueChange={(value) => {
table.setPageIndex((value as number) - 1);
}}
- value={table.getState().pagination.pageIndex + 1}
+ value={table.state.pagination.pageIndex + 1}
>
{Array.from({ length: table.getPageCount() }, (_, i) => {
- const start = i * table.getState().pagination.pageSize + 1;
+ const start = i * table.state.pagination.pageSize + 1;
const end = Math.min(
- (i + 1) * table.getState().pagination.pageSize,
+ (i + 1) * table.state.pagination.pageSize,
table.getRowCount(),
);
const pageNum = i + 1;
diff --git a/apps/ui/registry/default/particles/p-table-6.tsx b/apps/ui/registry/default/particles/p-table-6.tsx
index de2fcdc61..b3b8bbb01 100644
--- a/apps/ui/registry/default/particles/p-table-6.tsx
+++ b/apps/ui/registry/default/particles/p-table-6.tsx
@@ -2,9 +2,11 @@
import {
type ColumnDef,
+ columnVisibilityFeature,
flexRender,
- getCoreRowModel,
- useReactTable,
+ rowSelectionFeature,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import type React from "react";
import { useMemo, useState } from "react";
@@ -89,7 +91,12 @@ const getStatusColor = (status: Project["status"]) => {
}
};
-const getColumns = (): ColumnDef[] => [
+const features = tableFeatures({
+ columnVisibilityFeature,
+ rowSelectionFeature,
+});
+
+const getColumns = (): ColumnDef[] => [
{
cell: ({ row }) => {
const toggleHandler = row.getToggleSelectedHandler();
@@ -108,7 +115,6 @@ const getColumns = (): ColumnDef[] => [
/>
);
},
- enableSorting: false,
header: ({ table }) => {
const isAllSelected = table.getIsAllPageRowsSelected();
const isSomeSelected = table.getIsSomePageRowsSelected();
@@ -179,11 +185,11 @@ export default function Particle() {
const columns = useMemo(() => getColumns(), []);
- const table = useReactTable({
+ const table = useTable({
columns,
data: tableData,
enableRowSelection: true,
- getCoreRowModel: getCoreRowModel(),
+ features,
onRowSelectionChange: setRowSelection,
state: {
rowSelection,
diff --git a/apps/ui/registry/default/particles/p-table-8.tsx b/apps/ui/registry/default/particles/p-table-8.tsx
index d8e5d2990..629b7d43a 100644
--- a/apps/ui/registry/default/particles/p-table-8.tsx
+++ b/apps/ui/registry/default/particles/p-table-8.tsx
@@ -2,13 +2,20 @@
import {
type ColumnDef,
+ columnSizingFeature,
+ columnVisibilityFeature,
+ createPaginatedRowModel,
+ createSortedRowModel,
flexRender,
- getCoreRowModel,
- getPaginationRowModel,
- getSortedRowModel,
type PaginationState,
+ rowPaginationFeature,
+ rowSelectionFeature,
+ rowSortingFeature,
type SortingState,
- useReactTable,
+ sortFn_alphanumeric,
+ sortFn_text,
+ tableFeatures,
+ useTable,
} from "@tanstack/react-table";
import { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from "lucide-react";
import { useState } from "react";
@@ -67,7 +74,21 @@ const getStatusColor = (status: Flight["status"]) => {
}
};
-const columns: ColumnDef[] = [
+const features = tableFeatures({
+ columnSizingFeature,
+ columnVisibilityFeature,
+ rowPaginationFeature,
+ paginatedRowModel: createPaginatedRowModel(),
+ rowSelectionFeature,
+ rowSortingFeature,
+ sortedRowModel: createSortedRowModel(),
+ sortFns: {
+ alphanumeric: sortFn_alphanumeric,
+ text: sortFn_text,
+ },
+});
+
+const columns: ColumnDef[] = [
{
cell: ({ row }) => (
Viewing
{
- const start = i * table.getState().pagination.pageSize + 1;
+ const start = i * table.state.pagination.pageSize + 1;
const end = Math.min(
- (i + 1) * table.getState().pagination.pageSize,
+ (i + 1) * table.state.pagination.pageSize,
table.getRowCount(),
);
const pageNum = i + 1;
@@ -313,7 +332,7 @@ export default function Particle() {
onValueChange={(value) => {
table.setPageIndex((value as number) - 1);
}}
- value={table.getState().pagination.pageIndex + 1}
+ value={table.state.pagination.pageIndex + 1}
>
{Array.from({ length: table.getPageCount() }, (_, i) => {
- const start = i * table.getState().pagination.pageSize + 1;
+ const start = i * table.state.pagination.pageSize + 1;
const end = Math.min(
- (i + 1) * table.getState().pagination.pageSize,
+ (i + 1) * table.state.pagination.pageSize,
table.getRowCount(),
);
const pageNum = i + 1;
diff --git a/bun.lock b/bun.lock
index 4812e6546..4f31f428d 100644
--- a/bun.lock
+++ b/bun.lock
@@ -22,7 +22,7 @@
"@dnd-kit/utilities": "^3.2.2",
"@hugeicons/core-free-icons": "^2.0.0",
"@hugeicons/react": "^1.1.1",
- "@tanstack/react-table": "^8.21.3",
+ "@tanstack/react-table": "^9.2.4",
"dompurify": "^3.3.1",
"lucide-react": "^0.555.0",
"marked": "^17.0.1",
@@ -55,7 +55,7 @@
"@origin-space/image-cropper": "^0.1.9",
"@radix-ui/react-icons": "^1.3.2",
"@remixicon/react": "^4.7.0",
- "@tanstack/react-table": "^8.21.3",
+ "@tanstack/react-table": "^9.2.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "1.1.1",
@@ -110,7 +110,7 @@
"@hugeicons/core-free-icons": "^2.0.0",
"@hugeicons/react": "^1.1.1",
"@remixicon/react": "^4.7.0",
- "@tanstack/react-table": "^8.21.3",
+ "@tanstack/react-table": "^9.2.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
@@ -936,9 +936,13 @@
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.17", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.17", "@tailwindcss/oxide": "4.1.17", "postcss": "^8.4.41", "tailwindcss": "4.1.17" } }, "sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw=="],
- "@tanstack/react-table": ["@tanstack/react-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "react": "19.2.0", "react-dom": "19.2.0" } }, "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww=="],
+ "@tanstack/react-store": ["@tanstack/react-store@0.11.1", "", { "dependencies": { "@tanstack/store": "0.11.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-HaIGKI3YLmjBYIvy5DFDY23oNaYZIsTZfngey07Uh5iLVJgM3bIGCnZeOFOqzjFld9JHWcaHJnasD/bKoGKwJQ=="],
- "@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="],
+ "@tanstack/react-table": ["@tanstack/react-table@9.2.4", "", { "dependencies": { "@tanstack/react-store": "^0.11.1", "@tanstack/table-core": "9.2.4" }, "peerDependencies": { "react": ">=18" } }, "sha512-Rzp1Q4e0/nIgEjmISYR5HeEgLTNtrG+C7NFZf/AbCxPO5hg+zC3yNGwcoECigUk8SFzzvhXbd2rFdtP2ZiGrfA=="],
+
+ "@tanstack/store": ["@tanstack/store@0.11.1", "", {}, "sha512-mzTOBhypOuDJAy/D8n2MfUZ1HFkXnmSETviRyhqEC8LUE7/IZQExOTxMANj3KjTofYTkFNpBY67qaVrT41YccA=="],
+
+ "@tanstack/table-core": ["@tanstack/table-core@9.2.4", "", { "dependencies": { "@tanstack/store": "^0.11.1" } }, "sha512-GwdDyGGr6UXAtubF14yAwcXvdaogqfsQgIk89Suebjxob/Rjq2xvfmXsjDF1rQmKmhHsJm9TOY7myxv3i6geJw=="],
"@tootallnate/quickjs-emscripten": ["@tootallnate/quickjs-emscripten@0.23.0", "", {}, "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="],
@@ -2630,10 +2634,6 @@
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
- "@tanstack/react-table/react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
-
- "@tanstack/react-table/react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "0.27.0" }, "peerDependencies": { "react": "19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="],
-
"@ts-morph/common/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
"@turbo/gen/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="],
From f5f0e3908a0e6734ac89e6cfa67444f4f7fb6ff7 Mon Sep 17 00:00:00 2001
From: pasqualevitiello
Date: Sun, 6 Sep 2026 12:40:21 +0200
Subject: [PATCH 2/3] perf: optimize TanStack Table state updates
---
.../members/members-page-client.tsx | 403 +++++++++---------
.../[id]/members/team-members-page-client.tsx | 224 +++++-----
apps/origin/public/r/comp-477.json | 2 +-
apps/origin/public/r/comp-478.json | 2 +-
apps/origin/public/r/comp-479.json | 2 +-
apps/origin/public/r/comp-480.json | 2 +-
apps/origin/public/r/comp-481.json | 2 +-
apps/origin/public/r/comp-482.json | 2 +-
apps/origin/public/r/comp-483.json | 2 +-
apps/origin/public/r/comp-484.json | 2 +-
apps/origin/public/r/comp-485.json | 2 +-
.../registry/default/components/comp-477.tsx | 13 +-
.../registry/default/components/comp-478.tsx | 41 +-
.../registry/default/components/comp-479.tsx | 44 +-
.../registry/default/components/comp-480.tsx | 40 +-
.../registry/default/components/comp-481.tsx | 45 +-
.../registry/default/components/comp-482.tsx | 18 +-
.../registry/default/components/comp-483.tsx | 49 ++-
.../registry/default/components/comp-484.tsx | 49 ++-
.../registry/default/components/comp-485.tsx | 59 ++-
apps/ui/public/r/p-table-3.json | 2 +-
apps/ui/public/r/p-table-4.json | 2 +-
apps/ui/public/r/p-table-6.json | 2 +-
apps/ui/public/r/p-table-8.json | 2 +-
.../registry/default/particles/p-table-3.tsx | 65 +--
.../registry/default/particles/p-table-4.tsx | 48 +--
.../registry/default/particles/p-table-6.tsx | 65 +--
.../registry/default/particles/p-table-8.tsx | 48 +--
28 files changed, 595 insertions(+), 642 deletions(-)
diff --git a/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx b/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx
index d84dbfece..97ab05926 100644
--- a/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx
+++ b/apps/examples/calcom/app/(dashboard)/members/members-page-client.tsx
@@ -41,7 +41,6 @@ import { cn } from "@coss/ui/lib/utils";
import {
type Column,
type ColumnDef,
- type ColumnSizingState,
columnFilteringFeature,
columnPinningFeature,
columnResizingFeature,
@@ -624,10 +623,8 @@ export function MembersPageClient() {
const [columnVisibility, setColumnVisibility] = useState(
DEFAULT_COLUMN_VISIBILITY,
);
- const [columnSizing, setColumnSizing] = useState({});
const tableContainerRef = useRef(null);
const [containerWidth, setContainerWidth] = useState(0);
- const [rowSelection, setRowSelection] = useState({});
const [sorting, setSorting] = useState([
{ desc: false, id: "name" },
]);
@@ -692,34 +689,25 @@ export function MembersPageClient() {
return () => observer.disconnect();
}, []);
- const table = useTable({
- columnResizeMode: "onChange",
- columns,
- data: filteredMembers,
- enableRowSelection: true,
- enableSortingRemoval: false,
- features,
- getRowId: (row) => row.id,
- initialState: {
- columnPinning: INITIAL_COLUMN_PINNING,
- },
- onColumnSizingChange: setColumnSizing,
- onRowSelectionChange: setRowSelection,
- onSortingChange: setSorting,
- state: {
- columnSizing,
- rowSelection,
- sorting,
+ const table = useTable(
+ {
+ columnResizeMode: "onChange",
+ columns,
+ data: filteredMembers,
+ enableRowSelection: true,
+ enableSortingRemoval: false,
+ features,
+ getRowId: (row) => row.id,
+ initialState: {
+ columnPinning: INITIAL_COLUMN_PINNING,
+ },
+ onSortingChange: setSorting,
+ state: {
+ sorting,
+ },
},
- });
-
- const headers = table.getHeaderGroups()[0]?.headers ?? [];
- const columnsTotalSize = table.getCenterTotalSize();
- const tableWidth =
- containerWidth > 0
- ? Math.max(containerWidth + 2, columnsTotalSize)
- : columnsTotalSize;
- const fillerColumnId = getFillerColumnId(headers);
+ () => null,
+ );
return (
<>
@@ -837,175 +825,204 @@ export function MembersPageClient() {
- ({
+ columnSizing: state.columnSizing,
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ })}
>
-
- }
- className="table-fixed [--border:color-mix(in_srgb,var(--color-black)_8%,color-mix(in_srgb,var(--color-black)_3%,var(--background)))] dark:[--border:color-mix(in_srgb,var(--color-white)_6%,color-mix(in_srgb,var(--color-white)_4.6%,var(--background)))]"
- variant="card"
- >
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {headerGroup.headers.map((header) => (
-
- {header.isPlaceholder ? null : header.column.getCanSort() ? (
- {
- if (event.key === "Enter" || event.key === " ") {
- event.preventDefault();
- header.column.getToggleSortingHandler()?.(event);
+ {() => {
+ const headers = table.getHeaderGroups()[0]?.headers ?? [];
+ const columnsTotalSize = table.getCenterTotalSize();
+ const tableWidth =
+ containerWidth > 0
+ ? Math.max(containerWidth + 2, columnsTotalSize)
+ : columnsTotalSize;
+ const fillerColumnId = getFillerColumnId(headers);
+
+ return (
+
+
+ }
+ className="table-fixed [--border:color-mix(in_srgb,var(--color-black)_8%,color-mix(in_srgb,var(--color-black)_3%,var(--background)))] dark:[--border:color-mix(in_srgb,var(--color-white)_6%,color-mix(in_srgb,var(--color-white)_4.6%,var(--background)))]"
+ variant="card"
+ >
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => (
+
-
- {flexRender(
- header.column.columnDef.header,
- header.getContext(),
+ className="relative z-1 select-none bg-[color-mix(in_srgb,var(--color-black)_3%,var(--background))] before:pointer-events-none before:absolute before:inset-y-0 before:z-1 not-data-pinned:before:hidden before:w-4 before:from-[color-mix(in_srgb,var(--color-black)_3%,var(--background))] before:to-transparent data-[pinned=start]:before:start-full data-[pinned=end]:before:end-full in-data-overflow-x-end:data-[pinned=end]:before:bg-linear-to-l last:*:data-[slot=column-resize-handle]:opacity-0 data-[pinned=start]:max-md:before:hidden data-[pinned=start]:md:sticky data-[pinned=start]:md:start-(--pinned-start-offset) in-data-overflow-x-start:data-[pinned=start]:md:before:bg-linear-to-r dark:bg-[color-mix(in_srgb,var(--color-white)_4.6%,var(--background))] dark:before:from-[color-mix(in_srgb,var(--color-white)_4.6%,var(--background))]"
+ colSpan={header.colSpan}
+ key={header.id}
+ {...getPinnedDataAttribute(header.column)}
+ style={{
+ ...getPinningStyles(header.column),
+ width: getColumnDisplayWidth({
+ columnId: header.column.id,
+ columnsTotalSize,
+ fillerColumnId,
+ headers,
+ size: header.getSize(),
+ tableWidth,
+ }),
+ }}
+ >
+ {header.isPlaceholder ? null : header.column.getCanSort() ? (
+ {
+ if (
+ event.key === "Enter" ||
+ event.key === " "
+ ) {
+ event.preventDefault();
+ header.column.getToggleSortingHandler()?.(
+ event,
+ );
+ }
+ }}
+ role="button"
+ tabIndex={0}
+ >
+
+ {flexRender(
+ header.column.columnDef.header,
+ header.getContext(),
+ )}
+
+ {{
+ asc: (
+
+ ),
+ desc: (
+
+ ),
+ }[header.column.getIsSorted() as string] ??
+ null}
+
+ ) : (
+
+ {flexRender(
+ header.column.columnDef.header,
+ header.getContext(),
+ )}
+
)}
-
- {{
- asc: (
- header.column.resetSize()}
+ onMouseDown={header.getResizeHandler()}
+ style={{ cursor: "col-resize" }}
+ onTouchStart={header.getResizeHandler()}
/>
- ),
- desc: (
-
- ),
- }[header.column.getIsSorted() as string] ?? null}
-
- ) : (
-
- {flexRender(
- header.column.columnDef.header,
- header.getContext(),
- )}
-
- )}
- {header.column.getCanResize() ? (
- header.column.resetSize()}
- onMouseDown={header.getResizeHandler()}
- style={{ cursor: "col-resize" }}
- onTouchStart={header.getResizeHandler()}
- />
- ) : null}
-
- ))}
-
- ))}
-
-
- {table.getRowModel().rows.length ? (
- table.getRowModel().rows.map((row) => (
- {
- if (shouldIgnoreRowSelectionClick(event.target)) return;
- row.toggleSelected();
- }}
- >
- {row.getVisibleCells().map((cell) => (
-
- {flexRender(
- cell.column.columnDef.cell,
- cell.getContext(),
- )}
-
+ ) : null}
+
+ ))}
+
))}
-
- ))
- ) : (
-
-
- No members found.
-
-
- )}
-
-
-
-
- {table.getFilteredSelectedRowModel().rows.length > 0 ? (
- <>
-
- {table.getFilteredSelectedRowModel().rows.length}
- {" "}
- of{" "}
-
- {table.getFilteredRowModel().rows.length}
- {" "}
- selected
- >
- ) : (
- <>
-
- {table.getFilteredRowModel().rows.length}
- {" "}
- members
- >
- )}
-
-
-
+
+
+ {table.getRowModel().rows.length ? (
+ table.getRowModel().rows.map((row) => (
+ {
+ if (shouldIgnoreRowSelectionClick(event.target))
+ return;
+ row.toggleSelected();
+ }}
+ >
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(
+ cell.column.columnDef.cell,
+ cell.getContext(),
+ )}
+
+ ))}
+
+ ))
+ ) : (
+
+
+ No members found.
+
+
+ )}
+
+
+
+
+ {table.getFilteredSelectedRowModel().rows.length > 0 ? (
+ <>
+
+ {table.getFilteredSelectedRowModel().rows.length}
+ {" "}
+ of{" "}
+
+ {table.getFilteredRowModel().rows.length}
+ {" "}
+ selected
+ >
+ ) : (
+ <>
+
+ {table.getFilteredRowModel().rows.length}
+ {" "}
+ members
+ >
+ )}
+
+
+
+ );
+ }}
+
>
);
diff --git a/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx b/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx
index 2624827a7..7d2cca51f 100644
--- a/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx
+++ b/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx
@@ -348,7 +348,6 @@ export function TeamMembersPageClient() {
const [searchValue, setSearchValue] = useState("");
const [showRoleColumn, setShowRoleColumn] = useState(true);
const [showLastActiveColumn, setShowLastActiveColumn] = useState(true);
- const [rowSelection, setRowSelection] = useState({});
const [sorting, setSorting] = useState([
{ desc: false, id: "name" },
]);
@@ -407,20 +406,21 @@ export function TeamMembersPageClient() {
});
}, [showLastActiveColumn, showRoleColumn]);
- const table = useTable({
- columns,
- data: filteredMembers,
- enableRowSelection: true,
- enableSortingRemoval: false,
- features,
- getRowId: (row) => row.id,
- onRowSelectionChange: setRowSelection,
- onSortingChange: setSorting,
- state: {
- rowSelection,
- sorting,
+ const table = useTable(
+ {
+ columns,
+ data: filteredMembers,
+ enableRowSelection: true,
+ enableSortingRemoval: false,
+ features,
+ getRowId: (row) => row.id,
+ onSortingChange: setSorting,
+ state: {
+ sorting,
+ },
},
- });
+ () => null,
+ );
return (
<>
@@ -538,100 +538,114 @@ export function TeamMembersPageClient() {
-
-
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {headerGroup.headers.map((header) => {
- const columnSize = header.column.getSize();
-
- return (
-
- {header.isPlaceholder ? null : header.column.getCanSort() ? (
- {
- if (event.key === "Enter" || event.key === " ") {
- event.preventDefault();
- header.column.getToggleSortingHandler()?.(
- event,
- );
- }
- }}
- role="button"
- tabIndex={0}
- >
- {flexRender(
+
({
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ })}
+ >
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => {
+ const columnSize = header.column.getSize();
+
+ return (
+
+ {header.isPlaceholder ? null : header.column.getCanSort() ? (
+ {
+ if (
+ event.key === "Enter" ||
+ event.key === " "
+ ) {
+ event.preventDefault();
+ header.column.getToggleSortingHandler()?.(
+ event,
+ );
+ }
+ }}
+ role="button"
+ tabIndex={0}
+ >
+ {flexRender(
+ header.column.columnDef.header,
+ header.getContext(),
+ )}
+ {{
+ asc: (
+
+ ),
+ desc: (
+
+ ),
+ }[header.column.getIsSorted() as string] ?? null}
+
+ ) : (
+ flexRender(
header.column.columnDef.header,
header.getContext(),
- )}
- {{
- asc: (
-
- ),
- desc: (
-
- ),
- }[header.column.getIsSorted() as string] ?? null}
-
- ) : (
- flexRender(
- header.column.columnDef.header,
- header.getContext(),
- )
- )}
-
- );
- })}
-
- ))}
-
-
- {table.getRowModel().rows.length ? (
- table.getRowModel().rows.map((row) => (
-
- {row.getVisibleCells().map((cell) => (
-
- {flexRender(
- cell.column.columnDef.cell,
- cell.getContext(),
- )}
-
- ))}
+ )
+ )}
+
+ );
+ })}
- ))
- ) : (
-
-
- No members found.
-
-
- )}
-
-
-
+ ))}
+
+
+ {table.getRowModel().rows.length ? (
+ table.getRowModel().rows.map((row) => (
+
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(
+ cell.column.columnDef.cell,
+ cell.getContext(),
+ )}
+
+ ))}
+
+ ))
+ ) : (
+
+
+ No members found.
+
+
+ )}
+
+
+
+
>
);
diff --git a/apps/origin/public/r/comp-477.json b/apps/origin/public/r/comp-477.json
index 2b81959e8..e150ef997 100644
--- a/apps/origin/public/r/comp-477.json
+++ b/apps/origin/public/r/comp-477.json
@@ -13,7 +13,7 @@
"files": [
{
"path": "registry/default/components/comp-477.tsx",
- "content": "\"use client\";\n\nimport {\n columnVisibilityFeature,\n type ColumnDef,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n features,\n });\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total \n \n {new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(data.reduce((total, item) => total + item.balance, 0))}\n \n \n \n
\n
\n Basic data table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable(\n {\n columns,\n data,\n features,\n },\n (state) => ({ rowSelection: state.rowSelection }),\n );\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total \n \n {new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(data.reduce((total, item) => total + item.balance, 0))}\n \n \n \n
\n
\n Basic data table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-478.json b/apps/origin/public/r/comp-478.json
index 5087227f0..93c0f9222 100644
--- a/apps/origin/public/r/comp-478.json
+++ b/apps/origin/public/r/comp-478.json
@@ -15,7 +15,7 @@
"files": [
{
"path": "registry/default/components/comp-478.tsx",
- "content": "\"use client\";\n\nimport {\n columnFacetingFeature,\n columnFilteringFeature,\n columnVisibilityFeature,\n type Column,\n type ColumnDef,\n type ColumnFiltersState,\n createFacetedMinMaxValues,\n createFacetedRowModel,\n createFacetedUniqueValues,\n createFilteredRowModel,\n createSortedRowModel,\n filterFn_includesString,\n filterFn_inNumberRange,\n flexRender,\n metaHelper,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronUpIcon,\n ExternalLinkIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n keyword: string;\n intents: Array<\n \"Informational\" | \"Navigational\" | \"Commercial\" | \"Transactional\"\n >;\n volume: number;\n cpc: number;\n traffic: number;\n link: string;\n};\n\nconst features = tableFeatures({\n columnFilteringFeature,\n columnFacetingFeature,\n columnVisibilityFeature,\n facetedMinMaxValues: createFacetedMinMaxValues(),\n facetedRowModel: createFacetedRowModel(),\n facetedUniqueValues: createFacetedUniqueValues(),\n filteredRowModel: createFilteredRowModel(),\n filterFns: {\n includesString: filterFn_includesString,\n inNumberRange: filterFn_inNumberRange,\n },\n columnMeta: metaHelper<{\n filterVariant?: \"text\" | \"range\" | \"select\";\n }>(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"keyword\",\n cell: ({ row }) => (\n {row.getValue(\"keyword\")}
\n ),\n header: \"Keyword\",\n },\n {\n accessorKey: \"intents\",\n cell: ({ row }) => {\n const intents = row.getValue(\"intents\") as string[];\n return (\n \n {intents.map((intent) => {\n const styles = {\n Commercial: \"bg-amber-400/20 text-amber-500\",\n Informational: \"bg-indigo-400/20 text-indigo-500\",\n Navigational: \"bg-emerald-400/20 text-emerald-500\",\n Transactional: \"bg-rose-400/20 text-rose-500\",\n }[intent];\n\n return (\n
\n {intent.charAt(0)}\n
\n );\n })}\n
\n );\n },\n enableSorting: false,\n filterFn: (row, id, filterValue) => {\n const rowValue = row.getValue(id);\n return Array.isArray(rowValue) && rowValue.includes(filterValue);\n },\n header: \"Intents\",\n meta: {\n filterVariant: \"select\",\n },\n },\n {\n accessorKey: \"volume\",\n cell: ({ row }) => {\n const volume = Number.parseInt(row.getValue(\"volume\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(volume);\n },\n header: \"Volume\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"cpc\",\n cell: ({ row }) => ${row.getValue(\"cpc\")}
,\n header: \"CPC\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"traffic\",\n cell: ({ row }) => {\n const traffic = Number.parseInt(row.getValue(\"traffic\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(traffic);\n },\n header: \"Traffic\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"link\",\n cell: ({ row }) => (\n \n {row.getValue(\"link\")} \n \n ),\n enableSorting: false,\n header: \"Link\",\n },\n];\n\nconst items: Item[] = [\n {\n cpc: 2.5,\n id: \"1\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react components\",\n link: \"https://coss.com/origin\",\n traffic: 88,\n volume: 2507,\n },\n {\n cpc: 4.75,\n id: \"2\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"buy react templates\",\n link: \"https://coss.com/origin/input\",\n traffic: 65,\n volume: 1850,\n },\n {\n cpc: 3.25,\n id: \"3\",\n intents: [\"Informational\", \"Commercial\"],\n keyword: \"react ui library\",\n link: \"https://coss.com/origin/badge\",\n traffic: 112,\n volume: 3200,\n },\n {\n cpc: 1.95,\n id: \"4\",\n intents: [\"Transactional\"],\n keyword: \"tailwind components download\",\n link: \"https://coss.com/origin/alert\",\n traffic: 45,\n volume: 890,\n },\n {\n cpc: 5.5,\n id: \"5\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react dashboard template free\",\n link: \"https://coss.com/origin/tabs\",\n traffic: 156,\n volume: 4100,\n },\n {\n cpc: 1.25,\n id: \"6\",\n intents: [\"Informational\"],\n keyword: \"how to use react components\",\n link: \"https://coss.com/origin/table\",\n traffic: 42,\n volume: 1200,\n },\n {\n cpc: 6.8,\n id: \"7\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react ui kit premium\",\n link: \"https://coss.com/origin/avatar\",\n traffic: 28,\n volume: 760,\n },\n {\n cpc: 1.8,\n id: \"8\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react component documentation\",\n link: \"https://coss.com/origin\",\n traffic: 35,\n volume: 950,\n },\n];\n\nexport default function Component() {\n const [columnFilters, setColumnFilters] = useState([]);\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"traffic\",\n },\n ]);\n\n const table = useTable({\n columns,\n data: items,\n enableSortingRemoval: false,\n features,\n onColumnFiltersChange: setColumnFilters,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n sorting,\n },\n });\n\n const keywordColumn = table.getColumn(\"keyword\");\n const intentsColumn = table.getColumn(\"intents\");\n const volumeColumn = table.getColumn(\"volume\");\n const cpcColumn = table.getColumn(\"cpc\");\n const trafficColumn = table.getColumn(\"traffic\");\n\n return (\n \n {/* Filters */}\n
\n {/* Search input */}\n {keywordColumn && (\n
\n \n
\n )}\n {/* Intents select */}\n {intentsColumn && (\n
\n \n
\n )}\n {/* Volume inputs */}\n {volumeColumn && (\n
\n \n
\n )}\n {/* CPC inputs */}\n {cpcColumn && (\n
\n \n
\n )}\n {/* Traffic inputs */}\n {trafficColumn && (\n
\n \n
\n )}\n
\n\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Data table with filters made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction Filter({\n column,\n}: {\n column: Column;\n}) {\n const id = useId();\n const columnFilterValue = column.getFilterValue();\n const { filterVariant } = column.columnDef.meta ?? {};\n const columnHeader =\n typeof column.columnDef.header === \"string\" ? column.columnDef.header : \"\";\n const sortedUniqueValues = useMemo(() => {\n if (filterVariant === \"range\") return [];\n\n // Get all unique values from the column\n const values = Array.from(column.getFacetedUniqueValues().keys());\n\n // If the values are arrays, flatten them and get unique items\n const flattenedValues = values.reduce((acc: string[], curr) => {\n if (Array.isArray(curr)) {\n acc.push(...curr);\n } else {\n acc.push(curr);\n }\n return acc;\n }, []);\n\n // Get unique values and sort them\n return Array.from(new Set(flattenedValues)).sort();\n }, [column, filterVariant]);\n\n if (filterVariant === \"range\") {\n return (\n \n );\n }\n\n if (filterVariant === \"select\") {\n return (\n \n {columnHeader} \n {\n column.setFilterValue(value === \"all\" ? undefined : value);\n }}\n value={columnFilterValue?.toString() ?? \"all\"}\n >\n \n \n \n \n All \n {sortedUniqueValues.map((value) => (\n \n {String(value)}\n \n ))}\n \n \n
\n );\n }\n\n return (\n \n
{columnHeader} \n
\n
column.setFilterValue(e.target.value)}\n placeholder={`Search ${columnHeader.toLowerCase()}`}\n type=\"text\"\n value={(columnFilterValue ?? \"\") as string}\n />\n
\n \n
\n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type Column,\n type ColumnDef,\n columnFacetingFeature,\n columnFilteringFeature,\n columnVisibilityFeature,\n createFacetedMinMaxValues,\n createFacetedRowModel,\n createFacetedUniqueValues,\n createFilteredRowModel,\n createSortedRowModel,\n filterFn_includesString,\n filterFn_inNumberRange,\n flexRender,\n metaHelper,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronUpIcon,\n ExternalLinkIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport { useId, useMemo } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n keyword: string;\n intents: Array<\n \"Informational\" | \"Navigational\" | \"Commercial\" | \"Transactional\"\n >;\n volume: number;\n cpc: number;\n traffic: number;\n link: string;\n};\n\nconst features = tableFeatures({\n columnFilteringFeature,\n columnFacetingFeature,\n columnVisibilityFeature,\n facetedMinMaxValues: createFacetedMinMaxValues(),\n facetedRowModel: createFacetedRowModel(),\n facetedUniqueValues: createFacetedUniqueValues(),\n filteredRowModel: createFilteredRowModel(),\n filterFns: {\n includesString: filterFn_includesString,\n inNumberRange: filterFn_inNumberRange,\n },\n columnMeta: metaHelper<{\n filterVariant?: \"text\" | \"range\" | \"select\";\n }>(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"keyword\",\n cell: ({ row }) => (\n {row.getValue(\"keyword\")}
\n ),\n header: \"Keyword\",\n },\n {\n accessorKey: \"intents\",\n cell: ({ row }) => {\n const intents = row.getValue(\"intents\") as string[];\n return (\n \n {intents.map((intent) => {\n const styles = {\n Commercial: \"bg-amber-400/20 text-amber-500\",\n Informational: \"bg-indigo-400/20 text-indigo-500\",\n Navigational: \"bg-emerald-400/20 text-emerald-500\",\n Transactional: \"bg-rose-400/20 text-rose-500\",\n }[intent];\n\n return (\n
\n {intent.charAt(0)}\n
\n );\n })}\n
\n );\n },\n enableSorting: false,\n filterFn: (row, id, filterValue) => {\n const rowValue = row.getValue(id);\n return Array.isArray(rowValue) && rowValue.includes(filterValue);\n },\n header: \"Intents\",\n meta: {\n filterVariant: \"select\",\n },\n },\n {\n accessorKey: \"volume\",\n cell: ({ row }) => {\n const volume = Number.parseInt(row.getValue(\"volume\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(volume);\n },\n header: \"Volume\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"cpc\",\n cell: ({ row }) => ${row.getValue(\"cpc\")}
,\n header: \"CPC\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"traffic\",\n cell: ({ row }) => {\n const traffic = Number.parseInt(row.getValue(\"traffic\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(traffic);\n },\n header: \"Traffic\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"link\",\n cell: ({ row }) => (\n \n {row.getValue(\"link\")} \n \n ),\n enableSorting: false,\n header: \"Link\",\n },\n];\n\nconst items: Item[] = [\n {\n cpc: 2.5,\n id: \"1\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react components\",\n link: \"https://coss.com/origin\",\n traffic: 88,\n volume: 2507,\n },\n {\n cpc: 4.75,\n id: \"2\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"buy react templates\",\n link: \"https://coss.com/origin/input\",\n traffic: 65,\n volume: 1850,\n },\n {\n cpc: 3.25,\n id: \"3\",\n intents: [\"Informational\", \"Commercial\"],\n keyword: \"react ui library\",\n link: \"https://coss.com/origin/badge\",\n traffic: 112,\n volume: 3200,\n },\n {\n cpc: 1.95,\n id: \"4\",\n intents: [\"Transactional\"],\n keyword: \"tailwind components download\",\n link: \"https://coss.com/origin/alert\",\n traffic: 45,\n volume: 890,\n },\n {\n cpc: 5.5,\n id: \"5\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react dashboard template free\",\n link: \"https://coss.com/origin/tabs\",\n traffic: 156,\n volume: 4100,\n },\n {\n cpc: 1.25,\n id: \"6\",\n intents: [\"Informational\"],\n keyword: \"how to use react components\",\n link: \"https://coss.com/origin/table\",\n traffic: 42,\n volume: 1200,\n },\n {\n cpc: 6.8,\n id: \"7\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react ui kit premium\",\n link: \"https://coss.com/origin/avatar\",\n traffic: 28,\n volume: 760,\n },\n {\n cpc: 1.8,\n id: \"8\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react component documentation\",\n link: \"https://coss.com/origin\",\n traffic: 35,\n volume: 950,\n },\n];\n\nexport default function Component() {\n const table = useTable(\n {\n columns,\n data: items,\n enableSortingRemoval: false,\n features,\n initialState: {\n sorting: [\n {\n desc: false,\n id: \"traffic\",\n },\n ],\n },\n },\n (state) => ({\n columnFilters: state.columnFilters,\n rowSelection: state.rowSelection,\n sorting: state.sorting,\n }),\n );\n\n const keywordColumn = table.getColumn(\"keyword\");\n const intentsColumn = table.getColumn(\"intents\");\n const volumeColumn = table.getColumn(\"volume\");\n const cpcColumn = table.getColumn(\"cpc\");\n const trafficColumn = table.getColumn(\"traffic\");\n\n return (\n \n {/* Filters */}\n
\n {/* Search input */}\n {keywordColumn && (\n
\n \n
\n )}\n {/* Intents select */}\n {intentsColumn && (\n
\n \n
\n )}\n {/* Volume inputs */}\n {volumeColumn && (\n
\n \n
\n )}\n {/* CPC inputs */}\n {cpcColumn && (\n
\n \n
\n )}\n {/* Traffic inputs */}\n {trafficColumn && (\n
\n \n
\n )}\n
\n\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Data table with filters made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction Filter({\n column,\n}: {\n column: Column;\n}) {\n const id = useId();\n const columnFilterValue = column.getFilterValue();\n const { filterVariant } = column.columnDef.meta ?? {};\n const columnHeader =\n typeof column.columnDef.header === \"string\" ? column.columnDef.header : \"\";\n const sortedUniqueValues = useMemo(() => {\n if (filterVariant === \"range\") return [];\n\n // Get all unique values from the column\n const values = Array.from(column.getFacetedUniqueValues().keys());\n\n // If the values are arrays, flatten them and get unique items\n const flattenedValues = values.reduce((acc: string[], curr) => {\n if (Array.isArray(curr)) {\n acc.push(...curr);\n } else {\n acc.push(curr);\n }\n return acc;\n }, []);\n\n // Get unique values and sort them\n return Array.from(new Set(flattenedValues)).sort();\n }, [column, filterVariant]);\n\n if (filterVariant === \"range\") {\n return (\n \n );\n }\n\n if (filterVariant === \"select\") {\n return (\n \n {columnHeader} \n {\n column.setFilterValue(value === \"all\" ? undefined : value);\n }}\n value={columnFilterValue?.toString() ?? \"all\"}\n >\n \n \n \n \n All \n {sortedUniqueValues.map((value) => (\n \n {String(value)}\n \n ))}\n \n \n
\n );\n }\n\n return (\n \n
{columnHeader} \n
\n
column.setFilterValue(e.target.value)}\n placeholder={`Search ${columnHeader.toLowerCase()}`}\n type=\"text\"\n value={(columnFilterValue ?? \"\") as string}\n />\n
\n \n
\n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-479.json b/apps/origin/public/r/comp-479.json
index aaf05cde6..433acec77 100644
--- a/apps/origin/public/r/comp-479.json
+++ b/apps/origin/public/r/comp-479.json
@@ -11,7 +11,7 @@
"files": [
{
"path": "registry/default/components/comp-479.tsx",
- "content": "\"use client\";\n\nimport {\n columnResizingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n type ColumnDef,\n flexRender,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Excellent\" | \"Good\" | \"Average\" | \"Poor\";\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnResizingFeature,\n columnVisibilityFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n \n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n .cursor-col-resize]:opacity-0\"\n key={header.id}\n {...{\n colSpan: header.colSpan,\n style: {\n width: header.getSize(),\n },\n }}\n >\n {header.isPlaceholder ? null : (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n )}\n {header.column.getCanResize() && (\n header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Resizable and sortable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnResizingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Excellent\" | \"Good\" | \"Average\" | \"Poor\";\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnResizingFeature,\n columnVisibilityFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable(\n {\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n features,\n initialState: {\n sorting: [\n {\n desc: false,\n id: \"name\",\n },\n ],\n },\n },\n (state) => ({\n columnSizing: state.columnSizing,\n sorting: state.sorting,\n }),\n );\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n .cursor-col-resize]:opacity-0\"\n key={header.id}\n {...{\n colSpan: header.colSpan,\n style: {\n width: header.getSize(),\n },\n }}\n >\n {header.isPlaceholder ? null : (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n )}\n {header.column.getCanResize() && (\n header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Resizable and sortable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-480.json b/apps/origin/public/r/comp-480.json
index f8da1643a..6ff42c2a8 100644
--- a/apps/origin/public/r/comp-480.json
+++ b/apps/origin/public/r/comp-480.json
@@ -13,7 +13,7 @@
"files": [
{
"path": "registry/default/components/comp-480.tsx",
- "content": "\"use client\";\n\nimport {\n columnOrderingFeature,\n columnPinningFeature,\n columnResizingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n type Column,\n type ColumnDef,\n flexRender,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ArrowLeftToLineIcon,\n ArrowRightToLineIcon,\n EllipsisIcon,\n PinOffIcon,\n} from \"lucide-react\";\nimport { type CSSProperties, useEffect, useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Good\" | \"Very Good\" | \"Excellent\" | \"Outstanding\";\n};\n\nconst features = tableFeatures({\n columnOrderingFeature,\n columnPinningFeature,\n columnSizingFeature,\n columnResizingFeature,\n columnVisibilityFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\n// Helper function to compute pinning styles for columns\nconst getPinningStyles = (\n column: Column,\n): CSSProperties => {\n const isPinned = column.getIsPinned();\n return {\n insetInlineEnd:\n isPinned === \"end\" ? `${column.getAfter(\"end\")}px` : undefined,\n insetInlineStart:\n isPinned === \"start\" ? `${column.getStart(\"start\")}px` : undefined,\n position: isPinned ? \"sticky\" : \"relative\",\n width: column.getSize(),\n zIndex: isPinned ? 1 : 0,\n };\n};\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n \n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const { column } = header;\n const isPinned = column.getIsPinned();\n const isLastStartPinned =\n isPinned === \"start\" && column.getIsLastColumn(\"start\");\n const isFirstEndPinned =\n isPinned === \"end\" && column.getIsFirstColumn(\"end\");\n\n return (\n \n \n
\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {/* Pin/Unpin column controls with enhanced accessibility */}\n {!header.isPlaceholder &&\n header.column.getCanPin() &&\n (header.column.getIsPinned() ? (\n
header.column.pin(false)}\n size=\"icon\"\n title={`Unpin ${header.column.columnDef.header as string} column`}\n variant=\"ghost\"\n >\n \n \n ) : (\n
\n \n \n \n \n \n \n header.column.pin(\"start\")}\n >\n \n Stick to start\n \n header.column.pin(\"end\")}\n >\n \n Stick to end\n \n \n \n ))}\n {header.column.getCanResize() && (\n
header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n
\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => {\n const { column } = cell;\n const isPinned = column.getIsPinned();\n const isLastStartPinned =\n isPinned === \"start\" && column.getIsLastColumn(\"start\");\n const isFirstEndPinned =\n isPinned === \"end\" && column.getIsFirstColumn(\"end\");\n\n return (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n );\n })}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Pinnable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type Column,\n type ColumnDef,\n columnOrderingFeature,\n columnPinningFeature,\n columnResizingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n flexRender,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ArrowLeftToLineIcon,\n ArrowRightToLineIcon,\n EllipsisIcon,\n PinOffIcon,\n} from \"lucide-react\";\nimport { type CSSProperties, useEffect, useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Good\" | \"Very Good\" | \"Excellent\" | \"Outstanding\";\n};\n\nconst features = tableFeatures({\n columnOrderingFeature,\n columnPinningFeature,\n columnSizingFeature,\n columnResizingFeature,\n columnVisibilityFeature,\n});\n\n// Helper function to compute pinning styles for columns\nconst getPinningStyles = (\n column: Column,\n): CSSProperties => {\n const isPinned = column.getIsPinned();\n return {\n insetInlineEnd:\n isPinned === \"end\" ? `${column.getAfter(\"end\")}px` : undefined,\n insetInlineStart:\n isPinned === \"start\" ? `${column.getStart(\"start\")}px` : undefined,\n position: isPinned ? \"sticky\" : \"relative\",\n width: column.getSize(),\n zIndex: isPinned ? 1 : 0,\n };\n};\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable(\n {\n columnResizeMode: \"onChange\",\n columns,\n data,\n features,\n },\n (state) => ({\n columnPinning: state.columnPinning,\n columnSizing: state.columnSizing,\n }),\n );\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const { column } = header;\n const isPinned = column.getIsPinned();\n const isLastStartPinned =\n isPinned === \"start\" && column.getIsLastColumn(\"start\");\n const isFirstEndPinned =\n isPinned === \"end\" && column.getIsFirstColumn(\"end\");\n\n return (\n \n \n
\n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {/* Pin/Unpin column controls with enhanced accessibility */}\n {!header.isPlaceholder &&\n header.column.getCanPin() &&\n (header.column.getIsPinned() ? (\n
header.column.pin(false)}\n size=\"icon\"\n title={`Unpin ${header.column.columnDef.header as string} column`}\n variant=\"ghost\"\n >\n \n \n ) : (\n
\n \n \n \n \n \n \n header.column.pin(\"start\")}\n >\n \n Stick to start\n \n header.column.pin(\"end\")}\n >\n \n Stick to end\n \n \n \n ))}\n {header.column.getCanResize() && (\n
header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n
\n \n );\n })}\n \n ))}\n \n
\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => {\n const { column } = cell;\n const isPinned = column.getIsPinned();\n const isLastStartPinned =\n isPinned === \"start\" && column.getIsLastColumn(\"start\");\n const isFirstEndPinned =\n isPinned === \"end\" && column.getIsFirstColumn(\"end\");\n\n return (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n );\n })}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Pinnable columns made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-481.json b/apps/origin/public/r/comp-481.json
index 72b7b175b..885d04d0d 100644
--- a/apps/origin/public/r/comp-481.json
+++ b/apps/origin/public/r/comp-481.json
@@ -17,7 +17,7 @@
"files": [
{
"path": "registry/default/components/comp-481.tsx",
- "content": "\"use client\";\n\nimport {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n MouseSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { restrictToHorizontalAxis } from \"@dnd-kit/modifiers\";\nimport {\n arrayMove,\n horizontalListSortingStrategy,\n SortableContext,\n useSortable,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport {\n columnOrderingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n type Cell,\n type ColumnDef,\n flexRender,\n type Header,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, GripVerticalIcon } from \"lucide-react\";\nimport { type CSSProperties, useEffect, useId, useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnOrderingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n id: \"name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n id: \"email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n id: \"location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n id: \"status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n id: \"balance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n const [sorting, setSorting] = useState
([]);\n const [columnOrder, setColumnOrder] = useState(\n columns.map((column) => column.id as string),\n );\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onColumnOrderChange: setColumnOrder,\n onSortingChange: setSorting,\n state: {\n columnOrder,\n sorting,\n },\n });\n\n // reorder columns after drag & drop\n function handleDragEnd(event: DragEndEvent) {\n const { active, over } = event;\n if (active && over && active.id !== over.id) {\n setColumnOrder((columnOrder) => {\n const oldIndex = columnOrder.indexOf(active.id as string);\n const newIndex = columnOrder.indexOf(over.id as string);\n return arrayMove(columnOrder, oldIndex, newIndex); //this is just a splice util\n });\n }\n }\n\n const sensors = useSensors(\n useSensor(MouseSensor, {}),\n useSensor(TouchSensor, {}),\n useSensor(KeyboardSensor, {}),\n );\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n \n {headerGroup.headers.map((header) => (\n \n ))}\n \n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n \n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n Draggable columns made with{\" \"}\n \n TanStack Table\n {\" \"}\n and{\" \"}\n \n dnd kit\n \n
\n \n );\n}\n\nconst DraggableTableHeader = ({\n header,\n}: {\n header: Header;\n}) => {\n const {\n attributes,\n isDragging,\n listeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({\n id: header.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n whiteSpace: \"nowrap\",\n width: header.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n \n \n \n \n \n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n \n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n size=\"icon\"\n variant=\"ghost\"\n >\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n \n
\n \n );\n};\n\nconst DragAlongCell = ({\n cell,\n}: {\n cell: Cell;\n}) => {\n const { isDragging, setNodeRef, transform, transition } = useSortable({\n id: cell.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n width: cell.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n );\n};\n",
+ "content": "\"use client\";\n\nimport {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n MouseSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { restrictToHorizontalAxis } from \"@dnd-kit/modifiers\";\nimport {\n arrayMove,\n horizontalListSortingStrategy,\n SortableContext,\n useSortable,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport {\n type Cell,\n type ColumnDef,\n columnOrderingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createSortedRowModel,\n flexRender,\n type Header,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, GripVerticalIcon } from \"lucide-react\";\nimport { type CSSProperties, useEffect, useId, useState } from \"react\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnOrderingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n id: \"name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n id: \"email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n id: \"location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n id: \"status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n id: \"balance\",\n },\n];\n\nconst initialColumnOrder = columns.map((column) => column.id as string);\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable(\n {\n columns,\n data,\n enableSortingRemoval: false,\n features,\n initialState: {\n columnOrder: initialColumnOrder,\n },\n },\n (state) => ({\n columnOrder: state.columnOrder,\n sorting: state.sorting,\n }),\n );\n\n // reorder columns after drag & drop\n function handleDragEnd(event: DragEndEvent) {\n const { active, over } = event;\n if (active && over && active.id !== over.id) {\n table.setColumnOrder((columnOrder) => {\n const oldIndex = columnOrder.indexOf(active.id as string);\n const newIndex = columnOrder.indexOf(over.id as string);\n return arrayMove(columnOrder, oldIndex, newIndex); //this is just a splice util\n });\n }\n }\n\n const sensors = useSensors(\n useSensor(MouseSensor, {}),\n useSensor(TouchSensor, {}),\n useSensor(KeyboardSensor, {}),\n );\n\n return (\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n \n {headerGroup.headers.map((header) => (\n \n ))}\n \n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n \n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n Draggable columns made with{\" \"}\n \n TanStack Table\n {\" \"}\n and{\" \"}\n \n dnd kit\n \n
\n \n );\n}\n\nconst DraggableTableHeader = ({\n header,\n}: {\n header: Header;\n}) => {\n const {\n attributes,\n isDragging,\n listeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({\n id: header.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n whiteSpace: \"nowrap\",\n width: header.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n \n \n \n \n \n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n \n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n size=\"icon\"\n variant=\"ghost\"\n >\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n \n
\n \n );\n};\n\nconst DragAlongCell = ({\n cell,\n}: {\n cell: Cell;\n}) => {\n const { isDragging, setNodeRef, transform, transition } = useSortable({\n id: cell.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n width: cell.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n );\n};\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-482.json b/apps/origin/public/r/comp-482.json
index bc3ebda73..3e3b008ba 100644
--- a/apps/origin/public/r/comp-482.json
+++ b/apps/origin/public/r/comp-482.json
@@ -14,7 +14,7 @@
"files": [
{
"path": "registry/default/components/comp-482.tsx",
- "content": "\"use client\";\n\nimport {\n columnVisibilityFeature,\n createExpandedRowModel,\n type ColumnDef,\n flexRender,\n rowExpandingFeature,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, InfoIcon } from \"lucide-react\";\nimport { Fragment, useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n note?: string;\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowExpandingFeature,\n expandedRowModel: createExpandedRowModel(),\n rowSelectionFeature,\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => {\n return row.getCanExpand() ? (\n \n {row.getIsExpanded() ? (\n \n ) : (\n \n )}\n \n ) : undefined;\n },\n header: () => null,\n id: \"expander\",\n },\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n features,\n getRowCanExpand: (row) => Boolean(row.original.note),\n });\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n {row.getIsExpanded() && (\n \n \n \n
\n \n \n
{row.original.note}
\n
\n \n \n )}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Expanding sub-row made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n createExpandedRowModel,\n flexRender,\n rowExpandingFeature,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, InfoIcon } from \"lucide-react\";\nimport { Fragment, useEffect, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n note?: string;\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowExpandingFeature,\n expandedRowModel: createExpandedRowModel(),\n rowSelectionFeature,\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => {\n return row.getCanExpand() ? (\n \n {row.getIsExpanded() ? (\n \n ) : (\n \n )}\n \n ) : undefined;\n },\n header: () => null,\n id: \"expander\",\n },\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState- ([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useTable(\n {\n columns,\n data,\n features,\n getRowCanExpand: (row) => Boolean(row.original.note),\n },\n (state) => ({\n expanded: state.expanded,\n rowSelection: state.rowSelection,\n }),\n );\n\n return (\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n {row.getIsExpanded() && (\n \n \n \n
\n \n \n
{row.original.note}
\n
\n \n \n )}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n Expanding sub-row made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-483.json b/apps/origin/public/r/comp-483.json
index 139a9bea6..665bf6018 100644
--- a/apps/origin/public/r/comp-483.json
+++ b/apps/origin/public/r/comp-483.json
@@ -17,7 +17,7 @@
"files": [
{
"path": "registry/default/components/comp-483.tsx",
- "content": "\"use client\";\n\nimport {\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n type ColumnDef,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 5,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData([...data, ...data]);\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n table.state.pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Paginated table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData([...data, ...data]);\n }\n fetchPosts();\n }, []);\n\n const table = useTable(\n {\n columns,\n data,\n enableSortingRemoval: false,\n features,\n initialState: {\n pagination: {\n pageIndex: 0,\n pageSize: 5,\n },\n sorting: [\n {\n desc: false,\n id: \"name\",\n },\n ],\n },\n },\n (state) => ({\n pagination: state.pagination,\n rowSelection: state.rowSelection,\n sorting: state.sorting,\n }),\n );\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n table.state.pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Paginated table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/public/r/comp-484.json b/apps/origin/public/r/comp-484.json
index 76e48760f..ca6c16e54 100644
--- a/apps/origin/public/r/comp-484.json
+++ b/apps/origin/public/r/comp-484.json
@@ -16,7 +16,7 @@
"files": [
{
"path": "registry/default/components/comp-484.tsx",
- "content": "\"use client\";\n\nimport {\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n type ColumnDef,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const pageSize = 5;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage: table.state.pagination.pageIndex + 1,\n paginationItemsToDisplay: 5,\n totalPages: table.getPageCount(),\n });\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Page number information */}\n
\n Page{\" \"}\n \n {table.state.pagination.pageIndex + 1}\n {\" \"}\n of {table.getPageCount()} \n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number buttons */}\n {pages.map((page) => {\n const isActive = page === table.state.pagination.pageIndex + 1;\n return (\n \n table.setPageIndex(page - 1)}\n size=\"icon\"\n variant={`${isActive ? \"outline\" : \"ghost\"}`}\n >\n {page}\n \n \n );\n })}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n\n {/* Results per page */}\n
\n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n \n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize} / page\n \n ))}\n \n \n
\n
\n
\n Numeric pagination made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const pageSize = 5;\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const table = useTable(\n {\n columns,\n data,\n enableSortingRemoval: false,\n features,\n initialState: {\n pagination: {\n pageIndex: 0,\n pageSize,\n },\n sorting: [\n {\n desc: false,\n id: \"name\",\n },\n ],\n },\n },\n (state) => ({\n pagination: state.pagination,\n rowSelection: state.rowSelection,\n sorting: state.sorting,\n }),\n );\n\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage: table.state.pagination.pageIndex + 1,\n paginationItemsToDisplay: 5,\n totalPages: table.getPageCount(),\n });\n\n return (\n
\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Page number information */}\n
\n Page{\" \"}\n \n {table.state.pagination.pageIndex + 1}\n {\" \"}\n of {table.getPageCount()} \n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number buttons */}\n {pages.map((page) => {\n const isActive = page === table.state.pagination.pageIndex + 1;\n return (\n \n table.setPageIndex(page - 1)}\n size=\"icon\"\n variant={`${isActive ? \"outline\" : \"ghost\"}`}\n >\n {page}\n \n \n );\n })}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n\n {/* Results per page */}\n
\n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n \n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize} / page\n \n ))}\n \n \n
\n
\n
\n Numeric pagination made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n",
"type": "registry:component"
},
{
diff --git a/apps/origin/public/r/comp-485.json b/apps/origin/public/r/comp-485.json
index a269a8a76..4b44a6bcf 100644
--- a/apps/origin/public/r/comp-485.json
+++ b/apps/origin/public/r/comp-485.json
@@ -21,7 +21,7 @@
"files": [
{
"path": "registry/default/components/comp-485.tsx",
- "content": "\"use client\";\n\nimport {\n columnFacetingFeature,\n columnFilteringFeature,\n columnSizingFeature,\n type ColumnVisibilityState,\n columnVisibilityFeature,\n createFacetedUniqueValues,\n createFilteredRowModel,\n createPaginatedRowModel,\n createSortedRowModel,\n type ColumnDef,\n type ColumnFiltersState,\n type FilterFn,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n type Row,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n type SortingState,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleAlertIcon,\n CircleXIcon,\n Columns3Icon,\n EllipsisIcon,\n FilterIcon,\n ListFilterIcon,\n PlusIcon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnFilteringFeature,\n columnFacetingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n facetedUniqueValues: createFacetedUniqueValues(),\n filteredRowModel: createFilteredRowModel(),\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\n// Custom filter function for multi-column searching\nconst multiColumnFilterFn: FilterFn = (\n row,\n _columnId,\n filterValue,\n) => {\n const searchableRowContent =\n `${row.original.name} ${row.original.email}`.toLowerCase();\n const searchTerm = (filterValue ?? \"\").toLowerCase();\n return searchableRowContent.includes(searchTerm);\n};\n\nconst statusFilterFn: FilterFn = (\n row,\n columnId,\n filterValue: string[],\n) => {\n if (!filterValue?.length) return true;\n const status = row.getValue(columnId) as string;\n return filterValue.includes(status);\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableHiding: false,\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n enableHiding: false,\n filterFn: multiColumnFilterFn,\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 220,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n filterFn: statusFilterFn,\n header: \"Status\",\n size: 100,\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n {\n cell: ({ row }) => ,\n enableHiding: false,\n header: () => Actions ,\n id: \"actions\",\n size: 60,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [columnFilters, setColumnFilters] = useState([]);\n const [columnVisibility, setColumnVisibility] =\n useState({});\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 10,\n });\n const inputRef = useRef(null);\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const handleDeleteRows = () => {\n const selectedRows = table.getSelectedRowModel().rows;\n const updatedData = data.filter(\n (item) => !selectedRows.some((row) => row.original.id === item.id),\n );\n setData(updatedData);\n table.resetRowSelection();\n };\n\n const table = useTable({\n columns,\n data,\n enableSortingRemoval: false,\n features,\n onColumnFiltersChange: setColumnFilters,\n onColumnVisibilityChange: setColumnVisibility,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n columnVisibility,\n pagination,\n sorting,\n },\n });\n\n // Get unique status values\n const uniqueStatusValues = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n\n if (!statusColumn) return [];\n\n const values = Array.from(statusColumn.getFacetedUniqueValues().keys());\n\n return values.sort();\n }, [table.getColumn]);\n\n // Get counts for each status\n const statusCounts = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n if (!statusColumn) return new Map();\n return statusColumn.getFacetedUniqueValues();\n }, [table]);\n\n const selectedStatuses = useMemo(() => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n return filterValue ?? [];\n }, [table]);\n\n const handleStatusChange = (checked: boolean, value: string) => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n const newFilterValue = filterValue ? [...filterValue] : [];\n\n if (checked) {\n newFilterValue.push(value);\n } else {\n const index = newFilterValue.indexOf(value);\n if (index > -1) {\n newFilterValue.splice(index, 1);\n }\n }\n\n table\n .getColumn(\"status\")\n ?.setFilterValue(newFilterValue.length ? newFilterValue : undefined);\n };\n\n return (\n
\n {/* Filters */}\n
\n
\n {/* Filter by name or email */}\n
\n
\n table.getColumn(\"name\")?.setFilterValue(e.target.value)\n }\n placeholder=\"Filter by name or email...\"\n ref={inputRef}\n type=\"text\"\n value={\n (table.getColumn(\"name\")?.getFilterValue() ?? \"\") as string\n }\n />\n
\n \n
\n {Boolean(table.getColumn(\"name\")?.getFilterValue()) && (\n
{\n table.getColumn(\"name\")?.setFilterValue(\"\");\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }}\n type=\"button\"\n >\n \n \n )}\n
\n {/* Filter by status */}\n
\n \n \n \n Status\n {selectedStatuses.length > 0 && (\n \n {selectedStatuses.length}\n \n )}\n \n \n \n \n
\n Filters\n
\n
\n {uniqueStatusValues.map((value, i) => (\n
\n \n handleStatusChange(checked, value)\n }\n />\n \n {value}{\" \"}\n \n {statusCounts.get(value)}\n \n \n
\n ))}\n
\n
\n \n \n {/* Toggle columns visibility */}\n
\n \n \n \n View\n \n \n \n Toggle columns \n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n \n column.toggleVisibility(!!value)\n }\n onSelect={(event) => event.preventDefault()}\n >\n {column.id}\n \n );\n })}\n \n \n
\n
\n {/* Delete button */}\n {table.getSelectedRowModel().rows.length > 0 && (\n
\n \n \n \n Delete\n \n {table.getSelectedRowModel().rows.length}\n \n \n \n \n \n
\n \n
\n
\n \n Are you absolutely sure?\n \n \n This action cannot be undone. This will permanently delete{\" \"}\n {table.getSelectedRowModel().rows.length} selected{\" \"}\n {table.getSelectedRowModel().rows.length === 1\n ? \"row\"\n : \"rows\"}\n .\n \n \n
\n \n Cancel \n \n Delete\n \n \n \n \n )}\n {/* Add user button */}\n
\n \n Add user\n \n
\n
\n\n {/* Table */}\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n table.state.pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Example of a more complex table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction RowActions({ row: _row }: { row: Row }) {\n return (\n \n \n \n \n \n \n
\n \n \n \n \n Edit \n ⌘E \n \n \n Duplicate \n ⌘D \n \n \n \n \n \n Archive \n ⌘A \n \n \n More \n \n \n Move to project \n Move to folder \n \n Advanced options \n \n \n \n \n \n \n Share \n Add to favorites \n \n \n \n Delete \n ⌘⌫ \n \n \n \n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnFacetingFeature,\n columnFilteringFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n createFacetedUniqueValues,\n createFilteredRowModel,\n createPaginatedRowModel,\n createSortedRowModel,\n type FilterFn,\n flexRender,\n type Row,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleAlertIcon,\n CircleXIcon,\n Columns3Icon,\n EllipsisIcon,\n FilterIcon,\n ListFilterIcon,\n PlusIcon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst features = tableFeatures({\n columnFilteringFeature,\n columnFacetingFeature,\n columnSizingFeature,\n columnVisibilityFeature,\n facetedUniqueValues: createFacetedUniqueValues(),\n filteredRowModel: createFilteredRowModel(),\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\n// Custom filter function for multi-column searching\nconst multiColumnFilterFn: FilterFn = (\n row,\n _columnId,\n filterValue,\n) => {\n const searchableRowContent =\n `${row.original.name} ${row.original.email}`.toLowerCase();\n const searchTerm = (filterValue ?? \"\").toLowerCase();\n return searchableRowContent.includes(searchTerm);\n};\n\nconst statusFilterFn: FilterFn = (\n row,\n columnId,\n filterValue: string[],\n) => {\n if (!filterValue?.length) return true;\n const status = row.getValue(columnId) as string;\n return filterValue.includes(status);\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableHiding: false,\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n {row.getValue(\"name\")}
\n ),\n enableHiding: false,\n filterFn: multiColumnFilterFn,\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 220,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n \n {row.original.flag} {\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n filterFn: statusFilterFn,\n header: \"Status\",\n size: 100,\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n {\n cell: ({ row }) => ,\n enableHiding: false,\n header: () => Actions ,\n id: \"actions\",\n size: 60,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const inputRef = useRef(null);\n\n const [data, setData] = useState- ([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const handleDeleteRows = () => {\n const selectedRows = table.getSelectedRowModel().rows;\n const updatedData = data.filter(\n (item) => !selectedRows.some((row) => row.original.id === item.id),\n );\n setData(updatedData);\n table.resetRowSelection();\n };\n\n const table = useTable(\n {\n columns,\n data,\n enableSortingRemoval: false,\n features,\n initialState: {\n pagination: {\n pageIndex: 0,\n pageSize: 10,\n },\n sorting: [\n {\n desc: false,\n id: \"name\",\n },\n ],\n },\n },\n (state) => ({\n columnFilters: state.columnFilters,\n columnVisibility: state.columnVisibility,\n pagination: state.pagination,\n rowSelection: state.rowSelection,\n sorting: state.sorting,\n }),\n );\n\n // Get unique status values\n const uniqueStatusValues = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n\n if (!statusColumn) return [];\n\n const values = Array.from(statusColumn.getFacetedUniqueValues().keys());\n\n return values.sort();\n }, [table.getColumn]);\n\n // Get counts for each status\n const statusCounts = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n if (!statusColumn) return new Map();\n return statusColumn.getFacetedUniqueValues();\n }, [table]);\n\n const selectedStatuses = useMemo(() => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n return filterValue ?? [];\n }, [table]);\n\n const handleStatusChange = (checked: boolean, value: string) => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n const newFilterValue = filterValue ? [...filterValue] : [];\n\n if (checked) {\n newFilterValue.push(value);\n } else {\n const index = newFilterValue.indexOf(value);\n if (index > -1) {\n newFilterValue.splice(index, 1);\n }\n }\n\n table\n .getColumn(\"status\")\n ?.setFilterValue(newFilterValue.length ? newFilterValue : undefined);\n };\n\n return (\n
\n {/* Filters */}\n
\n
\n {/* Filter by name or email */}\n
\n
\n table.getColumn(\"name\")?.setFilterValue(e.target.value)\n }\n placeholder=\"Filter by name or email...\"\n ref={inputRef}\n type=\"text\"\n value={\n (table.getColumn(\"name\")?.getFilterValue() ?? \"\") as string\n }\n />\n
\n \n
\n {Boolean(table.getColumn(\"name\")?.getFilterValue()) && (\n
{\n table.getColumn(\"name\")?.setFilterValue(\"\");\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }}\n type=\"button\"\n >\n \n \n )}\n
\n {/* Filter by status */}\n
\n \n \n \n Status\n {selectedStatuses.length > 0 && (\n \n {selectedStatuses.length}\n \n )}\n \n \n \n \n
\n Filters\n
\n
\n {uniqueStatusValues.map((value, i) => (\n
\n \n handleStatusChange(checked, value)\n }\n />\n \n {value}{\" \"}\n \n {statusCounts.get(value)}\n \n \n
\n ))}\n
\n
\n \n \n {/* Toggle columns visibility */}\n
\n \n \n \n View\n \n \n \n Toggle columns \n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n \n column.toggleVisibility(!!value)\n }\n onSelect={(event) => event.preventDefault()}\n >\n {column.id}\n \n );\n })}\n \n \n
\n
\n {/* Delete button */}\n {table.getSelectedRowModel().rows.length > 0 && (\n
\n \n \n \n Delete\n \n {table.getSelectedRowModel().rows.length}\n \n \n \n \n \n
\n \n
\n
\n \n Are you absolutely sure?\n \n \n This action cannot be undone. This will permanently delete{\" \"}\n {table.getSelectedRowModel().rows.length} selected{\" \"}\n {table.getSelectedRowModel().rows.length === 1\n ? \"row\"\n : \"rows\"}\n .\n \n \n
\n \n Cancel \n \n Delete\n \n \n \n \n )}\n {/* Add user button */}\n
\n \n Add user\n \n
\n
\n\n {/* Table */}\n
\n
\n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n Rows per page\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.state.pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n
\n \n {table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.state.pagination.pageIndex *\n table.state.pagination.pageSize +\n table.state.pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n
\n
\n\n {/* Pagination buttons */}\n
\n
\n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n
\n Example of a more complex table made with{\" \"}\n \n TanStack Table\n \n
\n
\n );\n}\n\nfunction RowActions({ row: _row }: { row: Row }) {\n return (\n \n \n \n \n \n \n
\n \n \n \n \n Edit \n ⌘E \n \n \n Duplicate \n ⌘D \n \n \n \n \n \n Archive \n ⌘A \n \n \n More \n \n \n Move to project \n Move to folder \n \n Advanced options \n \n \n \n \n \n \n Share \n Add to favorites \n \n \n \n Delete \n ⌘⌫ \n \n \n \n );\n}\n",
"type": "registry:component"
}
],
diff --git a/apps/origin/registry/default/components/comp-477.tsx b/apps/origin/registry/default/components/comp-477.tsx
index b0670a79d..0ac0e9865 100644
--- a/apps/origin/registry/default/components/comp-477.tsx
+++ b/apps/origin/registry/default/components/comp-477.tsx
@@ -121,11 +121,14 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useTable({
- columns,
- data,
- features,
- });
+ const table = useTable(
+ {
+ columns,
+ data,
+ features,
+ },
+ (state) => ({ rowSelection: state.rowSelection }),
+ );
return (
diff --git a/apps/origin/registry/default/components/comp-478.tsx b/apps/origin/registry/default/components/comp-478.tsx
index 4f474f79b..cb43b7192 100644
--- a/apps/origin/registry/default/components/comp-478.tsx
+++ b/apps/origin/registry/default/components/comp-478.tsx
@@ -3,7 +3,6 @@
import {
type Column,
type ColumnDef,
- type ColumnFiltersState,
columnFacetingFeature,
columnFilteringFeature,
columnVisibilityFeature,
@@ -18,7 +17,6 @@ import {
metaHelper,
rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
@@ -30,7 +28,7 @@ import {
ExternalLinkIcon,
SearchIcon,
} from "lucide-react";
-import { useId, useMemo, useState } from "react";
+import { useId, useMemo } from "react";
import { cn } from "@/registry/default/lib/utils";
import { Checkbox } from "@/registry/default/ui/checkbox";
import { Input } from "@/registry/default/ui/input";
@@ -278,26 +276,27 @@ const items: Item[] = [
];
export default function Component() {
- const [columnFilters, setColumnFilters] = useState
([]);
- const [sorting, setSorting] = useState([
+ const table = useTable(
{
- desc: false,
- id: "traffic",
+ columns,
+ data: items,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ sorting: [
+ {
+ desc: false,
+ id: "traffic",
+ },
+ ],
+ },
},
- ]);
-
- const table = useTable({
- columns,
- data: items,
- enableSortingRemoval: false,
- features,
- onColumnFiltersChange: setColumnFilters,
- onSortingChange: setSorting,
- state: {
- columnFilters,
- sorting,
- },
- });
+ (state) => ({
+ columnFilters: state.columnFilters,
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ }),
+ );
const keywordColumn = table.getColumn("keyword");
const intentsColumn = table.getColumn("intents");
diff --git a/apps/origin/registry/default/components/comp-479.tsx b/apps/origin/registry/default/components/comp-479.tsx
index 28eed82c4..4e06625ca 100644
--- a/apps/origin/registry/default/components/comp-479.tsx
+++ b/apps/origin/registry/default/components/comp-479.tsx
@@ -7,9 +7,7 @@ import {
columnVisibilityFeature,
createSortedRowModel,
flexRender,
- rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
@@ -46,7 +44,6 @@ const features = tableFeatures({
columnSizingFeature,
columnResizingFeature,
columnVisibilityFeature,
- rowSelectionFeature,
rowSortingFeature,
sortedRowModel: createSortedRowModel(),
sortFns: {
@@ -119,12 +116,6 @@ const columns: ColumnDef[] = [
export default function Component() {
const [data, setData] = useState- ([]);
- const [sorting, setSorting] = useState
([
- {
- desc: false,
- id: "name",
- },
- ]);
useEffect(() => {
async function fetchPosts() {
@@ -137,17 +128,27 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useTable({
- columnResizeMode: "onChange",
- columns,
- data,
- enableSortingRemoval: false,
- features,
- onSortingChange: setSorting,
- state: {
- sorting,
+ const table = useTable(
+ {
+ columnResizeMode: "onChange",
+ columns,
+ data,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ sorting: [
+ {
+ desc: false,
+ id: "name",
+ },
+ ],
+ },
},
- });
+ (state) => ({
+ columnSizing: state.columnSizing,
+ sorting: state.sorting,
+ }),
+ );
return (
@@ -242,10 +243,7 @@ export default function Component() {
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
-
+
{row.getVisibleCells().map((cell) => (
{flexRender(cell.column.columnDef.cell, cell.getContext())}
diff --git a/apps/origin/registry/default/components/comp-480.tsx b/apps/origin/registry/default/components/comp-480.tsx
index 7f89ef0a8..9ec43d1ae 100644
--- a/apps/origin/registry/default/components/comp-480.tsx
+++ b/apps/origin/registry/default/components/comp-480.tsx
@@ -8,13 +8,7 @@ import {
columnResizingFeature,
columnSizingFeature,
columnVisibilityFeature,
- createSortedRowModel,
flexRender,
- rowSelectionFeature,
- rowSortingFeature,
- type SortingState,
- sortFn_alphanumeric,
- sortFn_text,
tableFeatures,
useTable,
} from "@tanstack/react-table";
@@ -62,13 +56,6 @@ const features = tableFeatures({
columnSizingFeature,
columnResizingFeature,
columnVisibilityFeature,
- rowSelectionFeature,
- rowSortingFeature,
- sortedRowModel: createSortedRowModel(),
- sortFns: {
- alphanumeric: sortFn_alphanumeric,
- text: sortFn_text,
- },
});
// Helper function to compute pinning styles for columns
@@ -149,7 +136,6 @@ const columns: ColumnDef[] = [
export default function Component() {
const [data, setData] = useState- ([]);
- const [sorting, setSorting] = useState
([]);
useEffect(() => {
async function fetchPosts() {
@@ -162,17 +148,18 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useTable({
- columnResizeMode: "onChange",
- columns,
- data,
- enableSortingRemoval: false,
- features,
- onSortingChange: setSorting,
- state: {
- sorting,
+ const table = useTable(
+ {
+ columnResizeMode: "onChange",
+ columns,
+ data,
+ features,
},
- });
+ (state) => ({
+ columnPinning: state.columnPinning,
+ columnSizing: state.columnSizing,
+ }),
+ );
return (
@@ -297,10 +284,7 @@ export default function Component() {
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
-
+
{row.getVisibleCells().map((cell) => {
const { column } = cell;
const isPinned = column.getIsPinned();
diff --git a/apps/origin/registry/default/components/comp-481.tsx b/apps/origin/registry/default/components/comp-481.tsx
index c24ced7cb..f7511c8cd 100644
--- a/apps/origin/registry/default/components/comp-481.tsx
+++ b/apps/origin/registry/default/components/comp-481.tsx
@@ -27,9 +27,7 @@ import {
createSortedRowModel,
flexRender,
type Header,
- rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
@@ -61,7 +59,6 @@ const features = tableFeatures({
columnOrderingFeature,
columnSizingFeature,
columnVisibilityFeature,
- rowSelectionFeature,
rowSortingFeature,
sortedRowModel: createSortedRowModel(),
sortFns: {
@@ -117,12 +114,10 @@ const columns: ColumnDef[] = [
},
];
+const initialColumnOrder = columns.map((column) => column.id as string);
+
export default function Component() {
const [data, setData] = useState- ([]);
- const [sorting, setSorting] = useState
([]);
- const [columnOrder, setColumnOrder] = useState(
- columns.map((column) => column.id as string),
- );
useEffect(() => {
async function fetchPosts() {
@@ -135,24 +130,27 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useTable({
- columns,
- data,
- enableSortingRemoval: false,
- features,
- onColumnOrderChange: setColumnOrder,
- onSortingChange: setSorting,
- state: {
- columnOrder,
- sorting,
+ const table = useTable(
+ {
+ columns,
+ data,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ columnOrder: initialColumnOrder,
+ },
},
- });
+ (state) => ({
+ columnOrder: state.columnOrder,
+ sorting: state.sorting,
+ }),
+ );
// reorder columns after drag & drop
function handleDragEnd(event: DragEndEvent) {
const { active, over } = event;
if (active && over && active.id !== over.id) {
- setColumnOrder((columnOrder) => {
+ table.setColumnOrder((columnOrder) => {
const oldIndex = columnOrder.indexOf(active.id as string);
const newIndex = columnOrder.indexOf(over.id as string);
return arrayMove(columnOrder, oldIndex, newIndex); //this is just a splice util
@@ -179,7 +177,7 @@ export default function Component() {
{table.getHeaderGroups().map((headerGroup) => (
{headerGroup.headers.map((header) => (
@@ -192,13 +190,10 @@ export default function Component() {
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
-
+
{row.getVisibleCells().map((cell) => (
diff --git a/apps/origin/registry/default/components/comp-482.tsx b/apps/origin/registry/default/components/comp-482.tsx
index 2685438de..d12e7f000 100644
--- a/apps/origin/registry/default/components/comp-482.tsx
+++ b/apps/origin/registry/default/components/comp-482.tsx
@@ -161,12 +161,18 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useTable({
- columns,
- data,
- features,
- getRowCanExpand: (row) => Boolean(row.original.note),
- });
+ const table = useTable(
+ {
+ columns,
+ data,
+ features,
+ getRowCanExpand: (row) => Boolean(row.original.note),
+ },
+ (state) => ({
+ expanded: state.expanded,
+ rowSelection: state.rowSelection,
+ }),
+ );
return (
diff --git a/apps/origin/registry/default/components/comp-483.tsx b/apps/origin/registry/default/components/comp-483.tsx
index ca175d228..20ce40b15 100644
--- a/apps/origin/registry/default/components/comp-483.tsx
+++ b/apps/origin/registry/default/components/comp-483.tsx
@@ -7,11 +7,9 @@ import {
createPaginatedRowModel,
createSortedRowModel,
flexRender,
- type PaginationState,
rowPaginationFeature,
rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
@@ -155,18 +153,6 @@ const columns: ColumnDef
[] = [
export default function Component() {
const id = useId();
- const [pagination, setPagination] = useState({
- pageIndex: 0,
- pageSize: 5,
- });
-
- const [sorting, setSorting] = useState([
- {
- desc: false,
- id: "name",
- },
- ]);
-
const [data, setData] = useState- ([]);
useEffect(() => {
async function fetchPosts() {
@@ -179,18 +165,31 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useTable({
- columns,
- data,
- enableSortingRemoval: false,
- features,
- onPaginationChange: setPagination,
- onSortingChange: setSorting,
- state: {
- pagination,
- sorting,
+ const table = useTable(
+ {
+ columns,
+ data,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ pagination: {
+ pageIndex: 0,
+ pageSize: 5,
+ },
+ sorting: [
+ {
+ desc: false,
+ id: "name",
+ },
+ ],
+ },
},
- });
+ (state) => ({
+ pagination: state.pagination,
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ }),
+ );
return (
diff --git a/apps/origin/registry/default/components/comp-484.tsx b/apps/origin/registry/default/components/comp-484.tsx
index a4abee11d..657f4d764 100644
--- a/apps/origin/registry/default/components/comp-484.tsx
+++ b/apps/origin/registry/default/components/comp-484.tsx
@@ -7,11 +7,9 @@ import {
createPaginatedRowModel,
createSortedRowModel,
flexRender,
- type PaginationState,
rowPaginationFeature,
rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
@@ -155,18 +153,6 @@ const columns: ColumnDef
[] = [
export default function Component() {
const pageSize = 5;
- const [pagination, setPagination] = useState({
- pageIndex: 0,
- pageSize: pageSize,
- });
-
- const [sorting, setSorting] = useState([
- {
- desc: false,
- id: "name",
- },
- ]);
-
const [data, setData] = useState- ([]);
useEffect(() => {
async function fetchPosts() {
@@ -179,18 +165,31 @@ export default function Component() {
fetchPosts();
}, []);
- const table = useTable({
- columns,
- data,
- enableSortingRemoval: false,
- features,
- onPaginationChange: setPagination,
- onSortingChange: setSorting,
- state: {
- pagination,
- sorting,
+ const table = useTable(
+ {
+ columns,
+ data,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ pagination: {
+ pageIndex: 0,
+ pageSize,
+ },
+ sorting: [
+ {
+ desc: false,
+ id: "name",
+ },
+ ],
+ },
},
- });
+ (state) => ({
+ pagination: state.pagination,
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ }),
+ );
const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({
currentPage: table.state.pagination.pageIndex + 1,
diff --git a/apps/origin/registry/default/components/comp-485.tsx b/apps/origin/registry/default/components/comp-485.tsx
index 8f9f4e4e0..efeb879d6 100644
--- a/apps/origin/registry/default/components/comp-485.tsx
+++ b/apps/origin/registry/default/components/comp-485.tsx
@@ -2,8 +2,6 @@
import {
type ColumnDef,
- type ColumnFiltersState,
- type ColumnVisibilityState,
columnFacetingFeature,
columnFilteringFeature,
columnSizingFeature,
@@ -14,12 +12,10 @@ import {
createSortedRowModel,
type FilterFn,
flexRender,
- type PaginationState,
type Row,
rowPaginationFeature,
rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
@@ -244,22 +240,8 @@ const columns: ColumnDef
[] = [
export default function Component() {
const id = useId();
- const [columnFilters, setColumnFilters] = useState([]);
- const [columnVisibility, setColumnVisibility] =
- useState({});
- const [pagination, setPagination] = useState({
- pageIndex: 0,
- pageSize: 10,
- });
const inputRef = useRef(null);
- const [sorting, setSorting] = useState([
- {
- desc: false,
- id: "name",
- },
- ]);
-
const [data, setData] = useState- ([]);
useEffect(() => {
async function fetchPosts() {
@@ -281,22 +263,33 @@ export default function Component() {
table.resetRowSelection();
};
- const table = useTable({
- columns,
- data,
- enableSortingRemoval: false,
- features,
- onColumnFiltersChange: setColumnFilters,
- onColumnVisibilityChange: setColumnVisibility,
- onPaginationChange: setPagination,
- onSortingChange: setSorting,
- state: {
- columnFilters,
- columnVisibility,
- pagination,
- sorting,
+ const table = useTable(
+ {
+ columns,
+ data,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ pagination: {
+ pageIndex: 0,
+ pageSize: 10,
+ },
+ sorting: [
+ {
+ desc: false,
+ id: "name",
+ },
+ ],
+ },
},
- });
+ (state) => ({
+ columnFilters: state.columnFilters,
+ columnVisibility: state.columnVisibility,
+ pagination: state.pagination,
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ }),
+ );
// Get unique status values
const uniqueStatusValues = useMemo(() => {
diff --git a/apps/ui/public/r/p-table-3.json b/apps/ui/public/r/p-table-3.json
index 248ed0b2b..d81e78c69 100644
--- a/apps/ui/public/r/p-table-3.json
+++ b/apps/ui/public/r/p-table-3.json
@@ -14,7 +14,7 @@
"files": [
{
"path": "registry/default/particles/p-table-3.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame } from \"@/registry/default/ui/frame\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst getColumns = (): ColumnDef
[] => [\n {\n cell: ({ row }) => {\n const toggleHandler = row.getToggleSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n const toggleHandler = table.getToggleAllPageRowsSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nexport default function Particle() {\n const [tableData] = useState(data);\n const [rowSelection, setRowSelection] = useState({});\n\n const columns = useMemo(() => getColumns(), []);\n\n const table = useTable({\n columns,\n data: tableData,\n enableRowSelection: true,\n features,\n onRowSelectionChange: setRowSelection,\n state: {\n rowSelection,\n },\n });\n\n const totalBudget = tableData.reduce(\n (sum, project) => sum + project.budget,\n 0,\n );\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame } from \"@/registry/default/ui/frame\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst getColumns = (): ColumnDef[] => [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nconst columns = getColumns();\n\nexport default function Particle() {\n const table = useTable(\n {\n columns,\n data,\n enableRowSelection: true,\n features,\n },\n (state) => ({ rowSelection: state.rowSelection }),\n );\n\n const totalBudget = data.reduce((sum, project) => sum + project.budget, 0);\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/public/r/p-table-4.json b/apps/ui/public/r/p-table-4.json
index 3909b5a11..4d793a6c3 100644
--- a/apps/ui/public/r/p-table-4.json
+++ b/apps/ui/public/r/p-table-4.json
@@ -18,7 +18,7 @@
"files": [
{
"path": "registry/default/particles/p-table-4.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n type SortingState,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame, FrameFooter } from \"@/registry/default/ui/frame\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"departureTime\",\n },\n ]);\n\n const table = useTable({\n columns,\n data: flights,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.state.pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Frame, FrameFooter } from \"@/registry/default/ui/frame\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const table = useTable(\n {\n columns,\n data: flights,\n enableSortingRemoval: false,\n features,\n initialState: {\n pagination: {\n pageIndex: 0,\n pageSize,\n },\n sorting: [\n {\n desc: false,\n id: \"departureTime\",\n },\n ],\n },\n },\n (state) => ({\n pagination: state.pagination,\n rowSelection: state.rowSelection,\n sorting: state.sorting,\n }),\n );\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.state.pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/public/r/p-table-6.json b/apps/ui/public/r/p-table-6.json
index 106de9dd9..189e1e0fb 100644
--- a/apps/ui/public/r/p-table-6.json
+++ b/apps/ui/public/r/p-table-6.json
@@ -14,7 +14,7 @@
"files": [
{
"path": "registry/default/particles/p-table-6.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { CardFrame } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst getColumns = (): ColumnDef[] => [\n {\n cell: ({ row }) => {\n const toggleHandler = row.getToggleSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n const toggleHandler = table.getToggleAllPageRowsSelectedHandler();\n return (\n {\n // Create a synthetic event for the handler\n const syntheticEvent = {\n target: { checked: !!value },\n } as unknown as React.ChangeEvent;\n toggleHandler(syntheticEvent);\n }}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nexport default function Particle() {\n const [tableData] = useState(data);\n const [rowSelection, setRowSelection] = useState({});\n\n const columns = useMemo(() => getColumns(), []);\n\n const table = useTable({\n columns,\n data: tableData,\n enableRowSelection: true,\n features,\n onRowSelectionChange: setRowSelection,\n state: {\n rowSelection,\n },\n });\n\n const totalBudget = tableData.reduce(\n (sum, project) => sum + project.budget,\n 0,\n );\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnVisibilityFeature,\n flexRender,\n rowSelectionFeature,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { CardFrame } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Project = {\n id: string;\n project: string;\n status: \"Paid\" | \"Unpaid\" | \"Pending\" | \"Failed\";\n team: string;\n budget: number;\n};\n\nconst data: Project[] = [\n {\n budget: 12500,\n id: \"1\",\n project: \"Website Redesign\",\n status: \"Paid\",\n team: \"Frontend Team\",\n },\n {\n budget: 8750,\n id: \"2\",\n project: \"Mobile App\",\n status: \"Unpaid\",\n team: \"Mobile Team\",\n },\n {\n budget: 5200,\n id: \"3\",\n project: \"API Integration\",\n status: \"Pending\",\n team: \"Backend Team\",\n },\n {\n budget: 3800,\n id: \"4\",\n project: \"Database Migration\",\n status: \"Paid\",\n team: \"DevOps Team\",\n },\n {\n budget: 7200,\n id: \"5\",\n project: \"User Dashboard\",\n status: \"Paid\",\n team: \"UX Team\",\n },\n {\n budget: 2100,\n id: \"6\",\n project: \"Security Audit\",\n status: \"Failed\",\n team: \"Security Team\",\n },\n];\n\nconst getStatusColor = (status: Project[\"status\"]) => {\n switch (status) {\n case \"Paid\":\n return \"bg-emerald-500\";\n case \"Unpaid\":\n return \"bg-muted-foreground/64\";\n case \"Pending\":\n return \"bg-amber-500\";\n case \"Failed\":\n return \"bg-red-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnVisibilityFeature,\n rowSelectionFeature,\n});\n\nconst getColumns = (): ColumnDef[] => [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n },\n {\n accessorKey: \"project\",\n cell: ({ row }) => (\n {row.getValue(\"project\")}
\n ),\n header: \"Project\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Project[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n },\n {\n accessorKey: \"team\",\n header: \"Team\",\n },\n {\n accessorKey: \"budget\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"budget\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(amount);\n return {formatted}
;\n },\n header: () => Budget
,\n },\n];\n\nconst columns = getColumns();\n\nexport default function Particle() {\n const table = useTable(\n {\n columns,\n data,\n enableRowSelection: true,\n features,\n },\n (state) => ({ rowSelection: state.rowSelection }),\n );\n\n const totalBudget = data.reduce((sum, project) => sum + project.budget, 0);\n const formattedTotal = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 0,\n minimumFractionDigits: 0,\n style: \"currency\",\n }).format(totalBudget);\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total Budget \n {formattedTotal} \n \n \n
\n \n );\n}\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/public/r/p-table-8.json b/apps/ui/public/r/p-table-8.json
index 4f4c50180..354bb1edd 100644
--- a/apps/ui/public/r/p-table-8.json
+++ b/apps/ui/public/r/p-table-8.json
@@ -18,7 +18,7 @@
"files": [
{
"path": "registry/default/particles/p-table-8.tsx",
- "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n type PaginationState,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n type SortingState,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { CardFrame, CardFrameFooter } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"departureTime\",\n },\n ]);\n\n const table = useTable({\n columns,\n data: flights,\n enableSortingRemoval: false,\n features,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.state.pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
+ "content": "\"use client\";\n\nimport {\n type ColumnDef,\n columnSizingFeature,\n columnVisibilityFeature,\n createPaginatedRowModel,\n createSortedRowModel,\n flexRender,\n rowPaginationFeature,\n rowSelectionFeature,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n useTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from \"lucide-react\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { CardFrame, CardFrameFooter } from \"@/registry/default/ui/card\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectItem,\n SelectPopup,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Flight = {\n id: string;\n flightCode: string;\n destination: string;\n departureTime: string;\n arrivalTime: string;\n terminal: string;\n duration: string;\n status: \"On Time\" | \"Delayed\" | \"Cancelled\" | \"Boarding\";\n gate: string;\n};\n\nconst getStatusColor = (status: Flight[\"status\"]) => {\n switch (status) {\n case \"On Time\":\n return \"bg-emerald-500\";\n case \"Delayed\":\n return \"bg-amber-500\";\n case \"Cancelled\":\n return \"bg-red-500\";\n case \"Boarding\":\n return \"bg-blue-500\";\n default:\n return \"bg-muted-foreground/64\";\n }\n};\n\nconst features = tableFeatures({\n columnSizingFeature,\n columnVisibilityFeature,\n rowPaginationFeature,\n paginatedRowModel: createPaginatedRowModel(),\n rowSelectionFeature,\n rowSortingFeature,\n sortedRowModel: createSortedRowModel(),\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n text: sortFn_text,\n },\n});\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => {\n const isAllSelected = table.getIsAllPageRowsSelected();\n const isSomeSelected = table.getIsSomePageRowsSelected();\n return (\n table.toggleAllPageRowsSelected(!!value)}\n />\n );\n },\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"flightCode\",\n cell: ({ row }) => (\n \n {row.getValue(\"flightCode\")}\n
\n ),\n header: \"Flight\",\n size: 80,\n },\n {\n accessorKey: \"departureTime\",\n cell: ({ row }) => {\n const isCancelled = row.original.status === \"Cancelled\";\n const isDelayed = row.original.status === \"Delayed\";\n return (\n \n
\n {row.original.departureTime}\n
\n
\n
\n {row.original.duration}\n
\n
\n
{row.original.arrivalTime}
\n
\n );\n },\n header: \"Time\",\n size: 220,\n },\n {\n accessorKey: \"destination\",\n cell: ({ row }) => (\n {row.getValue(\"destination\")}
\n ),\n header: \"Destination\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => {\n const status = row.getValue(\"status\") as Flight[\"status\"];\n return (\n \n \n {status}\n \n );\n },\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"terminal\",\n cell: ({ row }) => (\n \n \n {row.getValue(\"terminal\")} \n \n ),\n header: \"Terminal\",\n size: 90,\n },\n {\n accessorKey: \"gate\",\n header: \"Gate\",\n size: 80,\n },\n];\n\nexport default function Particle() {\n const pageSize = 10;\n\n const table = useTable(\n {\n columns,\n data: flights,\n enableSortingRemoval: false,\n features,\n initialState: {\n pagination: {\n pageIndex: 0,\n pageSize,\n },\n sorting: [\n {\n desc: false,\n id: \"departureTime\",\n },\n ],\n },\n },\n (state) => ({\n pagination: state.pagination,\n rowSelection: state.rowSelection,\n sorting: state.sorting,\n }),\n );\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const columnSize = header.column.getSize();\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n \n \n {/* Results range selector */}\n
\n
Viewing
\n
{\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return { label: `${start}-${end}`, value: pageNum };\n })}\n onValueChange={(value) => {\n table.setPageIndex((value as number) - 1);\n }}\n value={table.state.pagination.pageIndex + 1}\n >\n \n \n \n \n {Array.from({ length: table.getPageCount() }, (_, i) => {\n const start = i * table.state.pagination.pageSize + 1;\n const end = Math.min(\n (i + 1) * table.state.pagination.pageSize,\n table.getRowCount(),\n );\n const pageNum = i + 1;\n return (\n \n {`${start}-${end}`}\n \n );\n })}\n \n \n
\n of{\" \"}\n \n {table.getRowCount()}\n {\" \"}\n results\n
\n
\n\n {/* Pagination */}\n
\n \n \n table.previousPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n table.nextPage()}\n size=\"sm\"\n variant=\"outline\"\n />\n }\n />\n \n \n \n
\n \n \n );\n}\n\nconst flights: Flight[] = [\n {\n arrivalTime: \"11:45\",\n departureTime: \"08:30\",\n destination: \"Los Angeles\",\n duration: \"5h 15m\",\n flightCode: \"AA1234\",\n gate: \"A12\",\n id: \"1\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"17:10\",\n departureTime: \"14:20\",\n destination: \"San Francisco\",\n duration: \"4h 50m\",\n flightCode: \"DL5678\",\n gate: \"B24\",\n id: \"2\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:30\",\n departureTime: \"10:15\",\n destination: \"Miami\",\n duration: \"3h 15m\",\n flightCode: \"UA9012\",\n gate: \"C8\",\n id: \"3\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"18:20\",\n departureTime: \"16:45\",\n destination: \"Seattle\",\n duration: \"2h 35m\",\n flightCode: \"SW3456\",\n gate: \"D15\",\n id: \"4\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:30\",\n departureTime: \"09:00\",\n destination: \"Salt Lake City\",\n duration: \"5h 30m\",\n flightCode: \"JB7890\",\n gate: \"E3\",\n id: \"5\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:30\",\n destination: \"Phoenix\",\n duration: \"2h 45m\",\n flightCode: \"AS2345\",\n gate: \"F7\",\n id: \"6\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:30\",\n departureTime: \"13:00\",\n destination: \"Las Vegas\",\n duration: \"5h 30m\",\n flightCode: \"HA6789\",\n gate: \"G12\",\n id: \"7\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"09:00\",\n departureTime: \"07:15\",\n destination: \"Dallas\",\n duration: \"1h 45m\",\n flightCode: \"FX0123\",\n gate: \"H5\",\n id: \"8\",\n status: \"Boarding\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"08:30\",\n departureTime: \"06:00\",\n destination: \"Denver\",\n duration: \"2h 30m\",\n flightCode: \"WN4567\",\n gate: \"I9\",\n id: \"9\",\n status: \"Boarding\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:45\",\n destination: \"Portland\",\n duration: \"2h 35m\",\n flightCode: \"B61234\",\n gate: \"J14\",\n id: \"10\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"18:45\",\n departureTime: \"15:30\",\n destination: \"Atlanta\",\n duration: \"3h 15m\",\n flightCode: \"NK8901\",\n gate: \"K6\",\n id: \"11\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:00\",\n departureTime: \"09:45\",\n destination: \"Chicago\",\n duration: \"2h 15m\",\n flightCode: \"F92345\",\n gate: \"L11\",\n id: \"12\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"14:15\",\n departureTime: \"11:00\",\n destination: \"Boston\",\n duration: \"3h 15m\",\n flightCode: \"SY6789\",\n gate: \"M3\",\n id: \"13\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:45\",\n departureTime: \"13:30\",\n destination: \"New York\",\n duration: \"3h 15m\",\n flightCode: \"G40123\",\n gate: \"N8\",\n id: \"14\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"11:20\",\n departureTime: \"08:00\",\n destination: \"Washington\",\n duration: \"3h 20m\",\n flightCode: \"YX5678\",\n gate: \"O12\",\n id: \"15\",\n status: \"Delayed\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"13:50\",\n departureTime: \"10:30\",\n destination: \"Orlando\",\n duration: \"3h 20m\",\n flightCode: \"4U9012\",\n gate: \"P5\",\n id: \"16\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"16:30\",\n departureTime: \"14:00\",\n destination: \"Houston\",\n duration: \"2h 30m\",\n flightCode: \"QF3456\",\n gate: \"Q9\",\n id: \"17\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"10:00\",\n departureTime: \"07:30\",\n destination: \"Minneapolis\",\n duration: \"2h 30m\",\n flightCode: \"LH7890\",\n gate: \"R7\",\n id: \"18\",\n status: \"Cancelled\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"19:30\",\n departureTime: \"16:15\",\n destination: \"Detroit\",\n duration: \"3h 15m\",\n flightCode: \"KL2345\",\n gate: \"S4\",\n id: \"19\",\n status: \"Cancelled\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"15:10\",\n departureTime: \"12:00\",\n destination: \"Philadelphia\",\n duration: \"3h 10m\",\n flightCode: \"AF6789\",\n gate: \"T16\",\n id: \"20\",\n status: \"On Time\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"12:25\",\n departureTime: \"09:15\",\n destination: \"Charlotte\",\n duration: \"3h 10m\",\n flightCode: \"BA0123\",\n gate: \"U10\",\n id: \"21\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"18:00\",\n departureTime: \"15:45\",\n destination: \"Nashville\",\n duration: \"2h 15m\",\n flightCode: \"IB4567\",\n gate: \"V8\",\n id: \"22\",\n status: \"Delayed\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"14:00\",\n departureTime: \"11:45\",\n destination: \"Austin\",\n duration: \"2h 15m\",\n flightCode: \"EK8901\",\n gate: \"W13\",\n id: \"23\",\n status: \"Cancelled\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"16:40\",\n departureTime: \"13:15\",\n destination: \"Tampa\",\n duration: \"3h 25m\",\n flightCode: \"QR2345\",\n gate: \"X6\",\n id: \"24\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"11:30\",\n departureTime: \"08:45\",\n destination: \"Raleigh\",\n duration: \"2h 45m\",\n flightCode: \"TK6789\",\n gate: \"Y11\",\n id: \"25\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"12:45\",\n departureTime: \"10:00\",\n destination: \"Indianapolis\",\n duration: \"2h 45m\",\n flightCode: \"VS3456\",\n gate: \"Z4\",\n id: \"26\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"20:00\",\n departureTime: \"17:30\",\n destination: \"Kansas City\",\n duration: \"2h 30m\",\n flightCode: \"LX7890\",\n gate: \"A8\",\n id: \"27\",\n status: \"Delayed\",\n terminal: \"3\",\n },\n {\n arrivalTime: \"15:20\",\n departureTime: \"12:30\",\n destination: \"Columbus\",\n duration: \"2h 50m\",\n flightCode: \"OS1234\",\n gate: \"B19\",\n id: \"28\",\n status: \"On Time\",\n terminal: \"1\",\n },\n {\n arrivalTime: \"20:15\",\n departureTime: \"18:00\",\n destination: \"Milwaukee\",\n duration: \"2h 15m\",\n flightCode: \"SN5678\",\n gate: \"C22\",\n id: \"29\",\n status: \"On Time\",\n terminal: \"2\",\n },\n {\n arrivalTime: \"21:30\",\n departureTime: \"19:15\",\n destination: \"Memphis\",\n duration: \"2h 15m\",\n flightCode: \"TP9012\",\n gate: \"D6\",\n id: \"30\",\n status: \"On Time\",\n terminal: \"3\",\n },\n];\n",
"type": "registry:block"
}
],
diff --git a/apps/ui/registry/default/particles/p-table-3.tsx b/apps/ui/registry/default/particles/p-table-3.tsx
index 9ab526ef6..9dc86f5a1 100644
--- a/apps/ui/registry/default/particles/p-table-3.tsx
+++ b/apps/ui/registry/default/particles/p-table-3.tsx
@@ -8,8 +8,6 @@ import {
tableFeatures,
useTable,
} from "@tanstack/react-table";
-import type React from "react";
-import { useMemo, useState } from "react";
import { Badge } from "@/registry/default/ui/badge";
import { Checkbox } from "@/registry/default/ui/checkbox";
import { Frame } from "@/registry/default/ui/frame";
@@ -98,39 +96,23 @@ const features = tableFeatures({
const getColumns = (): ColumnDef[] => [
{
- cell: ({ row }) => {
- const toggleHandler = row.getToggleSelectedHandler();
- return (
- {
- // Create a synthetic event for the handler
- const syntheticEvent = {
- target: { checked: !!value },
- } as unknown as React.ChangeEvent;
- toggleHandler(syntheticEvent);
- }}
- />
- );
- },
+ cell: ({ row }) => (
+ row.toggleSelected(!!value)}
+ />
+ ),
header: ({ table }) => {
const isAllSelected = table.getIsAllPageRowsSelected();
const isSomeSelected = table.getIsSomePageRowsSelected();
- const toggleHandler = table.getToggleAllPageRowsSelectedHandler();
return (
{
- // Create a synthetic event for the handler
- const syntheticEvent = {
- target: { checked: !!value },
- } as unknown as React.ChangeEvent;
- toggleHandler(syntheticEvent);
- }}
+ onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
/>
);
},
@@ -179,27 +161,20 @@ const getColumns = (): ColumnDef[] => [
},
];
-export default function Particle() {
- const [tableData] = useState(data);
- const [rowSelection, setRowSelection] = useState({});
-
- const columns = useMemo(() => getColumns(), []);
+const columns = getColumns();
- const table = useTable({
- columns,
- data: tableData,
- enableRowSelection: true,
- features,
- onRowSelectionChange: setRowSelection,
- state: {
- rowSelection,
+export default function Particle() {
+ const table = useTable(
+ {
+ columns,
+ data,
+ enableRowSelection: true,
+ features,
},
- });
-
- const totalBudget = tableData.reduce(
- (sum, project) => sum + project.budget,
- 0,
+ (state) => ({ rowSelection: state.rowSelection }),
);
+
+ const totalBudget = data.reduce((sum, project) => sum + project.budget, 0);
const formattedTotal = new Intl.NumberFormat("en-US", {
currency: "USD",
maximumFractionDigits: 0,
diff --git a/apps/ui/registry/default/particles/p-table-4.tsx b/apps/ui/registry/default/particles/p-table-4.tsx
index d05cdccf2..74a486e62 100644
--- a/apps/ui/registry/default/particles/p-table-4.tsx
+++ b/apps/ui/registry/default/particles/p-table-4.tsx
@@ -7,18 +7,15 @@ import {
createPaginatedRowModel,
createSortedRowModel,
flexRender,
- type PaginationState,
rowPaginationFeature,
rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
useTable,
} from "@tanstack/react-table";
import { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from "lucide-react";
-import { useState } from "react";
import { cn } from "@/registry/default/lib/utils";
import { Badge } from "@/registry/default/ui/badge";
import { Button } from "@/registry/default/ui/button";
@@ -207,30 +204,31 @@ const columns: ColumnDef[] = [
export default function Particle() {
const pageSize = 10;
- const [pagination, setPagination] = useState({
- pageIndex: 0,
- pageSize: pageSize,
- });
-
- const [sorting, setSorting] = useState([
+ const table = useTable(
{
- desc: false,
- id: "departureTime",
- },
- ]);
-
- const table = useTable({
- columns,
- data: flights,
- enableSortingRemoval: false,
- features,
- onPaginationChange: setPagination,
- onSortingChange: setSorting,
- state: {
- pagination,
- sorting,
+ columns,
+ data: flights,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ pagination: {
+ pageIndex: 0,
+ pageSize,
+ },
+ sorting: [
+ {
+ desc: false,
+ id: "departureTime",
+ },
+ ],
+ },
},
- });
+ (state) => ({
+ pagination: state.pagination,
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ }),
+ );
return (
diff --git a/apps/ui/registry/default/particles/p-table-6.tsx b/apps/ui/registry/default/particles/p-table-6.tsx
index b3b8bbb01..366f7642a 100644
--- a/apps/ui/registry/default/particles/p-table-6.tsx
+++ b/apps/ui/registry/default/particles/p-table-6.tsx
@@ -8,8 +8,6 @@ import {
tableFeatures,
useTable,
} from "@tanstack/react-table";
-import type React from "react";
-import { useMemo, useState } from "react";
import { Badge } from "@/registry/default/ui/badge";
import { CardFrame } from "@/registry/default/ui/card";
import { Checkbox } from "@/registry/default/ui/checkbox";
@@ -98,39 +96,23 @@ const features = tableFeatures({
const getColumns = (): ColumnDef[] => [
{
- cell: ({ row }) => {
- const toggleHandler = row.getToggleSelectedHandler();
- return (
- {
- // Create a synthetic event for the handler
- const syntheticEvent = {
- target: { checked: !!value },
- } as unknown as React.ChangeEvent;
- toggleHandler(syntheticEvent);
- }}
- />
- );
- },
+ cell: ({ row }) => (
+ row.toggleSelected(!!value)}
+ />
+ ),
header: ({ table }) => {
const isAllSelected = table.getIsAllPageRowsSelected();
const isSomeSelected = table.getIsSomePageRowsSelected();
- const toggleHandler = table.getToggleAllPageRowsSelectedHandler();
return (
{
- // Create a synthetic event for the handler
- const syntheticEvent = {
- target: { checked: !!value },
- } as unknown as React.ChangeEvent;
- toggleHandler(syntheticEvent);
- }}
+ onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
/>
);
},
@@ -179,27 +161,20 @@ const getColumns = (): ColumnDef[] => [
},
];
-export default function Particle() {
- const [tableData] = useState(data);
- const [rowSelection, setRowSelection] = useState({});
-
- const columns = useMemo(() => getColumns(), []);
+const columns = getColumns();
- const table = useTable({
- columns,
- data: tableData,
- enableRowSelection: true,
- features,
- onRowSelectionChange: setRowSelection,
- state: {
- rowSelection,
+export default function Particle() {
+ const table = useTable(
+ {
+ columns,
+ data,
+ enableRowSelection: true,
+ features,
},
- });
-
- const totalBudget = tableData.reduce(
- (sum, project) => sum + project.budget,
- 0,
+ (state) => ({ rowSelection: state.rowSelection }),
);
+
+ const totalBudget = data.reduce((sum, project) => sum + project.budget, 0);
const formattedTotal = new Intl.NumberFormat("en-US", {
currency: "USD",
maximumFractionDigits: 0,
diff --git a/apps/ui/registry/default/particles/p-table-8.tsx b/apps/ui/registry/default/particles/p-table-8.tsx
index 629b7d43a..3f48a78db 100644
--- a/apps/ui/registry/default/particles/p-table-8.tsx
+++ b/apps/ui/registry/default/particles/p-table-8.tsx
@@ -7,18 +7,15 @@ import {
createPaginatedRowModel,
createSortedRowModel,
flexRender,
- type PaginationState,
rowPaginationFeature,
rowSelectionFeature,
rowSortingFeature,
- type SortingState,
sortFn_alphanumeric,
sortFn_text,
tableFeatures,
useTable,
} from "@tanstack/react-table";
import { ChevronDownIcon, ChevronUpIcon, PlaneTakeoffIcon } from "lucide-react";
-import { useState } from "react";
import { cn } from "@/registry/default/lib/utils";
import { Badge } from "@/registry/default/ui/badge";
import { Button } from "@/registry/default/ui/button";
@@ -207,30 +204,31 @@ const columns: ColumnDef[] = [
export default function Particle() {
const pageSize = 10;
- const [pagination, setPagination] = useState({
- pageIndex: 0,
- pageSize: pageSize,
- });
-
- const [sorting, setSorting] = useState([
+ const table = useTable(
{
- desc: false,
- id: "departureTime",
- },
- ]);
-
- const table = useTable({
- columns,
- data: flights,
- enableSortingRemoval: false,
- features,
- onPaginationChange: setPagination,
- onSortingChange: setSorting,
- state: {
- pagination,
- sorting,
+ columns,
+ data: flights,
+ enableSortingRemoval: false,
+ features,
+ initialState: {
+ pagination: {
+ pageIndex: 0,
+ pageSize,
+ },
+ sorting: [
+ {
+ desc: false,
+ id: "departureTime",
+ },
+ ],
+ },
},
- });
+ (state) => ({
+ pagination: state.pagination,
+ rowSelection: state.rowSelection,
+ sorting: state.sorting,
+ }),
+ );
return (
From 15472fb4c0e35658410baf6ad26db50e3ba8d0c9 Mon Sep 17 00:00:00 2001
From: pasqualevitiello
Date: Sun, 6 Sep 2026 13:37:59 +0200
Subject: [PATCH 3/3] fix: restore team members table selection updates
Subscribe only re-renders when its child is a function, so static JSX left checkboxes stale until a sort. Match the members table: subscribe with a render function and toggle rows on click.
Co-authored-by: Cursor
---
.../[id]/members/team-members-page-client.tsx | 218 ++++++++++--------
1 file changed, 118 insertions(+), 100 deletions(-)
diff --git a/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx b/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx
index 7d2cca51f..9bee2d2b5 100644
--- a/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx
+++ b/apps/examples/calcom/app/(settings)/settings/teams/[id]/members/team-members-page-client.tsx
@@ -165,6 +165,15 @@ const members: TeamMember[] = [
},
];
+function shouldIgnoreRowSelectionClick(target: EventTarget | null): boolean {
+ return (
+ target instanceof Element &&
+ target.closest(
+ 'a, button, input, select, textarea, [role="button"], [role="checkbox"], [data-slot="checkbox"], [data-slot="label"]',
+ ) !== null
+ );
+}
+
function getInitials(name: string): string {
const parts = name.trim().split(/\s+/);
if (parts.length === 0) return "";
@@ -252,13 +261,12 @@ function getColumns({
const cols: ColumnDef[] = [
{
cell: ({ row }) => (
-
+
row.toggleSelected(!!value)}
/>
- {`Select ${row.original.name}`}
),
enableSorting: false,
@@ -544,107 +552,117 @@ export function TeamMembersPageClient() {
sorting: state.sorting,
})}
>
-
-
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {headerGroup.headers.map((header) => {
- const columnSize = header.column.getSize();
-
- return (
-
- {header.isPlaceholder ? null : header.column.getCanSort() ? (
- {
- if (
- event.key === "Enter" ||
- event.key === " "
- ) {
- event.preventDefault();
- header.column.getToggleSortingHandler()?.(
- event,
- );
- }
- }}
- role="button"
- tabIndex={0}
- >
- {flexRender(
+ {() => (
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => {
+ const columnSize = header.column.getSize();
+
+ return (
+
+ {header.isPlaceholder ? null : header.column.getCanSort() ? (
+ {
+ if (
+ event.key === "Enter" ||
+ event.key === " "
+ ) {
+ event.preventDefault();
+ header.column.getToggleSortingHandler()?.(
+ event,
+ );
+ }
+ }}
+ role="button"
+ tabIndex={0}
+ >
+ {flexRender(
+ header.column.columnDef.header,
+ header.getContext(),
+ )}
+ {{
+ asc: (
+
+ ),
+ desc: (
+
+ ),
+ }[header.column.getIsSorted() as string] ??
+ null}
+
+ ) : (
+ flexRender(
header.column.columnDef.header,
header.getContext(),
- )}
- {{
- asc: (
-
- ),
- desc: (
-
- ),
- }[header.column.getIsSorted() as string] ?? null}
-
- ) : (
- flexRender(
- header.column.columnDef.header,
- header.getContext(),
- )
- )}
-
- );
- })}
-
- ))}
-
-
- {table.getRowModel().rows.length ? (
- table.getRowModel().rows.map((row) => (
-
- {row.getVisibleCells().map((cell) => (
-
- {flexRender(
- cell.column.columnDef.cell,
- cell.getContext(),
- )}
-
- ))}
+ )
+ )}
+
+ );
+ })}
+
+ ))}
+
+
+ {table.getRowModel().rows.length ? (
+ table.getRowModel().rows.map((row) => (
+ {
+ if (shouldIgnoreRowSelectionClick(event.target))
+ return;
+ row.toggleSelected();
+ }}
+ >
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(
+ cell.column.columnDef.cell,
+ cell.getContext(),
+ )}
+
+ ))}
+
+ ))
+ ) : (
+
+
+ No members found.
+
- ))
- ) : (
-
-
- No members found.
-
-
- )}
-
-
-
+ )}
+
+
+
+ )}
>