diff --git a/package.json b/package.json index 14449fa4f..b40fade8a 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@tanstack/react-router-ssr-query": "1.167.1", "@tanstack/react-start": "1.168.26", "@tanstack/react-start-client": "1.168.14", - "@tanstack/react-table": "^8.21.3", + "@tanstack/react-table": "9.0.0-beta.80", "@tanstack/workflow-core": "0.0.4", "@tanstack/workflow-runtime": "0.0.3", "@tanstack/workflow-store-drizzle-postgres": "0.0.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70cfa082d..0d97e5db5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -127,8 +127,8 @@ importers: specifier: 1.168.14 version: 1.168.14(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-table': - specifier: ^8.21.3 - version: 8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: 9.0.0-beta.80 + version: 9.0.0-beta.80(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/workflow-core': specifier: 0.0.4 version: 0.0.4(@opentelemetry/api@1.9.1) @@ -3560,12 +3560,11 @@ packages: 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 - '@tanstack/react-table@8.21.3': - resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} - engines: {node: '>=12'} + '@tanstack/react-table@9.0.0-beta.80': + resolution: {integrity: sha512-oBNjj/jl5D57LuWFy7tbZX4Td2W3Huhzx5s1k4GVBz1tyFfPGhEsWi3VM6uJKs4Ayz0IU8ODWzO0fdJ+RQlXyQ==} + engines: {node: '>=20'} peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' + react: '>=18' '@tanstack/redact@0.0.19': resolution: {integrity: sha512-fsEaG6sCooTQawyXff83FnLaZjhGoKoAWLPPTkEib/lqxATeloZc7Rq3TDRn9nQE1HAkQfuMjjCsYNRW3swRnQ==} @@ -3659,9 +3658,9 @@ packages: '@tanstack/store@0.9.3': resolution: {integrity: sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw==} - '@tanstack/table-core@8.21.3': - resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==} - engines: {node: '>=12'} + '@tanstack/table-core@9.0.0-beta.80': + resolution: {integrity: sha512-tD98Q6/qzjvbEomMtDqxrAQUAf9nsBD7RihY1073E0eaeYwP3GyW5Gdlb+PztSk9F0CsYArXeOqcrt1hV29O8w==} + engines: {node: '>=20'} '@tanstack/virtual-file-routes@1.162.0': resolution: {integrity: sha512-uhOeFyxLcU41HzvrxsGpiWdcMbScY1EDgbZ5K7DVRMYInbLYWAC0EA/kx9wXAoSM8q82bUG2hRl8+EAjE6XAbA==} @@ -9570,11 +9569,13 @@ snapshots: react-dom: 19.2.3(react@19.2.3) use-sync-external-store: 1.6.0(react@19.2.3) - '@tanstack/react-table@8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + '@tanstack/react-table@9.0.0-beta.80(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: - '@tanstack/table-core': 8.21.3 + '@tanstack/react-store': 0.11.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@tanstack/table-core': 9.0.0-beta.80 react: 19.2.3 - react-dom: 19.2.3(react@19.2.3) + transitivePeerDependencies: + - react-dom '@tanstack/redact@0.0.19(vite@8.0.13(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.7.0)(tsx@4.21.0)(yaml@2.9.0))': optionalDependencies: @@ -9703,7 +9704,9 @@ snapshots: '@tanstack/store@0.9.3': {} - '@tanstack/table-core@8.21.3': {} + '@tanstack/table-core@9.0.0-beta.80': + dependencies: + '@tanstack/store': 0.11.0 '@tanstack/virtual-file-routes@1.162.0': {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e6add2aca..076b0d1a6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,10 @@ packages: - . +minimumReleaseAgeExclude: + - '@tanstack/react-table@9.0.0-beta.80' + - '@tanstack/table-core@9.0.0-beta.80' + overrides: cross-spawn: '>=6.0.6' glob: '>=10.5.0' diff --git a/public/images/table/component-libraries/chakra-ui.svg b/public/images/table/component-libraries/chakra-ui.svg new file mode 100644 index 000000000..712e8e8da --- /dev/null +++ b/public/images/table/component-libraries/chakra-ui.svg @@ -0,0 +1 @@ +Chakra UI diff --git a/public/images/table/component-libraries/hero-ui.svg b/public/images/table/component-libraries/hero-ui.svg new file mode 100644 index 000000000..469b56fcb --- /dev/null +++ b/public/images/table/component-libraries/hero-ui.svg @@ -0,0 +1 @@ +HeroUI diff --git a/public/images/table/component-libraries/mantine.svg b/public/images/table/component-libraries/mantine.svg new file mode 100644 index 000000000..da84dcff5 --- /dev/null +++ b/public/images/table/component-libraries/mantine.svg @@ -0,0 +1 @@ +Mantine diff --git a/public/images/table/component-libraries/material-ui.svg b/public/images/table/component-libraries/material-ui.svg new file mode 100644 index 000000000..e0ee734f9 --- /dev/null +++ b/public/images/table/component-libraries/material-ui.svg @@ -0,0 +1 @@ +Material UI diff --git a/public/images/table/component-libraries/react-aria.svg b/public/images/table/component-libraries/react-aria.svg new file mode 100644 index 000000000..1b6ad7d31 --- /dev/null +++ b/public/images/table/component-libraries/react-aria.svg @@ -0,0 +1 @@ +React Aria diff --git a/public/images/table/component-libraries/shadcn-ui.svg b/public/images/table/component-libraries/shadcn-ui.svg new file mode 100644 index 000000000..d3b0c0cd1 --- /dev/null +++ b/public/images/table/component-libraries/shadcn-ui.svg @@ -0,0 +1 @@ +shadcn/ui diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 402ebf2e7..623295184 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -42,7 +42,6 @@ const FOOTER_COLUMNS: Array = [ { label: 'Discord', to: 'https://tlinz.com/discord' }, { label: 'GitHub', to: 'https://github.com/TanStack' }, { label: 'Maintainers', to: '/maintainers' }, - { label: 'Contributors', to: '/maintainers' }, { label: 'Showcase', to: '/showcase' }, ], }, diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 68388b894..3a60ba304 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -212,12 +212,6 @@ const NAV_GROUPS = [ description: 'Meet the people maintaining the stack.', icon: CodeIcon, }, - { - label: 'Contributors', - to: '/maintainers', - description: 'Core, library, and community contributors.', - icon: UsersIcon, - }, { label: 'Showcase', to: '/showcase', diff --git a/src/components/landing/TableLanding.tsx b/src/components/landing/TableLanding.tsx index b7f948d27..727f47a62 100644 --- a/src/components/landing/TableLanding.tsx +++ b/src/components/landing/TableLanding.tsx @@ -1,24 +1,33 @@ import * as React from 'react' import { - flexRender, - getCoreRowModel, - getFilteredRowModel, - getPaginationRowModel, - getSortedRowModel, - useReactTable, + cellSelectionFeature, + columnFilteringFeature, + columnVisibilityFeature, + createFilteredRowModel, + createPaginatedRowModel, + createSortedRowModel, + globalFilteringFeature, + rowPaginationFeature, + rowSelectionFeature, + rowSortingFeature, + sortFn_alphanumeric, + sortFn_basic, + tableFeatures, + useTable, + type Cell, type ColumnFiltersState, type ColumnDef, + type ColumnVisibilityState, type PaginationState, type RowSelectionState, type SortingState, - type VisibilityState, } from '@tanstack/react-table' +import { useHotkeys } from '@tanstack/react-hotkeys' import { - ArrowsHorizontalIcon, + ArrowRightIcon, + BracketsCurlyIcon, CaretDownIcon, CaretUpIcon, - FunnelIcon, - GridNineIcon, MagnifyingGlassIcon, RowsIcon, SlidersHorizontalIcon, @@ -34,7 +43,7 @@ import { } from './LibraryLanding' const tablePrompt = - 'Build a TanStack Table data grid for a TypeScript app. Keep it headless: define column definitions, row models, sorting, filtering, pagination, selection, visibility, and controlled state without prescribing markup. Render semantic table elements and synchronize table state to the URL or server only where the product needs it.' + 'Build a TanStack Table V9 data grid for a TypeScript app. Keep it headless. Define a stable tableFeatures object with only the feature plugins, create*RowModel slots, and function registries the product needs. Use TanStack Store-backed table state, selectors, or table.Subscribe for reactive reads, and external atoms only for slices the app must own. Render semantic table elements and synchronize state to the URL or server only where the product needs it.' type TableIssue = { id: string @@ -45,8 +54,20 @@ type TableIssue = { } type StatusFilter = 'all' | TableIssue['status'] -type Surface = 'table' | 'cards' | 'dense' -type StateOwner = 'component' | 'url' | 'server' +type StateMode = 'selected' | 'subscribed' | 'external' + +const tableWorkbenchFeatures = tableFeatures({ + cellSelectionFeature, + columnFilteringFeature, + globalFilteringFeature, + rowSortingFeature, + rowPaginationFeature, + rowSelectionFeature, + columnVisibilityFeature, + filteredRowModel: createFilteredRowModel(), + sortedRowModel: createSortedRowModel(), + paginatedRowModel: createPaginatedRowModel(), +}) const tableRows: Array = [ { @@ -114,54 +135,139 @@ const statusFilters: Array<{ label: string; value: StatusFilter }> = [ { label: 'Shipped', value: 'shipped' }, ] -const rowModels = [ - { label: 'Core', code: 'getCoreRowModel()', rows: '8 rows', icon: RowsIcon }, +const tableResponsibilities = ['State', 'Row processing', 'Typed APIs'] as const + +const developerControls = [ + 'Markup & semantics', + 'Styles & components', + 'Events & interactions', +] as const + +const componentLibraryExamples = [ { - label: 'Filter', - code: 'getFilteredRowModel()', - rows: '5 rows', - icon: FunnelIcon, + name: 'shadcn/ui + Base UI', + detail: 'Base UI', + logo: '/images/table/component-libraries/shadcn-ui.svg', + href: '/table/latest/docs/framework/react/examples/kitchen-sink-shadcn-base', }, { - label: 'Sort', - code: 'getSortedRowModel()', - rows: '5 rows', - icon: ArrowsHorizontalIcon, + name: 'shadcn/ui + Radix UI', + detail: 'Radix UI', + logo: '/images/table/component-libraries/shadcn-ui.svg', + href: '/table/latest/docs/framework/react/examples/kitchen-sink-shadcn-radix', + }, + { + name: 'HeroUI', + detail: 'HeroUI', + logo: '/images/table/component-libraries/hero-ui.svg', + href: '/table/latest/docs/framework/react/examples/kitchen-sink-hero-ui', + }, + { + name: 'React Aria', + detail: 'Adobe', + logo: '/images/table/component-libraries/react-aria.svg', + href: '/table/latest/docs/framework/react/examples/kitchen-sink-react-aria', + }, + { + name: 'Material UI', + detail: 'MUI', + logo: '/images/table/component-libraries/material-ui.svg', + href: '/table/latest/docs/framework/react/examples/kitchen-sink-material-ui', + }, + { + name: 'Mantine', + detail: 'Mantine', + logo: '/images/table/component-libraries/mantine.svg', + href: '/table/latest/docs/framework/react/examples/kitchen-sink-mantine', }, { - label: 'Page', - code: 'getPaginationRowModel()', - rows: '4 rows', - icon: StackIcon, + name: 'Chakra UI', + detail: 'Chakra UI', + logo: '/images/table/component-libraries/chakra-ui.svg', + href: '/table/latest/docs/framework/react/examples/kitchen-sink-chakra-ui', }, ] as const -const stateOwners: Record< - StateOwner, +const stateModes: Record< + StateMode, { code: string; note: string; path: string } > = { - component: { - code: 'onSortingChange: setSorting', - note: 'Fast local interaction with no external coordination.', - path: 'header → table state → row model', + selected: { + code: 'const sorting = table.state.sorting', + note: 'Select the state a component needs when creating its table instance.', + path: 'table store → selected state → component', }, - url: { - code: 'navigate({ search: { sort } })', - note: 'Shareable, restorable state for product navigation.', - path: 'header → URL search → table state', + subscribed: { + code: ' state.sorting}>', + note: 'Move a reactive read to the smallest part of the tree that renders it.', + path: 'sorting atom → subscription island → UI', }, - server: { - code: 'manualSorting: true', - note: 'Table reports the next sort state; your data layer fetches the ordered rows.', - path: 'header → controlled sorting → API query', + external: { + code: 'atoms: { sorting: sortingAtom }', + note: 'Give an external TanStack Store atom ownership when other systems share the slice.', + path: 'external atom → table feature → app', }, } +const rowModelStages = [ + { + code: 'automatic', + label: 'Core', + note: 'data to rows', + }, + { + code: 'createFilteredRowModel()', + label: 'Filter', + note: 'column + global', + }, + { + code: 'createGroupedRowModel()', + label: 'Group', + note: 'grouped rows', + }, + { + code: 'createSortedRowModel()', + label: 'Sort', + note: 'ordered rows', + }, + { + code: 'createExpandedRowModel()', + label: 'Expand', + note: 'visible sub-rows', + }, + { + code: 'createPaginatedRowModel()', + label: 'Paginate', + note: 'current page', + }, +] as const + +const tableToolbox = [ + { + label: 'Custom features', + code: 'tableFeatures({ densityFeature })', + detail: + 'Add state, options, and APIs through the same extension system used by built-in features.', + }, + { + label: 'Reusable tables', + code: 'createTableHook({ features, ... })', + detail: + 'Share typed features, options, column helpers, and registered components across a product.', + }, + { + label: 'Devtools', + code: 'useTanStackTableDevtools(table)', + detail: + 'Inspect table state and derived data in supported framework integrations instead of logging internals.', + }, +] as const + export default function TableLanding() { return ( } libraryId="table" prompt={tablePrompt} @@ -170,51 +276,106 @@ export default function TableLanding() {
-
- - -
+ + + + + +
) } +function ComponentLibraryExamples() { + return ( +
+
+

+ Already using one of these popular component libraries? +

+

+ Check out our official component library examples. +

+
+ +
+ {componentLibraryExamples.map((example) => ( + + + + + + + {example.name} + + + {example.detail} example + + + + ))} +
+
+ ) +} + function TableWorkbench() { + const gridRef = React.useRef(null) const [globalFilter, setGlobalFilter] = React.useState('') const [statusFilter, setStatusFilter] = React.useState('all') const [sorting, setSorting] = React.useState([ { id: 'score', desc: true }, ]) const [columnVisibility, setColumnVisibility] = - React.useState({ owner: false }) + React.useState({ owner: false }) const [rowSelection, setRowSelection] = React.useState({}) const [pagination, setPagination] = React.useState({ pageIndex: 0, @@ -226,10 +387,13 @@ function TableWorkbench() { [statusFilter], ) - const columns = React.useMemo>>( + const columns = React.useMemo< + Array> + >( () => [ { id: 'select', + enableCellSelection: false, header: ({ table }) => ( { if (input) { - input.indeterminate = table.getIsSomePageRowsSelected() + input.indeterminate = + table.getIsSomePageRowsSelected() && + !table.getIsAllPageRowsSelected() } }} type="checkbox" @@ -260,29 +426,38 @@ function TableWorkbench() { /> ), }, - { accessorKey: 'project', header: 'Project' }, - { accessorKey: 'owner', header: 'Owner' }, + { + accessorKey: 'project', + header: 'Project', + sortFn: sortFn_alphanumeric, + }, + { + accessorKey: 'owner', + header: 'Owner', + sortFn: sortFn_alphanumeric, + }, { accessorKey: 'status', header: 'Status', cell: ({ getValue }) => ( ()} /> ), + filterFn: (row, columnId, value) => + row.getValue(columnId) === value, + sortFn: sortFn_alphanumeric, }, - { accessorKey: 'score', header: 'Score' }, + { accessorKey: 'score', header: 'Score', sortFn: sortFn_basic }, ], [], ) - const table = useReactTable({ + const table = useTable({ + features: tableWorkbenchFeatures, columns, data: tableRows, + enableCellSelection: true, enableRowSelection: true, - getCoreRowModel: getCoreRowModel(), - getFilteredRowModel: getFilteredRowModel(), - getPaginationRowModel: getPaginationRowModel(), getRowId: (row) => row.id, - getSortedRowModel: getSortedRowModel(), globalFilterFn: (row, _columnId, filterValue) => { const search = String(filterValue).trim().toLowerCase() if (!search) return true @@ -306,8 +481,40 @@ function TableWorkbench() { }, }) + useHotkeys( + [ + { hotkey: 'ArrowUp', callback: () => table.moveCellSelection('up') }, + { hotkey: 'ArrowDown', callback: () => table.moveCellSelection('down') }, + { hotkey: 'ArrowLeft', callback: () => table.moveCellSelection('left') }, + { + hotkey: 'ArrowRight', + callback: () => table.moveCellSelection('right'), + }, + { + hotkey: 'Shift+ArrowUp', + callback: () => table.extendCellSelection('up'), + }, + { + hotkey: 'Shift+ArrowDown', + callback: () => table.extendCellSelection('down'), + }, + { + hotkey: 'Shift+ArrowLeft', + callback: () => table.extendCellSelection('left'), + }, + { + hotkey: 'Shift+ArrowRight', + callback: () => table.extendCellSelection('right'), + }, + { hotkey: 'Mod+A', callback: () => table.selectAllCells() }, + { hotkey: 'Escape', callback: () => table.resetCellSelection(true) }, + ], + { preventDefault: true, target: gridRef }, + ) + const filteredRows = table.getFilteredRowModel().rows.length const selectedRows = table.getSelectedRowModel().rows.length + const selectedCells = table.getSelectedCellCount() return ( @@ -381,7 +588,23 @@ function TableWorkbench() { -
+
+ +
+ +
{table.getHeaderGroups().map((headerGroup) => ( @@ -407,10 +630,7 @@ function TableWorkbench() { onClick={header.column.getToggleSortingHandler()} type="button" > - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {sort === 'asc' ? ( ))} @@ -486,7 +714,7 @@ function TableWorkbench() { - page {table.getState().pagination.pageIndex + 1} /{' '} + page {table.state.pagination.pageIndex + 1} /{' '} {Math.max(table.getPageCount(), 1)} @@ -495,178 +723,88 @@ function TableWorkbench() { ) } -function RowPipeline() { - return ( -
- {rowModels.map((model, index) => { - const Icon = model.icon - return ( -
-
- ) - })} -
- ) -} - -function SurfaceLab() { - const [surface, setSurface] = React.useState('table') - const rows = tableRows.slice(0, 4) - +function OwnershipModel() { return ( - -
-
- {(['table', 'cards', 'dense'] as const).map((item) => ( - - ))} -
-
-
- {surface === 'table' ? ( -
- {rows.map((row) => ( -
- - {row.id} - - - {row.project} - - - {row.score} - -
- ))} -
- ) : surface === 'cards' ? ( -
- {rows.map((row) => ( + +
+
+

+ TanStack Table handles +

+

+ Headless table logic +

+
+ {tableResponsibilities.map((responsibility) => (
- -

- {row.project} -

-

- {row.owner} · score {row.score} -

+ {responsibility}
))}
- ) : ( -
- {rows.map((row) => ( +
+ +
+

+ You control +

+

+ 100% of the rendered result +

+
+ {developerControls.map((control) => (
- - - {row.id} - - - {row.project} - - - {row.status} - + {control}
))}
- )} +
- - ) -} -function TableVirtualBoundary() { - return ( -
-
-

- Table -

-

- Owns columns, row models, feature state, and the data handed to your - renderer. -

-
-
-

- Virtual -

-

- Measures the scroll surface and limits which rows or columns are - mounted. Pair it with Table when rendering volume demands it. -

+
+
+

+ Works with your stack +

+

+ Use any component library or design system, including your own. +

+
+ + headless logic → your UI +
-
+ ) } function StateSwitchboard() { - const [owner, setOwner] = React.useState('url') - const selected = stateOwners[owner] + const [mode, setMode] = React.useState('subscribed') + const selected = stateModes[mode] return ( - +
- {(['component', 'url', 'server'] as const).map((item) => ( + {(['selected', 'subscribed', 'external'] as const).map((item) => (
{headerGroup.headers.map((header) => ( ))} @@ -310,7 +308,7 @@ export default function SimpleTable() { {row.getVisibleCells().map((cell) => ( ))} diff --git a/src/libraries/libraries.ts b/src/libraries/libraries.ts index 92aa984c3..891e25282 100644 --- a/src/libraries/libraries.ts +++ b/src/libraries/libraries.ts @@ -292,10 +292,10 @@ export const table: LibrarySlim = { ...categoryStyles.ui, name: 'TanStack Table', to: '/table', - tagline: 'Headless UI for building powerful tables & datagrids', + tagline: 'Headless, type-safe table and data-grid infrastructure', description: - 'Supercharge your tables or build a datagrid from scratch in any framework while retaining 100% control over markup and styles.', - badge: undefined, + 'Build tables and data grids with feature-level tree shaking, reactive state, fast row models, and complete control over markup and styles.', + badge: 'fresh', repo: 'tanstack/table', frameworks: [ 'angular', @@ -306,14 +306,13 @@ export const table: LibrarySlim = { 'solid', 'svelte', 'vue', - 'qwik', 'lit', 'alpine', 'vanilla', ], - latestVersion: 'v8', + latestVersion: 'v9', latestBranch: 'main', - availableVersions: ['v8', 'beta'], + availableVersions: ['v9', 'v8', 'beta'], scarfId: 'dc8b39e1-3fe9-4f3a-8e56-d4e2cf420a9e', defaultDocs: 'overview', sitemap: { @@ -400,7 +399,7 @@ export const form: LibrarySlim = { tagline: 'Headless UI for building performant and type-safe forms', description: 'Headless, performant, and type-safe form state management for TS/JS, React, Preact, Vue, Angular, Solid, Lit and Svelte.', - badge: 'new', + badge: undefined, repo: 'tanstack/form', corePackageName: '@tanstack/form-core', npmPackageNames: ['@tanstack/form-core'], diff --git a/src/libraries/maintainers.ts b/src/libraries/maintainers.ts index 4b384c2d9..be684e229 100644 --- a/src/libraries/maintainers.ts +++ b/src/libraries/maintainers.ts @@ -145,7 +145,7 @@ export const allMaintainers: Maintainer[] = [ maintainerOf: ['table', 'store'], contributorOf: ['virtual'], consultantOf: ['query'], - frameworkExpertise: ['react', 'preact', 'solid'], + frameworkExpertise: ['react', 'preact', 'solid', 'octane'], specialties: ['Data Grids', 'Performance', 'Dashboards'], social: { twitter: 'https://x.com/kevinvancott', diff --git a/src/libraries/table.tsx b/src/libraries/table.tsx index 825d9c28b..fe9b39bed 100644 --- a/src/libraries/table.tsx +++ b/src/libraries/table.tsx @@ -1,5 +1,5 @@ import { - PersonSimpleIcon, + BracketsCurlyIcon, LightningIcon, GearIcon, } from '@phosphor-icons/react' @@ -10,7 +10,7 @@ const textStyles = 'text-category-ui' export const tableProject = { ...table, - description: `Supercharge your tables or build a datagrid from scratch for TS/JS, React, Vue, Solid, Svelte, Qwik, Angular, and Lit while retaining 100% control over markup and styles.`, + description: `Headless, type-safe table and data-grid infrastructure with feature-level tree shaking, reactive state, fast row models, and adapters for React, Preact, Vue, Solid, Svelte, Angular, Ember, Lit, Alpine, and Octane.`, latestBranch: 'main', defaultDocs: 'introduction', legacyPackages: ['react-table'], @@ -46,52 +46,54 @@ export const tableProject = { ], featureHighlights: [ { - title: 'Designed for zero design', + title: '100% Control', icon: (
- +
), description: (
- What good is a powerful table if that super hip designer you just - hired can't work their UI magic on it?{' '} + TanStack Table provides the state, row processing, and typed APIs + without prescribing your markup or styles. Having 100% control of your + code matters more than ever.{' '} - TanStack Table is headless by design + Your semantics, components, design system, interactions, and source + code stay yours. Use any component library or design system, + including your own. - , which means 100% control down to the very smallest HTML tag, - component, class and style. Pixel Perfection? Go for it!
), }, { - title: 'Big Power, Small Package', + title: 'Reactive by Design', icon: , description: (
- Don't be fooled by the small bundle size. TanStack Table is a - workhorse. It's built to materialize, filter, sort, group, aggregate, - paginate and display massive data sets using a very small API surface. - Wire up your new or existing tables and{' '} + Every registered state slice is backed by TanStack Store, whose + fine-grained reactivity is built on alien-signals. Read a selected + snapshot, subscribe exactly where state is rendered, or own a slice + with an external atom.{' '} - watch your users become instantly more productive + Fine-grained reactivity keeps unrelated parts of a large table out + of the render path. - .
), }, { - title: 'Extensible', + title: 'Built to Extend', icon: , description: (
- TanStack table ships with excellent defaults to get you off the ground - as fast as possible, but nothing is stopping you from{' '} + Custom features use the same extension points as Table's built-ins. + Compose shared options with tableOptions, build app-level table + systems with createTableHook, and inspect live instances with the + supported Devtools integration.{' '} - customizing and overriding literally everything to your liking + Scale from one headless table to a typed table platform for your + whole product. - . Feeling tenacious enough to build your own Sheets/Excel/AirTable - clone? Be our guest 😉
), }, diff --git a/src/routes/admin/audit.tsx b/src/routes/admin/audit.tsx index 5dc8c153e..76b0b0c87 100644 --- a/src/routes/admin/audit.tsx +++ b/src/routes/admin/audit.tsx @@ -12,12 +12,12 @@ import { TableRow, TableCell, } from '~/components/TableComponents' +import { flexRender } from '@tanstack/react-table' import { - useReactTable, getCoreRowModel, - flexRender, - type ColumnDef, -} from '@tanstack/react-table' + useLegacyTable as useReactTable, +} from '@tanstack/react-table/legacy' +import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy' import * as v from 'valibot' import { listAuditLogs } from '~/utils/audit.functions' import { ShieldIcon, CaretDownIcon, CaretUpIcon } from '@phosphor-icons/react' diff --git a/src/routes/admin/github-stats.tsx b/src/routes/admin/github-stats.tsx index bf952b3c7..8a36b7f72 100644 --- a/src/routes/admin/github-stats.tsx +++ b/src/routes/admin/github-stats.tsx @@ -10,12 +10,12 @@ import { TableRow, TableCell, } from '~/components/TableComponents' +import { flexRender } from '@tanstack/react-table' import { - useReactTable, getCoreRowModel, - flexRender, - type ColumnDef, -} from '@tanstack/react-table' + useLegacyTable as useReactTable, +} from '@tanstack/react-table/legacy' +import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy' import { listGitHubStatsCache, refreshGitHubStats, diff --git a/src/routes/admin/logins.tsx b/src/routes/admin/logins.tsx index ae3d072e2..e00e3a38f 100644 --- a/src/routes/admin/logins.tsx +++ b/src/routes/admin/logins.tsx @@ -12,13 +12,15 @@ import { TableRow, TableCell, } from '~/components/TableComponents' +import { flexRender } from '@tanstack/react-table' import { - useReactTable, getCoreRowModel, - flexRender, - type ColumnDef, - type Column, -} from '@tanstack/react-table' + useLegacyTable as useReactTable, +} from '@tanstack/react-table/legacy' +import type { + LegacyColumn as Column, + LegacyColumnDef as ColumnDef, +} from '@tanstack/react-table/legacy' import * as v from 'valibot' import { listLoginHistory } from '~/utils/audit.functions' import { SignInIcon } from '@phosphor-icons/react' diff --git a/src/routes/admin/roles.$roleId.tsx b/src/routes/admin/roles.$roleId.tsx index 27a020fb5..85cd06bad 100644 --- a/src/routes/admin/roles.$roleId.tsx +++ b/src/routes/admin/roles.$roleId.tsx @@ -4,12 +4,12 @@ import { useRemoveUsersFromRole } from '~/utils/mutations' import { useQuery } from '@tanstack/react-query' import { getRole, getUsersWithRole } from '~/utils/roles.functions' import { useCurrentUserQuery } from '~/hooks/useCurrentUser' +import { flexRender } from '@tanstack/react-table' import { - useReactTable, getCoreRowModel, - flexRender, - type ColumnDef, -} from '@tanstack/react-table' + useLegacyTable as useReactTable, +} from '@tanstack/react-table/legacy' +import type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy' import { ArrowLeftIcon, LockIcon, diff --git a/src/routes/admin/roles.index.tsx b/src/routes/admin/roles.index.tsx index 7bd8b6df7..ded0d002f 100644 --- a/src/routes/admin/roles.index.tsx +++ b/src/routes/admin/roles.index.tsx @@ -14,12 +14,12 @@ import { useState, useMemo, useCallback } from 'react' import { useQuery, keepPreviousData } from '@tanstack/react-query' import { useCreateRole, useUpdateRole, useDeleteRole } from '~/utils/mutations' import { listRoles, sendTestModeratorEmail } from '~/utils/roles.functions' +import { flexRender } from '@tanstack/react-table' import { - useReactTable, getCoreRowModel, - flexRender, - type Row, -} from '@tanstack/react-table' + useLegacyTable as useReactTable, +} from '@tanstack/react-table/legacy' +import type { LegacyRow as Row } from '@tanstack/react-table/legacy' import { PencilSimpleLineIcon, PlusIcon, diff --git a/src/routes/admin/users.tsx b/src/routes/admin/users.tsx index 970386855..65177d8cb 100644 --- a/src/routes/admin/users.tsx +++ b/src/routes/admin/users.tsx @@ -12,13 +12,15 @@ import { TableRow, TableCell, } from '~/components/TableComponents' +import { flexRender } from '@tanstack/react-table' import { - useReactTable, getCoreRowModel, - flexRender, - type ColumnDef, - type Column, -} from '@tanstack/react-table' + useLegacyTable as useReactTable, +} from '@tanstack/react-table/legacy' +import type { + LegacyColumn as Column, + LegacyColumnDef as ColumnDef, +} from '@tanstack/react-table/legacy' import { useUpdateUserCapabilities, useAdminSetAdsDisabled,
- {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} +
- {flexRender( - header.column.columnDef.header, - header.getContext(), - )} +
- {flexRender(cell.column.columnDef.cell, cell.getContext())} +