From 079cf8f4fdb0c176a27e92bd732fae580f8be179 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Dec 2025 07:31:25 +0000 Subject: [PATCH] feat(examples): add use-case driven List, Horizontal List, and Grid examples Add three new React examples that focus on common use cases rather than implementation details. Each example defaults to dynamic sizing but includes interactive controls to switch between fixed, variable, and dynamic modes, helping users understand when to use each approach. - List: Vertical list virtualization with mode switching - Horizontal List: Horizontal list/carousel virtualization - Grid: 2D grid virtualization with both row and column virtualization --- docs/config.json | 12 + examples/react/grid/index.html | 12 + examples/react/grid/package.json | 24 ++ examples/react/grid/src/index.css | 77 ++++++ examples/react/grid/src/main.tsx | 261 ++++++++++++++++++ examples/react/grid/tsconfig.json | 25 ++ examples/react/grid/vite.config.js | 7 + examples/react/horizontal-list/index.html | 12 + examples/react/horizontal-list/package.json | 24 ++ examples/react/horizontal-list/src/index.css | 77 ++++++ examples/react/horizontal-list/src/main.tsx | 207 ++++++++++++++ examples/react/horizontal-list/tsconfig.json | 25 ++ examples/react/horizontal-list/vite.config.js | 7 + examples/react/list/index.html | 12 + examples/react/list/package.json | 24 ++ examples/react/list/src/index.css | 77 ++++++ examples/react/list/src/main.tsx | 202 ++++++++++++++ examples/react/list/tsconfig.json | 25 ++ examples/react/list/vite.config.js | 7 + 19 files changed, 1117 insertions(+) create mode 100644 examples/react/grid/index.html create mode 100644 examples/react/grid/package.json create mode 100644 examples/react/grid/src/index.css create mode 100644 examples/react/grid/src/main.tsx create mode 100644 examples/react/grid/tsconfig.json create mode 100644 examples/react/grid/vite.config.js create mode 100644 examples/react/horizontal-list/index.html create mode 100644 examples/react/horizontal-list/package.json create mode 100644 examples/react/horizontal-list/src/index.css create mode 100644 examples/react/horizontal-list/src/main.tsx create mode 100644 examples/react/horizontal-list/tsconfig.json create mode 100644 examples/react/horizontal-list/vite.config.js create mode 100644 examples/react/list/index.html create mode 100644 examples/react/list/package.json create mode 100644 examples/react/list/src/index.css create mode 100644 examples/react/list/src/main.tsx create mode 100644 examples/react/list/tsconfig.json create mode 100644 examples/react/list/vite.config.js diff --git a/docs/config.json b/docs/config.json index e65ba6ad2..d9ef673fc 100644 --- a/docs/config.json +++ b/docs/config.json @@ -112,6 +112,18 @@ { "label": "react", "children": [ + { + "to": "framework/react/examples/list", + "label": "List" + }, + { + "to": "framework/react/examples/horizontal-list", + "label": "Horizontal List" + }, + { + "to": "framework/react/examples/grid", + "label": "Grid" + }, { "to": "framework/react/examples/fixed", "label": "Fixed" diff --git a/examples/react/grid/index.html b/examples/react/grid/index.html new file mode 100644 index 000000000..e57b08cf9 --- /dev/null +++ b/examples/react/grid/index.html @@ -0,0 +1,12 @@ + + + + + + Grid Virtualization Example + + +
+ + + diff --git a/examples/react/grid/package.json b/examples/react/grid/package.json new file mode 100644 index 000000000..b291c7a63 --- /dev/null +++ b/examples/react/grid/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-react-virtual-example-grid", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "serve": "vite preview" + }, + "dependencies": { + "@faker-js/faker": "^8.4.1", + "@tanstack/react-virtual": "^3.13.13", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/node": "^24.5.2", + "@types/react": "^18.3.23", + "@types/react-dom": "^18.3.7", + "@vitejs/plugin-react": "^4.5.2", + "typescript": "5.4.5", + "vite": "^5.4.19" + } +} diff --git a/examples/react/grid/src/index.css b/examples/react/grid/src/index.css new file mode 100644 index 000000000..96e655143 --- /dev/null +++ b/examples/react/grid/src/index.css @@ -0,0 +1,77 @@ +*, +*:before, +*:after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + font-size: 14px; +} + +body { + padding: 1rem; +} + +.List { + border: 1px solid #e6e4dc; + max-width: 100%; +} + +.ListItemEven, +.ListItemOdd { + display: flex; + align-items: center; + justify-content: center; +} + +.ListItemEven { + background-color: #e6e4dc; +} + +.controls { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; + flex-wrap: wrap; + align-items: center; +} + +.controls label { + display: flex; + align-items: center; + gap: 0.25rem; + cursor: pointer; +} + +.mode-selector { + display: flex; + gap: 0.5rem; + padding: 0.5rem; + background: #f5f5f5; + border-radius: 4px; +} + +.mode-selector label { + padding: 0.25rem 0.5rem; + border-radius: 4px; +} + +.mode-selector input:checked + span { + background: #007bff; + color: white; + padding: 0.25rem 0.5rem; + border-radius: 4px; + margin: -0.25rem -0.5rem; +} + +button { + border: 1px solid gray; + padding: 0.25rem 0.5rem; + background: white; + cursor: pointer; +} + +button:hover { + background: #f0f0f0; +} diff --git a/examples/react/grid/src/main.tsx b/examples/react/grid/src/main.tsx new file mode 100644 index 000000000..f5c28cdd2 --- /dev/null +++ b/examples/react/grid/src/main.tsx @@ -0,0 +1,261 @@ +import * as React from 'react' +import { createRoot } from 'react-dom/client' +import { faker } from '@faker-js/faker' +import { useVirtualizer } from '@tanstack/react-virtual' + +import './index.css' + +type SizingMode = 'dynamic' | 'fixed' | 'variable' + +const randomNumber = (min: number, max: number) => + faker.number.int({ min, max }) + +const rowCount = 10000 +const columnCount = 10000 + +// Generate cell content for dynamic mode +const generateCellContent = (row: number, col: number) => { + // Use a deterministic seed based on position + faker.seed(row * columnCount + col) + return faker.lorem.words(randomNumber(1, 4)) +} + +// Pre-computed variable sizes for "variable" mode +const variableRowHeights = new Array(rowCount) + .fill(true) + .map(() => 25 + Math.round(Math.random() * 75)) + +const variableColumnWidths = new Array(columnCount) + .fill(true) + .map(() => 75 + Math.round(Math.random() * 125)) + +function Grid() { + const parentRef = React.useRef(null) + const [sizingMode, setSizingMode] = React.useState('dynamic') + + // Row virtualizer + const rowVirtualizer = useVirtualizer({ + count: rowCount, + getScrollElement: () => parentRef.current, + estimateSize: React.useCallback( + (index: number) => { + switch (sizingMode) { + case 'fixed': + return 35 + case 'variable': + return variableRowHeights[index] + case 'dynamic': + default: + return 50 + } + }, + [sizingMode], + ), + overscan: 5, + }) + + // Column virtualizer + const columnVirtualizer = useVirtualizer({ + horizontal: true, + count: columnCount, + getScrollElement: () => parentRef.current, + estimateSize: React.useCallback( + (index: number) => { + switch (sizingMode) { + case 'fixed': + return 100 + case 'variable': + return variableColumnWidths[index] + case 'dynamic': + default: + return 120 + } + }, + [sizingMode], + ), + overscan: 5, + }) + + const virtualRows = rowVirtualizer.getVirtualItems() + const virtualColumns = columnVirtualizer.getVirtualItems() + + return ( +
+
+
+ Sizing Mode: + {(['dynamic', 'fixed', 'variable'] as const).map((mode) => ( + + ))} +
+
+ +
+ + + +
+ +

+ {sizingMode === 'dynamic' && ( + <> + Dynamic mode: Cell sizes are estimated and can vary + based on content. Best for unknown or variable content. + + )} + {sizingMode === 'fixed' && ( + <> + Fixed mode: All cells have the same dimensions + (35px height, 100px width). Best performance for uniform grids. + + )} + {sizingMode === 'variable' && ( + <> + Variable mode: Each row/column has pre-computed + dimensions. Use when sizes are known but vary per row/column. + + )} +

+ +
+
+ {virtualRows.map((virtualRow) => ( + + {virtualColumns.map((virtualColumn) => { + const isEven = + (virtualRow.index + virtualColumn.index) % 2 === 0 + return ( +
+ {sizingMode === 'dynamic' ? ( +
+
+ {virtualRow.index},{virtualColumn.index} +
+
+ {generateCellContent( + virtualRow.index, + virtualColumn.index, + )} +
+
+ ) : ( + `${virtualRow.index}, ${virtualColumn.index}` + )} +
+ ) + })} +
+ ))} +
+
+ +

+ Rendering {virtualRows.length * virtualColumns.length} of{' '} + {(rowCount * columnCount).toLocaleString()} cells ( + {virtualRows.length} rows x {virtualColumns.length} columns) +

+
+ ) +} + +function App() { + return ( +
+

Grid Virtualization

+

+ Efficiently render large 2D grids (spreadsheets, data tables, game + boards) by only rendering visible cells. Both rows and columns are + virtualized simultaneously. +

+ + {process.env.NODE_ENV === 'development' && ( +

+ Note: Running in development mode. Performance will + improve in production builds. +

+ )} +
+ ) +} + +const container = document.getElementById('root')! +const root = createRoot(container) + +root.render( + + + , +) diff --git a/examples/react/grid/tsconfig.json b/examples/react/grid/tsconfig.json new file mode 100644 index 000000000..87318025a --- /dev/null +++ b/examples/react/grid/tsconfig.json @@ -0,0 +1,25 @@ +{ + "composite": true, + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/examples/react/grid/vite.config.js b/examples/react/grid/vite.config.js new file mode 100644 index 000000000..5a33944a9 --- /dev/null +++ b/examples/react/grid/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/examples/react/horizontal-list/index.html b/examples/react/horizontal-list/index.html new file mode 100644 index 000000000..27b5ad9ee --- /dev/null +++ b/examples/react/horizontal-list/index.html @@ -0,0 +1,12 @@ + + + + + + Horizontal List Virtualization Example + + +
+ + + diff --git a/examples/react/horizontal-list/package.json b/examples/react/horizontal-list/package.json new file mode 100644 index 000000000..be440454e --- /dev/null +++ b/examples/react/horizontal-list/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-react-virtual-example-horizontal-list", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "serve": "vite preview" + }, + "dependencies": { + "@faker-js/faker": "^8.4.1", + "@tanstack/react-virtual": "^3.13.13", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/node": "^24.5.2", + "@types/react": "^18.3.23", + "@types/react-dom": "^18.3.7", + "@vitejs/plugin-react": "^4.5.2", + "typescript": "5.4.5", + "vite": "^5.4.19" + } +} diff --git a/examples/react/horizontal-list/src/index.css b/examples/react/horizontal-list/src/index.css new file mode 100644 index 000000000..96e655143 --- /dev/null +++ b/examples/react/horizontal-list/src/index.css @@ -0,0 +1,77 @@ +*, +*:before, +*:after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + font-size: 14px; +} + +body { + padding: 1rem; +} + +.List { + border: 1px solid #e6e4dc; + max-width: 100%; +} + +.ListItemEven, +.ListItemOdd { + display: flex; + align-items: center; + justify-content: center; +} + +.ListItemEven { + background-color: #e6e4dc; +} + +.controls { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; + flex-wrap: wrap; + align-items: center; +} + +.controls label { + display: flex; + align-items: center; + gap: 0.25rem; + cursor: pointer; +} + +.mode-selector { + display: flex; + gap: 0.5rem; + padding: 0.5rem; + background: #f5f5f5; + border-radius: 4px; +} + +.mode-selector label { + padding: 0.25rem 0.5rem; + border-radius: 4px; +} + +.mode-selector input:checked + span { + background: #007bff; + color: white; + padding: 0.25rem 0.5rem; + border-radius: 4px; + margin: -0.25rem -0.5rem; +} + +button { + border: 1px solid gray; + padding: 0.25rem 0.5rem; + background: white; + cursor: pointer; +} + +button:hover { + background: #f0f0f0; +} diff --git a/examples/react/horizontal-list/src/main.tsx b/examples/react/horizontal-list/src/main.tsx new file mode 100644 index 000000000..1fcc94609 --- /dev/null +++ b/examples/react/horizontal-list/src/main.tsx @@ -0,0 +1,207 @@ +import * as React from 'react' +import { createRoot } from 'react-dom/client' +import { faker } from '@faker-js/faker' +import { useVirtualizer } from '@tanstack/react-virtual' + +import './index.css' + +type SizingMode = 'dynamic' | 'fixed' | 'variable' + +const randomNumber = (min: number, max: number) => + faker.number.int({ min, max }) + +// Generate data for the horizontal list +const items = new Array(10000) + .fill(true) + .map(() => faker.lorem.words(randomNumber(2, 8))) + +// Pre-computed variable widths for "variable" mode +const variableWidths = new Array(10000) + .fill(true) + .map(() => 75 + Math.round(Math.random() * 150)) + +function HorizontalList() { + const parentRef = React.useRef(null) + const [sizingMode, setSizingMode] = React.useState('dynamic') + + const count = items.length + + // Configure virtualizer based on sizing mode + const virtualizer = useVirtualizer({ + horizontal: true, + count, + getScrollElement: () => parentRef.current, + estimateSize: React.useCallback( + (index: number) => { + switch (sizingMode) { + case 'fixed': + return 100 + case 'variable': + return variableWidths[index] + case 'dynamic': + default: + return 120 + } + }, + [sizingMode], + ), + overscan: 5, + }) + + const virtualItems = virtualizer.getVirtualItems() + + // For dynamic mode, we need to measure elements + const measureElement = sizingMode === 'dynamic' ? virtualizer.measureElement : undefined + + return ( +
+
+
+ Sizing Mode: + {(['dynamic', 'fixed', 'variable'] as const).map((mode) => ( + + ))} +
+
+ +
+ + + +
+ +

+ {sizingMode === 'dynamic' && ( + <> + Dynamic mode: Each item's width is measured at render time. + Content width varies and the virtualizer adapts automatically. + + )} + {sizingMode === 'fixed' && ( + <> + Fixed mode: All items have the same fixed width (100px). + Best performance, use when all items are identical width. + + )} + {sizingMode === 'variable' && ( + <> + Variable mode: Each item has a known but different width. + Widths are pre-computed, not measured at runtime. + + )} +

+ +
+
+ {virtualItems.map((virtualColumn) => ( +
+ {sizingMode === 'dynamic' ? ( +
+
Item {virtualColumn.index}
+
{items[virtualColumn.index]}
+
+ ) : ( + `Column ${virtualColumn.index}` + )} +
+ ))} +
+
+ +

+ Rendering {virtualItems.length} of {count.toLocaleString()} items +

+
+ ) +} + +function App() { + return ( +
+

Horizontal List Virtualization

+

+ Efficiently render large horizontal lists (carousels, timelines, etc.) + by only rendering visible items. Try different sizing modes to see how + they affect behavior. +

+ + {process.env.NODE_ENV === 'development' && ( +

+ Note: Running in development mode. Performance will + improve in production builds. +

+ )} +
+ ) +} + +const container = document.getElementById('root')! +const root = createRoot(container) + +root.render( + + + , +) diff --git a/examples/react/horizontal-list/tsconfig.json b/examples/react/horizontal-list/tsconfig.json new file mode 100644 index 000000000..87318025a --- /dev/null +++ b/examples/react/horizontal-list/tsconfig.json @@ -0,0 +1,25 @@ +{ + "composite": true, + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/examples/react/horizontal-list/vite.config.js b/examples/react/horizontal-list/vite.config.js new file mode 100644 index 000000000..5a33944a9 --- /dev/null +++ b/examples/react/horizontal-list/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/examples/react/list/index.html b/examples/react/list/index.html new file mode 100644 index 000000000..ad789c923 --- /dev/null +++ b/examples/react/list/index.html @@ -0,0 +1,12 @@ + + + + + + List Virtualization Example + + +
+ + + diff --git a/examples/react/list/package.json b/examples/react/list/package.json new file mode 100644 index 000000000..4d5d7bacc --- /dev/null +++ b/examples/react/list/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-react-virtual-example-list", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "serve": "vite preview" + }, + "dependencies": { + "@faker-js/faker": "^8.4.1", + "@tanstack/react-virtual": "^3.13.13", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/node": "^24.5.2", + "@types/react": "^18.3.23", + "@types/react-dom": "^18.3.7", + "@vitejs/plugin-react": "^4.5.2", + "typescript": "5.4.5", + "vite": "^5.4.19" + } +} diff --git a/examples/react/list/src/index.css b/examples/react/list/src/index.css new file mode 100644 index 000000000..96e655143 --- /dev/null +++ b/examples/react/list/src/index.css @@ -0,0 +1,77 @@ +*, +*:before, +*:after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + font-size: 14px; +} + +body { + padding: 1rem; +} + +.List { + border: 1px solid #e6e4dc; + max-width: 100%; +} + +.ListItemEven, +.ListItemOdd { + display: flex; + align-items: center; + justify-content: center; +} + +.ListItemEven { + background-color: #e6e4dc; +} + +.controls { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; + flex-wrap: wrap; + align-items: center; +} + +.controls label { + display: flex; + align-items: center; + gap: 0.25rem; + cursor: pointer; +} + +.mode-selector { + display: flex; + gap: 0.5rem; + padding: 0.5rem; + background: #f5f5f5; + border-radius: 4px; +} + +.mode-selector label { + padding: 0.25rem 0.5rem; + border-radius: 4px; +} + +.mode-selector input:checked + span { + background: #007bff; + color: white; + padding: 0.25rem 0.5rem; + border-radius: 4px; + margin: -0.25rem -0.5rem; +} + +button { + border: 1px solid gray; + padding: 0.25rem 0.5rem; + background: white; + cursor: pointer; +} + +button:hover { + background: #f0f0f0; +} diff --git a/examples/react/list/src/main.tsx b/examples/react/list/src/main.tsx new file mode 100644 index 000000000..44e80101d --- /dev/null +++ b/examples/react/list/src/main.tsx @@ -0,0 +1,202 @@ +import * as React from 'react' +import { createRoot } from 'react-dom/client' +import { faker } from '@faker-js/faker' +import { useVirtualizer } from '@tanstack/react-virtual' + +import './index.css' + +type SizingMode = 'dynamic' | 'fixed' | 'variable' + +const randomNumber = (min: number, max: number) => + faker.number.int({ min, max }) + +// Generate data for the list +const sentences = new Array(10000) + .fill(true) + .map(() => faker.lorem.sentence(randomNumber(20, 70))) + +// Pre-computed variable sizes for "variable" mode +const variableSizes = new Array(10000) + .fill(true) + .map(() => 25 + Math.round(Math.random() * 100)) + +function List() { + const parentRef = React.useRef(null) + const [sizingMode, setSizingMode] = React.useState('dynamic') + + const count = sentences.length + + // Configure virtualizer based on sizing mode + const virtualizer = useVirtualizer({ + count, + getScrollElement: () => parentRef.current, + estimateSize: React.useCallback( + (index: number) => { + switch (sizingMode) { + case 'fixed': + return 35 + case 'variable': + return variableSizes[index] + case 'dynamic': + default: + return 45 + } + }, + [sizingMode], + ), + overscan: 5, + }) + + const items = virtualizer.getVirtualItems() + + // For dynamic mode, we need to measure elements + const measureElement = sizingMode === 'dynamic' ? virtualizer.measureElement : undefined + + return ( +
+
+
+ Sizing Mode: + {(['dynamic', 'fixed', 'variable'] as const).map((mode) => ( + + ))} +
+
+ +
+ + + +
+ +

+ {sizingMode === 'dynamic' && ( + <> + Dynamic mode: Each item's height is measured at render time. + Content can vary and the virtualizer adapts automatically. + + )} + {sizingMode === 'fixed' && ( + <> + Fixed mode: All items have the same fixed height (35px). + Best performance, use when all items are identical height. + + )} + {sizingMode === 'variable' && ( + <> + Variable mode: Each item has a known but different height. + Heights are pre-computed, not measured at runtime. + + )} +

+ +
+
+
+ {items.map((virtualRow) => ( +
+ {sizingMode === 'dynamic' ? ( +
+
Row {virtualRow.index}
+
{sentences[virtualRow.index]}
+
+ ) : ( +
Row {virtualRow.index}
+ )} +
+ ))} +
+
+
+ +

+ Rendering {items.length} of {count.toLocaleString()} items +

+
+ ) +} + +function App() { + return ( +
+

List Virtualization

+

+ Efficiently render large vertical lists by only rendering visible items. + Try different sizing modes to see how they affect behavior. +

+ + {process.env.NODE_ENV === 'development' && ( +

+ Note: Running in development mode. Performance will + improve in production builds. +

+ )} +
+ ) +} + +const container = document.getElementById('root')! +const root = createRoot(container) + +root.render( + + + , +) diff --git a/examples/react/list/tsconfig.json b/examples/react/list/tsconfig.json new file mode 100644 index 000000000..87318025a --- /dev/null +++ b/examples/react/list/tsconfig.json @@ -0,0 +1,25 @@ +{ + "composite": true, + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/examples/react/list/vite.config.js b/examples/react/list/vite.config.js new file mode 100644 index 000000000..5a33944a9 --- /dev/null +++ b/examples/react/list/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +})