diff --git a/.gitignore b/.gitignore index 9ad8d4c877..444f5075df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /.cache +/.nitro +/.output +/.tanstack /coverage /dist /lib diff --git a/biome.json b/biome.json index a5a129ee34..2233d3ad96 100644 --- a/biome.json +++ b/biome.json @@ -4,6 +4,9 @@ "includes": [ "**", "!.cache/**/*", + "!.nitro/**/*", + "!.output/**/*", + "!.tanstack/**/*", "!coverage/**/*", "!dist/**/*", "!lib/**/*", diff --git a/eslint.config.js b/eslint.config.js index d2513453e8..de7d21d584 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -12,7 +12,7 @@ import testingLibrary from 'eslint-plugin-testing-library'; import markdown from '@eslint/markdown'; export default defineConfig([ - globalIgnores(['.cache', 'coverage', 'dist', 'lib']), + globalIgnores(['.cache', '.nitro', '.output', '.tanstack', 'coverage', 'dist', 'lib']), { linterOptions: { diff --git a/index.html b/index.html deleted file mode 100644 index 8e8135b360..0000000000 --- a/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - React Data Grid - - - -
- - - diff --git a/package.json b/package.json index 28d6828837..aa705fa0fe 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ ], "scripts": { "start": "vite serve --clearScreen false", - "preview": "vite preview", + "preview": "node .output/server/index.mjs", "build:website": "vite build", "build": "rolldown -c", "test": "vitest run", @@ -58,13 +58,14 @@ "@faker-js/faker": "^9.9.0", "@ianvs/prettier-plugin-sort-imports": "^4.5.1", "@linaria/core": "^6.3.0", - "@tanstack/react-router": "^1.128.0", - "@tanstack/router-plugin": "^1.128.0", + "@tanstack/react-router": "^1.130.12", + "@tanstack/react-start": "^1.130.15", "@types/node": "^24.0.14", "@types/react": "^19.1.3", "@types/react-dom": "^19.1.3", "@typescript-eslint/eslint-plugin": "^8.37.0", "@typescript-eslint/parser": "^8.37.0", + "@vitejs/plugin-react": "^4.7.0", "@vitejs/plugin-react-oxc": "^0.3.0", "@vitest/browser": "^3.2.4", "@vitest/coverage-v8": "^3.2.4", diff --git a/vite.config.ts b/vite.config.ts index 00cab27f36..b550fc06c3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,4 @@ -import { tanstackRouter } from '@tanstack/router-plugin/vite'; +import { tanstackStart } from '@tanstack/react-start/plugin/vite'; import react from '@vitejs/plugin-react-oxc'; import wyw from '@wyw-in-js/vite'; import { defineConfig } from 'vite'; @@ -56,12 +56,18 @@ export default defineConfig(({ command, isPreview }) => ({ }, plugins: [ (!isTest || isPreview) && - tanstackRouter({ - target: 'react', - generatedRouteTree: 'website/routeTree.gen.ts', - routesDirectory: 'website/routes', - autoCodeSplitting: true, - verboseFileRoutes: false + tanstackStart({ + customViteReactPlugin: true, + tsr: { + srcDirectory: 'website', + // @ts-expect-error types are not correct + autoCodeSplitting: true, + verboseFileRoutes: false + }, + prerender: { + enabled: true, + crawlLinks: true + } }), react({ exclude: ['./.cache/**/*'] diff --git a/website/root.css b/website/root.css index 5e21fcd71d..92c76596d5 100644 --- a/website/root.css +++ b/website/root.css @@ -16,16 +16,13 @@ body { } body { + display: grid; + grid-template-columns: auto 1fr; color-scheme: var(--rdg-color-scheme, light dark); background-color: light-dark(#fff, hsl(0deg 0% 10%)); color: light-dark(#111, #fff); } -#root { - display: grid; - grid-template-columns: auto 1fr; -} - .fill-grid { block-size: 100%; } diff --git a/website/root.tsx b/website/root.tsx deleted file mode 100644 index 1f1d9d7e8a..0000000000 --- a/website/root.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import './root.css'; - -import { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; -import { - createHashHistory, - createRouter, - ErrorComponent, - RouterProvider -} from '@tanstack/react-router'; - -import { routeTree } from './routeTree.gen'; - -const router = createRouter({ - routeTree, - history: createHashHistory(), - caseSensitive: true, - defaultErrorComponent: ErrorComponent, - defaultNotFoundComponent: NotFound, - defaultPendingMinMs: 0, - defaultPreload: 'intent', - defaultStructuralSharing: true, - scrollRestoration: true -}); - -// Register the router instance for type safety -declare module '@tanstack/react-router' { - interface Register { - router: typeof router; - } -} - -function NotFound() { - return 'Nothing to see here'; -} - -createRoot(document.getElementById('root')!).render( - - - -); diff --git a/website/routeTree.gen.ts b/website/routeTree.gen.ts index cf9eb65c5b..298150f6d2 100644 --- a/website/routeTree.gen.ts +++ b/website/routeTree.gen.ts @@ -9,6 +9,10 @@ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import type { CreateFileRoute, FileRoutesByPath } from '@tanstack/react-router' +import type { + CreateServerFileRoute, + ServerFileRoutesByPath, +} from '@tanstack/react-start/server' import { Route as rootRouteImport } from './routes/__root' import { Route as VariableRowHeightRouteImport } from './routes/VariableRowHeight' @@ -465,6 +469,14 @@ declare module './routes/index' { FileRoutesByPath['/']['path'], FileRoutesByPath['/']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/']['parentRoute'], + ServerFileRoutesByPath['/']['id'], + ServerFileRoutesByPath['/']['path'], + ServerFileRoutesByPath['/']['fullPath'], + unknown + > } declare module './routes/AllFeatures' { const createFileRoute: CreateFileRoute< @@ -474,6 +486,14 @@ declare module './routes/AllFeatures' { FileRoutesByPath['/AllFeatures']['path'], FileRoutesByPath['/AllFeatures']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/AllFeatures']['parentRoute'], + ServerFileRoutesByPath['/AllFeatures']['id'], + ServerFileRoutesByPath['/AllFeatures']['path'], + ServerFileRoutesByPath['/AllFeatures']['fullPath'], + unknown + > } declare module './routes/Animation' { const createFileRoute: CreateFileRoute< @@ -483,6 +503,14 @@ declare module './routes/Animation' { FileRoutesByPath['/Animation']['path'], FileRoutesByPath['/Animation']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/Animation']['parentRoute'], + ServerFileRoutesByPath['/Animation']['id'], + ServerFileRoutesByPath['/Animation']['path'], + ServerFileRoutesByPath['/Animation']['fullPath'], + unknown + > } declare module './routes/CellNavigation' { const createFileRoute: CreateFileRoute< @@ -492,6 +520,14 @@ declare module './routes/CellNavigation' { FileRoutesByPath['/CellNavigation']['path'], FileRoutesByPath['/CellNavigation']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/CellNavigation']['parentRoute'], + ServerFileRoutesByPath['/CellNavigation']['id'], + ServerFileRoutesByPath['/CellNavigation']['path'], + ServerFileRoutesByPath['/CellNavigation']['fullPath'], + unknown + > } declare module './routes/ColumnGrouping' { const createFileRoute: CreateFileRoute< @@ -501,6 +537,14 @@ declare module './routes/ColumnGrouping' { FileRoutesByPath['/ColumnGrouping']['path'], FileRoutesByPath['/ColumnGrouping']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/ColumnGrouping']['parentRoute'], + ServerFileRoutesByPath['/ColumnGrouping']['id'], + ServerFileRoutesByPath['/ColumnGrouping']['path'], + ServerFileRoutesByPath['/ColumnGrouping']['fullPath'], + unknown + > } declare module './routes/ColumnSpanning' { const createFileRoute: CreateFileRoute< @@ -510,6 +554,14 @@ declare module './routes/ColumnSpanning' { FileRoutesByPath['/ColumnSpanning']['path'], FileRoutesByPath['/ColumnSpanning']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/ColumnSpanning']['parentRoute'], + ServerFileRoutesByPath['/ColumnSpanning']['id'], + ServerFileRoutesByPath['/ColumnSpanning']['path'], + ServerFileRoutesByPath['/ColumnSpanning']['fullPath'], + unknown + > } declare module './routes/ColumnsReordering' { const createFileRoute: CreateFileRoute< @@ -519,6 +571,14 @@ declare module './routes/ColumnsReordering' { FileRoutesByPath['/ColumnsReordering']['path'], FileRoutesByPath['/ColumnsReordering']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/ColumnsReordering']['parentRoute'], + ServerFileRoutesByPath['/ColumnsReordering']['id'], + ServerFileRoutesByPath['/ColumnsReordering']['path'], + ServerFileRoutesByPath['/ColumnsReordering']['fullPath'], + unknown + > } declare module './routes/CommonFeatures' { const createFileRoute: CreateFileRoute< @@ -528,6 +588,14 @@ declare module './routes/CommonFeatures' { FileRoutesByPath['/CommonFeatures']['path'], FileRoutesByPath['/CommonFeatures']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/CommonFeatures']['parentRoute'], + ServerFileRoutesByPath['/CommonFeatures']['id'], + ServerFileRoutesByPath['/CommonFeatures']['path'], + ServerFileRoutesByPath['/CommonFeatures']['fullPath'], + unknown + > } declare module './routes/ContextMenu' { const createFileRoute: CreateFileRoute< @@ -537,6 +605,14 @@ declare module './routes/ContextMenu' { FileRoutesByPath['/ContextMenu']['path'], FileRoutesByPath['/ContextMenu']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/ContextMenu']['parentRoute'], + ServerFileRoutesByPath['/ContextMenu']['id'], + ServerFileRoutesByPath['/ContextMenu']['path'], + ServerFileRoutesByPath['/ContextMenu']['fullPath'], + unknown + > } declare module './routes/CustomizableRenderers' { const createFileRoute: CreateFileRoute< @@ -546,6 +622,14 @@ declare module './routes/CustomizableRenderers' { FileRoutesByPath['/CustomizableRenderers']['path'], FileRoutesByPath['/CustomizableRenderers']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/CustomizableRenderers']['parentRoute'], + ServerFileRoutesByPath['/CustomizableRenderers']['id'], + ServerFileRoutesByPath['/CustomizableRenderers']['path'], + ServerFileRoutesByPath['/CustomizableRenderers']['fullPath'], + unknown + > } declare module './routes/HeaderFilters' { const createFileRoute: CreateFileRoute< @@ -555,6 +639,14 @@ declare module './routes/HeaderFilters' { FileRoutesByPath['/HeaderFilters']['path'], FileRoutesByPath['/HeaderFilters']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/HeaderFilters']['parentRoute'], + ServerFileRoutesByPath['/HeaderFilters']['id'], + ServerFileRoutesByPath['/HeaderFilters']['path'], + ServerFileRoutesByPath['/HeaderFilters']['fullPath'], + unknown + > } declare module './routes/InfiniteScrolling' { const createFileRoute: CreateFileRoute< @@ -564,6 +656,14 @@ declare module './routes/InfiniteScrolling' { FileRoutesByPath['/InfiniteScrolling']['path'], FileRoutesByPath['/InfiniteScrolling']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/InfiniteScrolling']['parentRoute'], + ServerFileRoutesByPath['/InfiniteScrolling']['id'], + ServerFileRoutesByPath['/InfiniteScrolling']['path'], + ServerFileRoutesByPath['/InfiniteScrolling']['fullPath'], + unknown + > } declare module './routes/MasterDetail' { const createFileRoute: CreateFileRoute< @@ -573,6 +673,14 @@ declare module './routes/MasterDetail' { FileRoutesByPath['/MasterDetail']['path'], FileRoutesByPath['/MasterDetail']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/MasterDetail']['parentRoute'], + ServerFileRoutesByPath['/MasterDetail']['id'], + ServerFileRoutesByPath['/MasterDetail']['path'], + ServerFileRoutesByPath['/MasterDetail']['fullPath'], + unknown + > } declare module './routes/MillionCells' { const createFileRoute: CreateFileRoute< @@ -582,6 +690,14 @@ declare module './routes/MillionCells' { FileRoutesByPath['/MillionCells']['path'], FileRoutesByPath['/MillionCells']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/MillionCells']['parentRoute'], + ServerFileRoutesByPath['/MillionCells']['id'], + ServerFileRoutesByPath['/MillionCells']['path'], + ServerFileRoutesByPath['/MillionCells']['fullPath'], + unknown + > } declare module './routes/NoRows' { const createFileRoute: CreateFileRoute< @@ -591,6 +707,14 @@ declare module './routes/NoRows' { FileRoutesByPath['/NoRows']['path'], FileRoutesByPath['/NoRows']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/NoRows']['parentRoute'], + ServerFileRoutesByPath['/NoRows']['id'], + ServerFileRoutesByPath['/NoRows']['path'], + ServerFileRoutesByPath['/NoRows']['fullPath'], + unknown + > } declare module './routes/ResizableGrid' { const createFileRoute: CreateFileRoute< @@ -600,6 +724,14 @@ declare module './routes/ResizableGrid' { FileRoutesByPath['/ResizableGrid']['path'], FileRoutesByPath['/ResizableGrid']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/ResizableGrid']['parentRoute'], + ServerFileRoutesByPath['/ResizableGrid']['id'], + ServerFileRoutesByPath['/ResizableGrid']['path'], + ServerFileRoutesByPath['/ResizableGrid']['fullPath'], + unknown + > } declare module './routes/RowGrouping' { const createFileRoute: CreateFileRoute< @@ -609,6 +741,14 @@ declare module './routes/RowGrouping' { FileRoutesByPath['/RowGrouping']['path'], FileRoutesByPath['/RowGrouping']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/RowGrouping']['parentRoute'], + ServerFileRoutesByPath['/RowGrouping']['id'], + ServerFileRoutesByPath['/RowGrouping']['path'], + ServerFileRoutesByPath['/RowGrouping']['fullPath'], + unknown + > } declare module './routes/RowsReordering' { const createFileRoute: CreateFileRoute< @@ -618,6 +758,14 @@ declare module './routes/RowsReordering' { FileRoutesByPath['/RowsReordering']['path'], FileRoutesByPath['/RowsReordering']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/RowsReordering']['parentRoute'], + ServerFileRoutesByPath['/RowsReordering']['id'], + ServerFileRoutesByPath['/RowsReordering']['path'], + ServerFileRoutesByPath['/RowsReordering']['fullPath'], + unknown + > } declare module './routes/ScrollToCell' { const createFileRoute: CreateFileRoute< @@ -627,6 +775,14 @@ declare module './routes/ScrollToCell' { FileRoutesByPath['/ScrollToCell']['path'], FileRoutesByPath['/ScrollToCell']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/ScrollToCell']['parentRoute'], + ServerFileRoutesByPath['/ScrollToCell']['id'], + ServerFileRoutesByPath['/ScrollToCell']['path'], + ServerFileRoutesByPath['/ScrollToCell']['fullPath'], + unknown + > } declare module './routes/TreeView' { const createFileRoute: CreateFileRoute< @@ -636,6 +792,14 @@ declare module './routes/TreeView' { FileRoutesByPath['/TreeView']['path'], FileRoutesByPath['/TreeView']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/TreeView']['parentRoute'], + ServerFileRoutesByPath['/TreeView']['id'], + ServerFileRoutesByPath['/TreeView']['path'], + ServerFileRoutesByPath['/TreeView']['fullPath'], + unknown + > } declare module './routes/VariableRowHeight' { const createFileRoute: CreateFileRoute< @@ -645,6 +809,14 @@ declare module './routes/VariableRowHeight' { FileRoutesByPath['/VariableRowHeight']['path'], FileRoutesByPath['/VariableRowHeight']['fullPath'] > + + const createServerFileRoute: CreateServerFileRoute< + ServerFileRoutesByPath['/VariableRowHeight']['parentRoute'], + ServerFileRoutesByPath['/VariableRowHeight']['id'], + ServerFileRoutesByPath['/VariableRowHeight']['path'], + ServerFileRoutesByPath['/VariableRowHeight']['fullPath'], + unknown + > } const rootRouteChildren: RootRouteChildren = { diff --git a/website/router.tsx b/website/router.tsx new file mode 100644 index 0000000000..893620de29 --- /dev/null +++ b/website/router.tsx @@ -0,0 +1,28 @@ +import { createRouter as createTanStackRouter, ErrorComponent } from '@tanstack/react-router'; + +import { routeTree } from './routeTree.gen'; + +export function createRouter() { + return createTanStackRouter({ + basepath: '/react-data-grid/', + routeTree, + caseSensitive: true, + defaultErrorComponent: ErrorComponent, + defaultNotFoundComponent: NotFound, + defaultPendingMinMs: 0, + defaultPreload: 'intent', + defaultStructuralSharing: true, + scrollRestoration: true + }); +} + +// Register the router instance for type safety +declare module '@tanstack/react-router' { + interface Register { + router: ReturnType; + } +} + +function NotFound() { + return 'Nothing to see here'; +} diff --git a/website/routes/__root.tsx b/website/routes/__root.tsx index 796e87ff3a..e2db03fb8c 100644 --- a/website/routes/__root.tsx +++ b/website/routes/__root.tsx @@ -1,5 +1,7 @@ -import { useState } from 'react'; -import { createRootRoute, Outlet } from '@tanstack/react-router'; +import '../root.css'; + +import { useState, type ReactNode } from 'react'; +import { createRootRoute, HeadContent, Outlet, Scripts } from '@tanstack/react-router'; import { css } from '@linaria/core'; import type { Direction } from '../../src/types'; @@ -7,6 +9,21 @@ import { DirectionContext } from '../directionContext'; import Nav from '../Nav'; export const Route = createRootRoute({ + head: () => ({ + meta: [ + { + name: 'viewport', + content: 'width=device-width, initial-scale=1' + }, + { + name: 'description', + content: 'Feature-rich and customizable data grid React component.' + }, + { + title: 'React Data Grid' + } + ] + }), component: Root }); @@ -23,11 +40,27 @@ function Root() { const [direction, setDirection] = useState('ltr'); return ( - -