From 581f6219140cd568a8348b47a117f1fda0e4edce Mon Sep 17 00:00:00 2001 From: Kevin Van Cott Date: Sun, 17 Nov 2024 19:30:46 -0600 Subject: [PATCH] fix some svelte and solid examples --- examples/solid/column-groups/src/App.tsx | 2 +- examples/solid/column-ordering/src/App.tsx | 6 +- examples/solid/filters-faceted/.gitignore | 2 + examples/solid/filters-faceted/README.md | 6 + examples/solid/filters-faceted/index.html | 16 ++ examples/solid/filters-faceted/package.json | 24 +++ examples/solid/filters-faceted/src/App.tsx | 184 ++++++++++++++++++ .../filters-faceted/src/ColumnFilter.tsx | 97 +++++++++ examples/solid/filters-faceted/src/index.css | 26 +++ examples/solid/filters-faceted/src/index.tsx | 6 + .../solid/filters-faceted/src/makeData.ts | 48 +++++ examples/solid/filters-faceted/tsconfig.json | 25 +++ examples/solid/filters-faceted/vite.config.ts | 10 + examples/solid/filters/src/App.tsx | 13 +- examples/solid/filters/src/ColumnFilter.tsx | 61 +++--- examples/solid/sorting/src/App.tsx | 2 +- examples/svelte/sorting/src/App.svelte | 7 +- examples/svelte/sorting/src/Header.svelte | 7 +- .../svelte/sorting/src/tableHelper.svelte.ts | 5 + .../columnFilteringFeature.utils.ts | 17 +- .../createFilteredRowModel.ts | 9 - 21 files changed, 507 insertions(+), 66 deletions(-) create mode 100644 examples/solid/filters-faceted/.gitignore create mode 100644 examples/solid/filters-faceted/README.md create mode 100644 examples/solid/filters-faceted/index.html create mode 100644 examples/solid/filters-faceted/package.json create mode 100644 examples/solid/filters-faceted/src/App.tsx create mode 100644 examples/solid/filters-faceted/src/ColumnFilter.tsx create mode 100644 examples/solid/filters-faceted/src/index.css create mode 100644 examples/solid/filters-faceted/src/index.tsx create mode 100644 examples/solid/filters-faceted/src/makeData.ts create mode 100644 examples/solid/filters-faceted/tsconfig.json create mode 100644 examples/solid/filters-faceted/vite.config.ts create mode 100644 examples/svelte/sorting/src/tableHelper.svelte.ts diff --git a/examples/solid/column-groups/src/App.tsx b/examples/solid/column-groups/src/App.tsx index 818304d487..5a4662411c 100644 --- a/examples/solid/column-groups/src/App.tsx +++ b/examples/solid/column-groups/src/App.tsx @@ -131,7 +131,7 @@ function App() { {(row) => ( - + {(cell) => ( {flexRender( diff --git a/examples/solid/column-ordering/src/App.tsx b/examples/solid/column-ordering/src/App.tsx index a49ba5d488..3fcde96f87 100644 --- a/examples/solid/column-ordering/src/App.tsx +++ b/examples/solid/column-ordering/src/App.tsx @@ -2,6 +2,7 @@ import { For, Show, createSignal } from 'solid-js' import { faker } from '@faker-js/faker' import { columnOrderingFeature, + columnVisibilityFeature, createTable, flexRender, tableFeatures, @@ -14,7 +15,10 @@ import type { ColumnVisibilityState, } from '@tanstack/solid-table' -const _features = tableFeatures({ columnOrderingFeature }) +const _features = tableFeatures({ + columnOrderingFeature, + columnVisibilityFeature, +}) const defaultColumns: Array> = [ { diff --git a/examples/solid/filters-faceted/.gitignore b/examples/solid/filters-faceted/.gitignore new file mode 100644 index 0000000000..76add878f8 --- /dev/null +++ b/examples/solid/filters-faceted/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/examples/solid/filters-faceted/README.md b/examples/solid/filters-faceted/README.md new file mode 100644 index 0000000000..b168d3c4b1 --- /dev/null +++ b/examples/solid/filters-faceted/README.md @@ -0,0 +1,6 @@ +# Example + +To run this example: + +- `npm install` or `yarn` +- `npm run start` or `yarn start` diff --git a/examples/solid/filters-faceted/index.html b/examples/solid/filters-faceted/index.html new file mode 100644 index 0000000000..7d9b4f7c51 --- /dev/null +++ b/examples/solid/filters-faceted/index.html @@ -0,0 +1,16 @@ + + + + + + + + Solid App + + + +
+ + + + diff --git a/examples/solid/filters-faceted/package.json b/examples/solid/filters-faceted/package.json new file mode 100644 index 0000000000..4b40b8f1d7 --- /dev/null +++ b/examples/solid/filters-faceted/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-solid-filters-faceted", + "version": "0.0.0", + "description": "", + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "lint": "eslint ./src" + }, + "license": "MIT", + "devDependencies": { + "@faker-js/faker": "^9.2.0", + "typescript": "5.6.3", + "vite": "^5.4.11", + "vite-plugin-solid": "^2.10.2" + }, + "dependencies": { + "@solid-primitives/scheduled": "^1.4.4", + "@tanstack/solid-table": "^9.0.0-alpha.10", + "solid-js": "^1.9.3" + } +} diff --git a/examples/solid/filters-faceted/src/App.tsx b/examples/solid/filters-faceted/src/App.tsx new file mode 100644 index 0000000000..b6ca0f6ead --- /dev/null +++ b/examples/solid/filters-faceted/src/App.tsx @@ -0,0 +1,184 @@ +import { + columnFacetingFeature, + columnFilteringFeature, + createFacetedMinMaxValues, + createFacetedRowModel, + createFacetedUniqueValues, + createFilteredRowModel, + createTable, + flexRender, + globalFilteringFeature, + tableFeatures, +} from '@tanstack/solid-table' +import { debounce } from '@solid-primitives/scheduled' +import { For, createSignal } from 'solid-js' +import { makeData } from './makeData' +import ColumnFilter from './ColumnFilter' +import type { Person } from './makeData' +import type { ColumnDef, ColumnFiltersState } from '@tanstack/solid-table' + +const _features = tableFeatures({ + columnFilteringFeature, + globalFilteringFeature, + columnFacetingFeature, +}) + +const columns: Array> = [ + { + header: 'Name', + footer: (props) => props.column.id, + columns: [ + { + accessorKey: 'firstName', + cell: (info) => info.getValue(), + footer: (props) => props.column.id, + }, + { + accessorFn: (row) => row.lastName, + id: 'lastName', + cell: (info) => info.getValue(), + header: () => Last Name, + footer: (props) => props.column.id, + }, + ], + }, + { + header: 'Info', + footer: (props) => props.column.id, + columns: [ + { + accessorKey: 'age', + header: () => 'Age', + footer: (props) => props.column.id, + }, + { + header: 'More Info', + columns: [ + { + accessorKey: 'visits', + header: () => Visits, + footer: (props) => props.column.id, + }, + { + accessorKey: 'status', + header: 'Status', + footer: (props) => props.column.id, + }, + { + accessorKey: 'progress', + header: 'Profile Progress', + footer: (props) => props.column.id, + }, + ], + }, + ], + }, +] + +function App() { + const [data, setData] = createSignal(makeData(1_000)) + const [columnFilters, setColumnFilters] = createSignal([]) + const [globalFilter, setGlobalFilter] = createSignal('') + const debounceSetGlobalFilter = debounce( + (value: string) => setGlobalFilter(value), + 500, + ) + const refreshData = () => setData(makeData(50_000)) // stress test + + const table = createTable({ + _features, + _rowModels: { + facetedRowModel: createFacetedRowModel(), + facetedMinMaxValues: createFacetedMinMaxValues(), + facetedUniqueValues: createFacetedUniqueValues(), + filteredRowModel: createFilteredRowModel(), + }, + get data() { + return data() + }, + columns, + state: { + get columnFilters() { + return columnFilters() + }, + get globalFilter() { + return globalFilter() + }, + }, + onGlobalFilterChange: setGlobalFilter, + globalFilterFn: 'includesString', + onColumnFiltersChange: setColumnFilters, + debugTable: true, + debugHeaders: true, + debugColumns: false, + }) + + return ( +
+ debounceSetGlobalFilter(e.currentTarget.value)} + placeholder="Search all columns..." + /> +
+ + + + {(headerGroup) => ( + + + {(header) => ( + + )} + + + )} + + + + + {(row) => ( + + + {(cell) => ( + + )} + + + )} + + +
+ {header.isPlaceholder ? null : ( + <> + {flexRender( + header.column.columnDef.header, + header.getContext(), + )} + {header.column.getCanFilter() ? ( +
+ +
+ ) : null} + + )} +
+ {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} +
+
{table.getRowModel().rows.length} Rows
+
+ +
+
{JSON.stringify(table.getState(), null, 2)}
+
+ ) +} + +export default App diff --git a/examples/solid/filters-faceted/src/ColumnFilter.tsx b/examples/solid/filters-faceted/src/ColumnFilter.tsx new file mode 100644 index 0000000000..efb3bd7888 --- /dev/null +++ b/examples/solid/filters-faceted/src/ColumnFilter.tsx @@ -0,0 +1,97 @@ +import { debounce } from '@solid-primitives/scheduled' +import { For, Show, createMemo } from 'solid-js' +import type { Column, Table } from '@tanstack/solid-table' + +function ColumnFilter(props: { + column: Column + table: Table +}) { + const firstValue = props.table + .getPreFilteredRowModel() + .flatRows[0]?.getValue(props.column.id) + + const columnFilterValue = () => props.column.getFilterValue() + + const sortedUniqueValues = createMemo(() => + typeof firstValue === 'number' + ? [] + : Array.from(props.column.getFacetedUniqueValues().keys()).sort(), + ) + + return ( + + + + {(value: string) => + + props.column.setFilterValue(e.target.value), + 500, + )} + placeholder={`Search... (${props.column.getFacetedUniqueValues().size})`} + class="w-36 border shadow rounded" + list={`${props.column.id}list`} + /> +
+ } + > +
+
+ + props.column.setFilterValue((old: [number, number]) => [ + e.target.value, + old[1], + ]), + 500, + )} + placeholder={`Min ${ + props.column.getFacetedMinMaxValues()?.[0] + ? `(${props.column.getFacetedMinMaxValues()?.[0]})` + : '' + }`} + class="w-24 border shadow rounded" + /> + + props.column.setFilterValue((old: [number, number]) => [ + old[0], + e.target.value, + ]), + 500, + )} + placeholder={`Max ${ + props.column.getFacetedMinMaxValues()?.[1] + ? `(${props.column.getFacetedMinMaxValues()?.[1]})` + : '' + }`} + class="w-24 border shadow rounded" + /> +
+
+ + ) +} + +export default ColumnFilter diff --git a/examples/solid/filters-faceted/src/index.css b/examples/solid/filters-faceted/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/solid/filters-faceted/src/index.css @@ -0,0 +1,26 @@ +html { + font-family: sans-serif; + font-size: 14px; +} + +table { + border: 1px solid lightgray; +} + +tbody { + border-bottom: 1px solid lightgray; +} + +th { + border-bottom: 1px solid lightgray; + border-right: 1px solid lightgray; + padding: 2px 4px; +} + +tfoot { + color: gray; +} + +tfoot th { + font-weight: normal; +} diff --git a/examples/solid/filters-faceted/src/index.tsx b/examples/solid/filters-faceted/src/index.tsx new file mode 100644 index 0000000000..ea9c952177 --- /dev/null +++ b/examples/solid/filters-faceted/src/index.tsx @@ -0,0 +1,6 @@ +/* @refresh reload */ +import { render } from 'solid-js/web' +import './index.css' +import App from './App' + +render(() => , document.getElementById('root') as HTMLElement) diff --git a/examples/solid/filters-faceted/src/makeData.ts b/examples/solid/filters-faceted/src/makeData.ts new file mode 100644 index 0000000000..b9fb014aba --- /dev/null +++ b/examples/solid/filters-faceted/src/makeData.ts @@ -0,0 +1,48 @@ +import { faker } from '@faker-js/faker' + +export type Person = { + firstName: string + lastName: string + age: number + visits: number + progress: number + status: 'relationship' | 'complicated' | 'single' + subRows?: Array +} + +const range = (len: number) => { + const arr: Array = [] + for (let i = 0; i < len; i++) { + arr.push(i) + } + return arr +} + +const newPerson = (): Person => { + return { + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + age: faker.number.int(40), + visits: faker.number.int(1000), + progress: faker.number.int(100), + status: faker.helpers.shuffle([ + 'relationship', + 'complicated', + 'single', + ])[0], + } +} + +export function makeData(...lens: Array) { + const makeDataLevel = (depth = 0): Array => { + const len = lens[depth] + return range(len).map((d): Person => { + return { + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + } + }) + } + + return makeDataLevel() +} diff --git a/examples/solid/filters-faceted/tsconfig.json b/examples/solid/filters-faceted/tsconfig.json new file mode 100644 index 0000000000..7ab027b8d2 --- /dev/null +++ b/examples/solid/filters-faceted/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/examples/solid/filters-faceted/vite.config.ts b/examples/solid/filters-faceted/vite.config.ts new file mode 100644 index 0000000000..d27427972d --- /dev/null +++ b/examples/solid/filters-faceted/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite' +import solidPlugin from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solidPlugin()], + build: { + target: 'esnext', + polyfillDynamicImport: false, + }, +}) diff --git a/examples/solid/filters/src/App.tsx b/examples/solid/filters/src/App.tsx index b6ca0f6ead..08be7cff9c 100644 --- a/examples/solid/filters/src/App.tsx +++ b/examples/solid/filters/src/App.tsx @@ -1,11 +1,11 @@ import { - columnFacetingFeature, columnFilteringFeature, createFacetedMinMaxValues, createFacetedRowModel, createFacetedUniqueValues, createFilteredRowModel, createTable, + filterFns, flexRender, globalFilteringFeature, tableFeatures, @@ -17,10 +17,9 @@ import ColumnFilter from './ColumnFilter' import type { Person } from './makeData' import type { ColumnDef, ColumnFiltersState } from '@tanstack/solid-table' -const _features = tableFeatures({ +export const _features = tableFeatures({ columnFilteringFeature, globalFilteringFeature, - columnFacetingFeature, }) const columns: Array> = [ @@ -50,6 +49,7 @@ const columns: Array> = [ accessorKey: 'age', header: () => 'Age', footer: (props) => props.column.id, + filterFn: 'inNumberRange', }, { header: 'More Info', @@ -58,6 +58,7 @@ const columns: Array> = [ accessorKey: 'visits', header: () => Visits, footer: (props) => props.column.id, + filterFn: 'inNumberRange', }, { accessorKey: 'status', @@ -68,6 +69,7 @@ const columns: Array> = [ accessorKey: 'progress', header: 'Profile Progress', footer: (props) => props.column.id, + filterFn: 'inNumberRange', }, ], }, @@ -93,6 +95,9 @@ function App() { facetedUniqueValues: createFacetedUniqueValues(), filteredRowModel: createFilteredRowModel(), }, + _processingFns: { + filterFns, + }, get data() { return data() }, @@ -157,7 +162,7 @@ function App() { {(row) => ( - + {(cell) => ( {flexRender( diff --git a/examples/solid/filters/src/ColumnFilter.tsx b/examples/solid/filters/src/ColumnFilter.tsx index efb3bd7888..36c205fd7f 100644 --- a/examples/solid/filters/src/ColumnFilter.tsx +++ b/examples/solid/filters/src/ColumnFilter.tsx @@ -1,10 +1,12 @@ import { debounce } from '@solid-primitives/scheduled' -import { For, Show, createMemo } from 'solid-js' +import { Show } from 'solid-js' +import type { Person } from './makeData' +import type { _features } from './App' import type { Column, Table } from '@tanstack/solid-table' function ColumnFilter(props: { - column: Column - table: Table + column: Column + table: Table }) { const firstValue = props.table .getPreFilteredRowModel() @@ -12,22 +14,11 @@ function ColumnFilter(props: { const columnFilterValue = () => props.column.getFilterValue() - const sortedUniqueValues = createMemo(() => - typeof firstValue === 'number' - ? [] - : Array.from(props.column.getFacetedUniqueValues().keys()).sort(), - ) - return ( - - - {(value: string) => - props.column.setFilterValue(e.target.value), 500, )} - placeholder={`Search... (${props.column.getFacetedUniqueValues().size})`} + placeholder={`Search...`} class="w-36 border shadow rounded" list={`${props.column.id}list`} /> @@ -46,46 +37,42 @@ function ColumnFilter(props: {
- props.column.setFilterValue((old: [number, number]) => [ - e.target.value, - old[1], - ]), + props.column.setFilterValue( + (old: [number, number] | undefined) => [ + e.target.value, + old?.[1] ?? '', + ], + ), 500, )} - placeholder={`Min ${ - props.column.getFacetedMinMaxValues()?.[0] - ? `(${props.column.getFacetedMinMaxValues()?.[0]})` - : '' - }`} + placeholder={`Min`} class="w-24 border shadow rounded" /> - props.column.setFilterValue((old: [number, number]) => [ - old[0], - e.target.value, - ]), + props.column.setFilterValue( + (old: [number, number] | undefined) => [ + old?.[0] ?? '', + e.target.value, + ], + ), 500, )} - placeholder={`Max ${ - props.column.getFacetedMinMaxValues()?.[1] - ? `(${props.column.getFacetedMinMaxValues()?.[1]})` - : '' - }`} + placeholder={`Max`} class="w-24 border shadow rounded" />
diff --git a/examples/solid/sorting/src/App.tsx b/examples/solid/sorting/src/App.tsx index 3799066455..a966b69012 100644 --- a/examples/solid/sorting/src/App.tsx +++ b/examples/solid/sorting/src/App.tsx @@ -127,7 +127,7 @@ function App() { {(row) => ( - + {(cell) => ( {flexRender( diff --git a/examples/svelte/sorting/src/App.svelte b/examples/svelte/sorting/src/App.svelte index 93851f6991..99c21f9347 100644 --- a/examples/svelte/sorting/src/App.svelte +++ b/examples/svelte/sorting/src/App.svelte @@ -2,21 +2,16 @@ import type { ColumnDef, SortingState } from '@tanstack/svelte-table' import { FlexRender, - rowSortingFeature, createSortedRowModel, createTable, createTableState, renderComponent, sortingFns, - tableFeatures, } from '@tanstack/svelte-table' import Header from './Header.svelte' import './index.css' import { makeData, type Person } from './makeData' - - const _features = tableFeatures({ - rowSortingFeature, - }) + import { _features } from './tableHelper.svelte' const columns: ColumnDef[] = [ { diff --git a/examples/svelte/sorting/src/Header.svelte b/examples/svelte/sorting/src/Header.svelte index 65937b9b9f..cc8a019c36 100644 --- a/examples/svelte/sorting/src/Header.svelte +++ b/examples/svelte/sorting/src/Header.svelte @@ -1,14 +1,11 @@