From e108954ba8e52da9580e88a5040b15150061e1d4 Mon Sep 17 00:00:00 2001 From: Kevin Van Cott Date: Tue, 7 Apr 2026 11:26:38 -0500 Subject: [PATCH 1/3] feat: svelte-table v9 refactor --- docs/config.json | 62 +- .../{basic => basic-inject-table}/.gitignore | 0 .../{basic => basic-inject-table}/README.md | 0 .../angular.json | 0 .../package.json | 0 .../public/favicon.ico | Bin .../src/app/app.config.ts | 0 .../src/app/app.html | 0 .../src/app/app.routes.ts | 0 .../src/app/app.ts | 0 .../src/index.html | 0 .../{basic => basic-inject-table}/src/main.ts | 0 .../src/styles.css | 0 .../tsconfig.app.json | 0 .../tsconfig.json | 0 .../solid/basic-external-state/src/App.tsx | 12 +- .../solid/basic-external-store/src/App.tsx | 12 +- examples/solid/basic-use-table/src/App.tsx | 25 +- examples/solid/column-groups/src/App.tsx | 25 +- examples/solid/column-ordering/src/App.tsx | 17 +- examples/solid/column-visibility/src/App.tsx | 17 +- examples/solid/filters-faceted/src/App.tsx | 12 +- examples/solid/filters/src/App.tsx | 12 +- examples/solid/row-selection/src/App.tsx | 12 +- examples/solid/sorting/src/App.tsx | 12 +- .../solid/with-tanstack-query/src/App.tsx | 16 +- .../.gitignore | 0 .../README.md | 0 .../index.html | 0 .../package.json | 2 +- .../svelte/basic-app-table/src/App.svelte | 180 ++++ .../src/index.css | 0 .../src/main.ts | 0 .../svelte.config.js | 0 .../tsconfig.json | 0 .../vite.config.js | 0 .../{basic => basic-create-table}/.gitignore | 0 .../{basic => basic-create-table}/README.md | 0 .../{basic => basic-create-table}/index.html | 0 .../svelte/basic-create-table/package.json | 23 + .../svelte/basic-create-table/src/App.svelte | 150 +++ .../src/index.css | 0 .../{basic => basic-create-table}/src/main.ts | 0 .../svelte.config.js | 0 .../tsconfig.json | 0 .../vite.config.js | 0 .../svelte/basic-external-state/index.html | 14 + .../svelte/basic-external-state/package.json | 24 + .../basic-external-state/src/App.svelte | 197 ++++ .../svelte/basic-external-state/src/index.css | 26 + .../svelte/basic-external-state/src/main.ts | 9 + .../basic-external-state/src/makeData.ts | 48 + .../src/vite-env.d.ts | 0 .../basic-external-state/svelte.config.js | 5 + .../svelte/basic-external-state/tsconfig.json | 13 + .../basic-external-state/vite.config.js | 17 + .../svelte/basic-external-store/index.html | 14 + .../svelte/basic-external-store/package.json | 24 + .../basic-external-store/src/App.svelte | 211 +++++ .../svelte/basic-external-store/src/index.css | 26 + .../svelte/basic-external-store/src/main.ts | 9 + .../basic-external-store/src/makeData.ts | 48 + .../basic-external-store/src/vite-env.d.ts | 2 + .../basic-external-store/svelte.config.js | 5 + .../svelte/basic-external-store/tsconfig.json | 13 + .../basic-external-store/vite.config.js | 17 + examples/svelte/basic-snippets/src/App.svelte | 35 +- .../svelte/basic-snippets/src/snippets.svelte | 2 - .../svelte/basic-table-helper/src/App.svelte | 159 ---- examples/svelte/basic/src/App.svelte | 166 ---- examples/svelte/column-groups/src/App.svelte | 27 +- .../svelte/column-ordering/src/App.svelte | 18 +- .../svelte/column-pinning-split/.gitignore | 8 + .../svelte/column-pinning-split/index.html | 14 + .../svelte/column-pinning-split/package.json | 24 + .../column-pinning-split/src/App.svelte | 313 ++++++ .../svelte/column-pinning-split/src/index.css | 26 + .../svelte/column-pinning-split/src/main.ts | 9 + .../column-pinning-split/src/makeData.ts | 47 + .../column-pinning-split/svelte.config.js | 5 + .../svelte/column-pinning-split/tsconfig.json | 13 + .../column-pinning-split/vite.config.js | 17 + .../svelte/column-pinning-sticky/.gitignore | 8 + .../svelte/column-pinning-sticky/index.html | 14 + .../svelte/column-pinning-sticky/package.json | 24 + .../column-pinning-sticky/src/App.svelte | 246 +++++ .../column-pinning-sticky/src/index.css | 49 + .../svelte/column-pinning-sticky/src/main.ts | 9 + .../column-pinning-sticky/src/makeData.ts | 47 + .../column-pinning-sticky/svelte.config.js | 5 + .../column-pinning-sticky/tsconfig.json | 13 + .../column-pinning-sticky/vite.config.js | 17 + examples/svelte/column-pinning/src/App.svelte | 44 +- .../column-resizing-performant/.gitignore | 8 + .../column-resizing-performant/index.html | 14 + .../column-resizing-performant/package.json | 24 + .../column-resizing-performant/src/App.svelte | 163 ++++ .../column-resizing-performant/src/index.css | 72 ++ .../column-resizing-performant/src/main.ts | 9 + .../src/makeData.ts | 43 + .../svelte.config.js | 5 + .../column-resizing-performant/tsconfig.json | 13 + .../column-resizing-performant/vite.config.js | 17 + examples/svelte/column-resizing/.gitignore | 8 + examples/svelte/column-resizing/index.html | 14 + examples/svelte/column-resizing/package.json | 23 + .../svelte/column-resizing/src/App.svelte | 300 ++++++ examples/svelte/column-resizing/src/index.css | 80 ++ examples/svelte/column-resizing/src/main.ts | 9 + .../svelte/column-resizing/svelte.config.js | 5 + examples/svelte/column-resizing/tsconfig.json | 13 + .../svelte/column-resizing/vite.config.js | 17 + examples/svelte/column-sizing/.gitignore | 8 + examples/svelte/column-sizing/index.html | 14 + .../{basic => column-sizing}/package.json | 2 +- examples/svelte/column-sizing/src/App.svelte | 232 +++++ examples/svelte/column-sizing/src/index.css | 57 ++ examples/svelte/column-sizing/src/main.ts | 9 + .../svelte/column-sizing/svelte.config.js | 5 + examples/svelte/column-sizing/tsconfig.json | 13 + examples/svelte/column-sizing/vite.config.js | 17 + .../svelte/column-visibility/src/App.svelte | 27 +- examples/svelte/composable-tables/.gitignore | 8 + examples/svelte/composable-tables/index.html | 13 + .../svelte/composable-tables/package.json | 24 + .../svelte/composable-tables/src/App.svelte | 22 + .../src/components/CategoryCell.svelte | 11 + .../src/components/ColumnFilter.svelte | 22 + .../src/components/FooterColumnId.svelte | 11 + .../src/components/FooterSum.svelte | 19 + .../src/components/NumberCell.svelte | 11 + .../src/components/PaginationControls.svelte | 65 ++ .../src/components/PriceCell.svelte | 16 + .../src/components/ProductsTable.svelte | 162 ++++ .../src/components/ProgressCell.svelte | 13 + .../src/components/RowActionsCell.svelte | 30 + .../src/components/RowCount.svelte | 13 + .../src/components/SortIndicator.svelte | 15 + .../src/components/StatusCell.svelte | 11 + .../src/components/TableToolbar.svelte | 31 + .../src/components/TextCell.svelte | 11 + .../src/components/UsersTable.svelte | 176 ++++ .../composable-tables/src/hooks/table.ts | 99 ++ .../svelte/composable-tables/src/index.css | 249 +++++ examples/svelte/composable-tables/src/main.ts | 9 + .../svelte/composable-tables/src/makeData.ts | 77 ++ .../svelte/composable-tables/svelte.config.js | 5 + .../svelte/composable-tables/tsconfig.json | 13 + .../svelte/composable-tables/vite.config.js | 17 + examples/svelte/expanding/.gitignore | 8 + examples/svelte/expanding/index.html | 14 + examples/svelte/expanding/package.json | 24 + examples/svelte/expanding/src/App.svelte | 296 ++++++ examples/svelte/expanding/src/index.css | 21 + examples/svelte/expanding/src/main.ts | 9 + examples/svelte/expanding/src/makeData.ts | 43 + examples/svelte/expanding/svelte.config.js | 5 + examples/svelte/expanding/tsconfig.json | 13 + examples/svelte/expanding/vite.config.js | 17 + examples/svelte/filtering/package.json | 1 - examples/svelte/filtering/src/App.svelte | 210 +++-- .../svelte/filtering/src/ColumnFilter.svelte | 68 ++ .../filtering/src/DebouncedInput.svelte | 29 + examples/svelte/filtering/src/main.ts | 11 - examples/svelte/filters-faceted/.gitignore | 8 + examples/svelte/filters-faceted/README.md | 6 + examples/svelte/filters-faceted/index.html | 14 + examples/svelte/filters-faceted/package.json | 24 + .../svelte/filters-faceted/src/App.svelte | 155 +++ .../filters-faceted/src/ColumnFilter.svelte | 78 ++ .../filters-faceted/src/DebouncedInput.svelte | 29 + examples/svelte/filters-faceted/src/index.css | 26 + examples/svelte/filters-faceted/src/main.ts | 9 + .../svelte/filters-faceted/src/makeData.ts | 48 + .../svelte/filters-faceted/svelte.config.js | 5 + examples/svelte/filters-faceted/tsconfig.json | 13 + .../svelte/filters-faceted/vite.config.js | 17 + examples/svelte/filters-fuzzy/.gitignore | 8 + examples/svelte/filters-fuzzy/README.md | 6 + examples/svelte/filters-fuzzy/index.html | 14 + examples/svelte/filters-fuzzy/package.json | 25 + examples/svelte/filters-fuzzy/src/App.svelte | 255 +++++ .../filters-fuzzy/src/DebouncedInput.svelte | 29 + examples/svelte/filters-fuzzy/src/index.css | 26 + examples/svelte/filters-fuzzy/src/main.ts | 20 + examples/svelte/filters-fuzzy/src/makeData.ts | 45 + .../svelte/filters-fuzzy/svelte.config.js | 5 + examples/svelte/filters-fuzzy/tsconfig.json | 13 + examples/svelte/filters-fuzzy/vite.config.js | 17 + examples/svelte/grouping/.gitignore | 8 + examples/svelte/grouping/index.html | 14 + examples/svelte/grouping/package.json | 24 + examples/svelte/grouping/src/App.svelte | 236 +++++ examples/svelte/grouping/src/index.css | 26 + examples/svelte/grouping/src/main.ts | 9 + examples/svelte/grouping/src/makeData.ts | 47 + examples/svelte/grouping/svelte.config.js | 5 + examples/svelte/grouping/tsconfig.json | 13 + examples/svelte/grouping/vite.config.js | 17 + examples/svelte/pagination/.gitignore | 8 + examples/svelte/pagination/index.html | 14 + examples/svelte/pagination/package.json | 24 + examples/svelte/pagination/src/App.svelte | 264 ++++++ examples/svelte/pagination/src/index.css | 21 + examples/svelte/pagination/src/main.ts | 9 + examples/svelte/pagination/src/makeData.ts | 43 + examples/svelte/pagination/svelte.config.js | 5 + examples/svelte/pagination/tsconfig.json | 13 + examples/svelte/pagination/vite.config.js | 17 + examples/svelte/row-pinning/.gitignore | 8 + examples/svelte/row-pinning/index.html | 14 + examples/svelte/row-pinning/package.json | 24 + examples/svelte/row-pinning/src/App.svelte | 385 ++++++++ examples/svelte/row-pinning/src/index.css | 26 + examples/svelte/row-pinning/src/main.ts | 9 + examples/svelte/row-pinning/src/makeData.ts | 43 + examples/svelte/row-pinning/svelte.config.js | 5 + examples/svelte/row-pinning/tsconfig.json | 13 + examples/svelte/row-pinning/vite.config.js | 17 + examples/svelte/row-selection/src/App.svelte | 101 +- examples/svelte/row-selection/src/main.ts | 11 +- .../svelte/row-selection/src/vite-env.d.ts | 2 + examples/svelte/row-selection/tsconfig.json | 12 +- examples/svelte/sorting/src/App.svelte | 27 +- examples/svelte/sub-components/.gitignore | 8 + examples/svelte/sub-components/index.html | 14 + examples/svelte/sub-components/package.json | 24 + examples/svelte/sub-components/src/App.svelte | 143 +++ examples/svelte/sub-components/src/index.css | 21 + examples/svelte/sub-components/src/main.ts | 9 + .../svelte/sub-components/src/makeData.ts | 43 + .../svelte/sub-components/svelte.config.js | 5 + examples/svelte/sub-components/tsconfig.json | 13 + examples/svelte/sub-components/vite.config.js | 17 + .../svelte/virtualized-columns/index.html | 13 + .../svelte/virtualized-columns/package.json | 25 + .../svelte/virtualized-columns/src/App.svelte | 199 ++++ .../svelte/virtualized-columns/src/index.css | 40 + .../svelte/virtualized-columns/src/main.ts | 9 + .../virtualized-columns/src/makeData.ts | 17 + .../virtualized-columns/src/vite-env.d.ts | 2 + .../virtualized-columns/svelte.config.js | 5 + .../svelte/virtualized-columns/tsconfig.json | 13 + .../svelte/virtualized-columns/vite.config.js | 17 + .../virtualized-infinite-scrolling/index.html | 13 + .../package.json | 26 + .../src/App.svelte | 243 +++++ .../src/Root.svelte | 10 + .../src/index.css | 40 + .../src/main.ts | 9 + .../src/makeData.ts | 89 ++ .../src/vite-env.d.ts | 2 + .../svelte.config.js | 5 + .../tsconfig.json | 13 + .../vite.config.js | 17 + examples/svelte/virtualized-rows/index.html | 13 + examples/svelte/virtualized-rows/package.json | 25 + .../svelte/virtualized-rows/src/App.svelte | 182 ++++ .../svelte/virtualized-rows/src/index.css | 40 + examples/svelte/virtualized-rows/src/main.ts | 9 + .../svelte/virtualized-rows/src/makeData.ts | 41 + .../svelte/virtualized-rows/src/vite-env.d.ts | 2 + .../svelte/virtualized-rows/svelte.config.js | 5 + .../svelte/virtualized-rows/tsconfig.json | 13 + .../svelte/virtualized-rows/vite.config.js | 17 + examples/svelte/with-tanstack-form/.gitignore | 8 + examples/svelte/with-tanstack-form/index.html | 14 + .../svelte/with-tanstack-form/package.json | 29 + .../svelte/with-tanstack-form/src/App.svelte | 374 ++++++++ .../src/FormStateIndicator.svelte | 29 + .../with-tanstack-form/src/NumberField.svelte | 19 + .../src/NumberFieldCell.svelte | 29 + .../with-tanstack-form/src/SelectField.svelte | 24 + .../src/SelectFieldCell.svelte | 14 + .../src/SubmitButton.svelte | 24 + .../with-tanstack-form/src/TextField.svelte | 18 + .../src/TextFieldCell.svelte | 21 + .../with-tanstack-form/src/form-context.ts | 3 + .../svelte/with-tanstack-form/src/form.ts | 18 + .../svelte/with-tanstack-form/src/index.css | 26 + .../svelte/with-tanstack-form/src/main.ts | 9 + .../svelte/with-tanstack-form/src/makeData.ts | 48 + .../with-tanstack-form/svelte.config.js | 5 + .../svelte/with-tanstack-form/tsconfig.json | 13 + .../svelte/with-tanstack-form/vite.config.js | 17 + .../svelte/with-tanstack-query/.gitignore | 8 + .../svelte/with-tanstack-query/index.html | 14 + .../svelte/with-tanstack-query/package.json | 27 + .../svelte/with-tanstack-query/src/App.svelte | 190 ++++ .../with-tanstack-query/src/Root.svelte | 10 + .../with-tanstack-query/src/fetchData.ts | 66 ++ .../svelte/with-tanstack-query/src/index.css | 26 + .../svelte/with-tanstack-query/src/main.ts | 9 + .../with-tanstack-query/svelte.config.js | 5 + .../svelte/with-tanstack-query/tsconfig.json | 13 + .../svelte/with-tanstack-query/vite.config.js | 17 + examples/vue/basic/src/App.vue | 17 +- examples/vue/column-ordering/src/App.vue | 17 +- examples/vue/column-pinning/src/App.vue | 33 +- .../vue/pagination-controlled/src/App.vue | 11 +- examples/vue/pagination/src/App.vue | 17 +- examples/vue/row-selection/src/App.vue | 11 +- examples/vue/sorting/src/App.vue | 16 +- examples/vue/virtualized-rows/src/App.vue | 10 +- package.json | 20 +- packages/svelte-table/eslint.config.js | 12 + packages/svelte-table/src/AppCell.svelte | 13 + packages/svelte-table/src/AppHeader.svelte | 13 + packages/svelte-table/src/AppTable.svelte | 11 + packages/svelte-table/src/FlexRender.svelte | 107 ++- packages/svelte-table/src/Subscribe.svelte | 18 +- packages/svelte-table/src/context-keys.ts | 3 + .../svelte-table/src/createTable.svelte.ts | 150 +-- .../svelte-table/src/createTableHelper.ts | 62 -- .../src/createTableHook.svelte.ts | 636 +++++++++++++ packages/svelte-table/src/index.ts | 10 +- packages/svelte-table/src/merge-objects.ts | 43 + packages/svelte-table/src/render-component.ts | 8 +- packages/vue-table/src/FlexRender.ts | 113 ++- pnpm-lock.yaml | 892 +++++++++++++++--- scripts/config.js | 8 +- 321 files changed, 11876 insertions(+), 1175 deletions(-) rename examples/angular/{basic => basic-inject-table}/.gitignore (100%) rename examples/angular/{basic => basic-inject-table}/README.md (100%) rename examples/angular/{basic => basic-inject-table}/angular.json (100%) rename examples/angular/{basic => basic-inject-table}/package.json (100%) rename examples/angular/{basic => basic-inject-table}/public/favicon.ico (100%) rename examples/angular/{basic => basic-inject-table}/src/app/app.config.ts (100%) rename examples/angular/{basic => basic-inject-table}/src/app/app.html (100%) rename examples/angular/{basic => basic-inject-table}/src/app/app.routes.ts (100%) rename examples/angular/{basic => basic-inject-table}/src/app/app.ts (100%) rename examples/angular/{basic => basic-inject-table}/src/index.html (100%) rename examples/angular/{basic => basic-inject-table}/src/main.ts (100%) rename examples/angular/{basic => basic-inject-table}/src/styles.css (100%) rename examples/angular/{basic => basic-inject-table}/tsconfig.app.json (100%) rename examples/angular/{basic => basic-inject-table}/tsconfig.json (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/.gitignore (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/README.md (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/index.html (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/package.json (89%) create mode 100644 examples/svelte/basic-app-table/src/App.svelte rename examples/svelte/{basic-table-helper => basic-app-table}/src/index.css (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/src/main.ts (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/svelte.config.js (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/tsconfig.json (100%) rename examples/svelte/{basic-table-helper => basic-app-table}/vite.config.js (100%) rename examples/svelte/{basic => basic-create-table}/.gitignore (100%) rename examples/svelte/{basic => basic-create-table}/README.md (100%) rename examples/svelte/{basic => basic-create-table}/index.html (100%) create mode 100644 examples/svelte/basic-create-table/package.json create mode 100644 examples/svelte/basic-create-table/src/App.svelte rename examples/svelte/{basic => basic-create-table}/src/index.css (100%) rename examples/svelte/{basic => basic-create-table}/src/main.ts (100%) rename examples/svelte/{basic => basic-create-table}/svelte.config.js (100%) rename examples/svelte/{basic => basic-create-table}/tsconfig.json (100%) rename examples/svelte/{basic => basic-create-table}/vite.config.js (100%) create mode 100644 examples/svelte/basic-external-state/index.html create mode 100644 examples/svelte/basic-external-state/package.json create mode 100644 examples/svelte/basic-external-state/src/App.svelte create mode 100644 examples/svelte/basic-external-state/src/index.css create mode 100644 examples/svelte/basic-external-state/src/main.ts create mode 100644 examples/svelte/basic-external-state/src/makeData.ts rename examples/svelte/{basic => basic-external-state}/src/vite-env.d.ts (100%) create mode 100644 examples/svelte/basic-external-state/svelte.config.js create mode 100644 examples/svelte/basic-external-state/tsconfig.json create mode 100644 examples/svelte/basic-external-state/vite.config.js create mode 100644 examples/svelte/basic-external-store/index.html create mode 100644 examples/svelte/basic-external-store/package.json create mode 100644 examples/svelte/basic-external-store/src/App.svelte create mode 100644 examples/svelte/basic-external-store/src/index.css create mode 100644 examples/svelte/basic-external-store/src/main.ts create mode 100644 examples/svelte/basic-external-store/src/makeData.ts create mode 100644 examples/svelte/basic-external-store/src/vite-env.d.ts create mode 100644 examples/svelte/basic-external-store/svelte.config.js create mode 100644 examples/svelte/basic-external-store/tsconfig.json create mode 100644 examples/svelte/basic-external-store/vite.config.js delete mode 100644 examples/svelte/basic-table-helper/src/App.svelte delete mode 100644 examples/svelte/basic/src/App.svelte create mode 100644 examples/svelte/column-pinning-split/.gitignore create mode 100644 examples/svelte/column-pinning-split/index.html create mode 100644 examples/svelte/column-pinning-split/package.json create mode 100644 examples/svelte/column-pinning-split/src/App.svelte create mode 100644 examples/svelte/column-pinning-split/src/index.css create mode 100644 examples/svelte/column-pinning-split/src/main.ts create mode 100644 examples/svelte/column-pinning-split/src/makeData.ts create mode 100644 examples/svelte/column-pinning-split/svelte.config.js create mode 100644 examples/svelte/column-pinning-split/tsconfig.json create mode 100644 examples/svelte/column-pinning-split/vite.config.js create mode 100644 examples/svelte/column-pinning-sticky/.gitignore create mode 100644 examples/svelte/column-pinning-sticky/index.html create mode 100644 examples/svelte/column-pinning-sticky/package.json create mode 100644 examples/svelte/column-pinning-sticky/src/App.svelte create mode 100644 examples/svelte/column-pinning-sticky/src/index.css create mode 100644 examples/svelte/column-pinning-sticky/src/main.ts create mode 100644 examples/svelte/column-pinning-sticky/src/makeData.ts create mode 100644 examples/svelte/column-pinning-sticky/svelte.config.js create mode 100644 examples/svelte/column-pinning-sticky/tsconfig.json create mode 100644 examples/svelte/column-pinning-sticky/vite.config.js create mode 100644 examples/svelte/column-resizing-performant/.gitignore create mode 100644 examples/svelte/column-resizing-performant/index.html create mode 100644 examples/svelte/column-resizing-performant/package.json create mode 100644 examples/svelte/column-resizing-performant/src/App.svelte create mode 100644 examples/svelte/column-resizing-performant/src/index.css create mode 100644 examples/svelte/column-resizing-performant/src/main.ts create mode 100644 examples/svelte/column-resizing-performant/src/makeData.ts create mode 100644 examples/svelte/column-resizing-performant/svelte.config.js create mode 100644 examples/svelte/column-resizing-performant/tsconfig.json create mode 100644 examples/svelte/column-resizing-performant/vite.config.js create mode 100644 examples/svelte/column-resizing/.gitignore create mode 100644 examples/svelte/column-resizing/index.html create mode 100644 examples/svelte/column-resizing/package.json create mode 100644 examples/svelte/column-resizing/src/App.svelte create mode 100644 examples/svelte/column-resizing/src/index.css create mode 100644 examples/svelte/column-resizing/src/main.ts create mode 100644 examples/svelte/column-resizing/svelte.config.js create mode 100644 examples/svelte/column-resizing/tsconfig.json create mode 100644 examples/svelte/column-resizing/vite.config.js create mode 100644 examples/svelte/column-sizing/.gitignore create mode 100644 examples/svelte/column-sizing/index.html rename examples/svelte/{basic => column-sizing}/package.json (90%) create mode 100644 examples/svelte/column-sizing/src/App.svelte create mode 100644 examples/svelte/column-sizing/src/index.css create mode 100644 examples/svelte/column-sizing/src/main.ts create mode 100644 examples/svelte/column-sizing/svelte.config.js create mode 100644 examples/svelte/column-sizing/tsconfig.json create mode 100644 examples/svelte/column-sizing/vite.config.js create mode 100644 examples/svelte/composable-tables/.gitignore create mode 100644 examples/svelte/composable-tables/index.html create mode 100644 examples/svelte/composable-tables/package.json create mode 100644 examples/svelte/composable-tables/src/App.svelte create mode 100644 examples/svelte/composable-tables/src/components/CategoryCell.svelte create mode 100644 examples/svelte/composable-tables/src/components/ColumnFilter.svelte create mode 100644 examples/svelte/composable-tables/src/components/FooterColumnId.svelte create mode 100644 examples/svelte/composable-tables/src/components/FooterSum.svelte create mode 100644 examples/svelte/composable-tables/src/components/NumberCell.svelte create mode 100644 examples/svelte/composable-tables/src/components/PaginationControls.svelte create mode 100644 examples/svelte/composable-tables/src/components/PriceCell.svelte create mode 100644 examples/svelte/composable-tables/src/components/ProductsTable.svelte create mode 100644 examples/svelte/composable-tables/src/components/ProgressCell.svelte create mode 100644 examples/svelte/composable-tables/src/components/RowActionsCell.svelte create mode 100644 examples/svelte/composable-tables/src/components/RowCount.svelte create mode 100644 examples/svelte/composable-tables/src/components/SortIndicator.svelte create mode 100644 examples/svelte/composable-tables/src/components/StatusCell.svelte create mode 100644 examples/svelte/composable-tables/src/components/TableToolbar.svelte create mode 100644 examples/svelte/composable-tables/src/components/TextCell.svelte create mode 100644 examples/svelte/composable-tables/src/components/UsersTable.svelte create mode 100644 examples/svelte/composable-tables/src/hooks/table.ts create mode 100644 examples/svelte/composable-tables/src/index.css create mode 100644 examples/svelte/composable-tables/src/main.ts create mode 100644 examples/svelte/composable-tables/src/makeData.ts create mode 100644 examples/svelte/composable-tables/svelte.config.js create mode 100644 examples/svelte/composable-tables/tsconfig.json create mode 100644 examples/svelte/composable-tables/vite.config.js create mode 100644 examples/svelte/expanding/.gitignore create mode 100644 examples/svelte/expanding/index.html create mode 100644 examples/svelte/expanding/package.json create mode 100644 examples/svelte/expanding/src/App.svelte create mode 100644 examples/svelte/expanding/src/index.css create mode 100644 examples/svelte/expanding/src/main.ts create mode 100644 examples/svelte/expanding/src/makeData.ts create mode 100644 examples/svelte/expanding/svelte.config.js create mode 100644 examples/svelte/expanding/tsconfig.json create mode 100644 examples/svelte/expanding/vite.config.js create mode 100644 examples/svelte/filtering/src/ColumnFilter.svelte create mode 100644 examples/svelte/filtering/src/DebouncedInput.svelte create mode 100644 examples/svelte/filters-faceted/.gitignore create mode 100644 examples/svelte/filters-faceted/README.md create mode 100644 examples/svelte/filters-faceted/index.html create mode 100644 examples/svelte/filters-faceted/package.json create mode 100644 examples/svelte/filters-faceted/src/App.svelte create mode 100644 examples/svelte/filters-faceted/src/ColumnFilter.svelte create mode 100644 examples/svelte/filters-faceted/src/DebouncedInput.svelte create mode 100644 examples/svelte/filters-faceted/src/index.css create mode 100644 examples/svelte/filters-faceted/src/main.ts create mode 100644 examples/svelte/filters-faceted/src/makeData.ts create mode 100644 examples/svelte/filters-faceted/svelte.config.js create mode 100644 examples/svelte/filters-faceted/tsconfig.json create mode 100644 examples/svelte/filters-faceted/vite.config.js create mode 100644 examples/svelte/filters-fuzzy/.gitignore create mode 100644 examples/svelte/filters-fuzzy/README.md create mode 100644 examples/svelte/filters-fuzzy/index.html create mode 100644 examples/svelte/filters-fuzzy/package.json create mode 100644 examples/svelte/filters-fuzzy/src/App.svelte create mode 100644 examples/svelte/filters-fuzzy/src/DebouncedInput.svelte create mode 100644 examples/svelte/filters-fuzzy/src/index.css create mode 100644 examples/svelte/filters-fuzzy/src/main.ts create mode 100644 examples/svelte/filters-fuzzy/src/makeData.ts create mode 100644 examples/svelte/filters-fuzzy/svelte.config.js create mode 100644 examples/svelte/filters-fuzzy/tsconfig.json create mode 100644 examples/svelte/filters-fuzzy/vite.config.js create mode 100644 examples/svelte/grouping/.gitignore create mode 100644 examples/svelte/grouping/index.html create mode 100644 examples/svelte/grouping/package.json create mode 100644 examples/svelte/grouping/src/App.svelte create mode 100644 examples/svelte/grouping/src/index.css create mode 100644 examples/svelte/grouping/src/main.ts create mode 100644 examples/svelte/grouping/src/makeData.ts create mode 100644 examples/svelte/grouping/svelte.config.js create mode 100644 examples/svelte/grouping/tsconfig.json create mode 100644 examples/svelte/grouping/vite.config.js create mode 100644 examples/svelte/pagination/.gitignore create mode 100644 examples/svelte/pagination/index.html create mode 100644 examples/svelte/pagination/package.json create mode 100644 examples/svelte/pagination/src/App.svelte create mode 100644 examples/svelte/pagination/src/index.css create mode 100644 examples/svelte/pagination/src/main.ts create mode 100644 examples/svelte/pagination/src/makeData.ts create mode 100644 examples/svelte/pagination/svelte.config.js create mode 100644 examples/svelte/pagination/tsconfig.json create mode 100644 examples/svelte/pagination/vite.config.js create mode 100644 examples/svelte/row-pinning/.gitignore create mode 100644 examples/svelte/row-pinning/index.html create mode 100644 examples/svelte/row-pinning/package.json create mode 100644 examples/svelte/row-pinning/src/App.svelte create mode 100644 examples/svelte/row-pinning/src/index.css create mode 100644 examples/svelte/row-pinning/src/main.ts create mode 100644 examples/svelte/row-pinning/src/makeData.ts create mode 100644 examples/svelte/row-pinning/svelte.config.js create mode 100644 examples/svelte/row-pinning/tsconfig.json create mode 100644 examples/svelte/row-pinning/vite.config.js create mode 100644 examples/svelte/row-selection/src/vite-env.d.ts create mode 100644 examples/svelte/sub-components/.gitignore create mode 100644 examples/svelte/sub-components/index.html create mode 100644 examples/svelte/sub-components/package.json create mode 100644 examples/svelte/sub-components/src/App.svelte create mode 100644 examples/svelte/sub-components/src/index.css create mode 100644 examples/svelte/sub-components/src/main.ts create mode 100644 examples/svelte/sub-components/src/makeData.ts create mode 100644 examples/svelte/sub-components/svelte.config.js create mode 100644 examples/svelte/sub-components/tsconfig.json create mode 100644 examples/svelte/sub-components/vite.config.js create mode 100644 examples/svelte/virtualized-columns/index.html create mode 100644 examples/svelte/virtualized-columns/package.json create mode 100644 examples/svelte/virtualized-columns/src/App.svelte create mode 100644 examples/svelte/virtualized-columns/src/index.css create mode 100644 examples/svelte/virtualized-columns/src/main.ts create mode 100644 examples/svelte/virtualized-columns/src/makeData.ts create mode 100644 examples/svelte/virtualized-columns/src/vite-env.d.ts create mode 100644 examples/svelte/virtualized-columns/svelte.config.js create mode 100644 examples/svelte/virtualized-columns/tsconfig.json create mode 100644 examples/svelte/virtualized-columns/vite.config.js create mode 100644 examples/svelte/virtualized-infinite-scrolling/index.html create mode 100644 examples/svelte/virtualized-infinite-scrolling/package.json create mode 100644 examples/svelte/virtualized-infinite-scrolling/src/App.svelte create mode 100644 examples/svelte/virtualized-infinite-scrolling/src/Root.svelte create mode 100644 examples/svelte/virtualized-infinite-scrolling/src/index.css create mode 100644 examples/svelte/virtualized-infinite-scrolling/src/main.ts create mode 100644 examples/svelte/virtualized-infinite-scrolling/src/makeData.ts create mode 100644 examples/svelte/virtualized-infinite-scrolling/src/vite-env.d.ts create mode 100644 examples/svelte/virtualized-infinite-scrolling/svelte.config.js create mode 100644 examples/svelte/virtualized-infinite-scrolling/tsconfig.json create mode 100644 examples/svelte/virtualized-infinite-scrolling/vite.config.js create mode 100644 examples/svelte/virtualized-rows/index.html create mode 100644 examples/svelte/virtualized-rows/package.json create mode 100644 examples/svelte/virtualized-rows/src/App.svelte create mode 100644 examples/svelte/virtualized-rows/src/index.css create mode 100644 examples/svelte/virtualized-rows/src/main.ts create mode 100644 examples/svelte/virtualized-rows/src/makeData.ts create mode 100644 examples/svelte/virtualized-rows/src/vite-env.d.ts create mode 100644 examples/svelte/virtualized-rows/svelte.config.js create mode 100644 examples/svelte/virtualized-rows/tsconfig.json create mode 100644 examples/svelte/virtualized-rows/vite.config.js create mode 100644 examples/svelte/with-tanstack-form/.gitignore create mode 100644 examples/svelte/with-tanstack-form/index.html create mode 100644 examples/svelte/with-tanstack-form/package.json create mode 100644 examples/svelte/with-tanstack-form/src/App.svelte create mode 100644 examples/svelte/with-tanstack-form/src/FormStateIndicator.svelte create mode 100644 examples/svelte/with-tanstack-form/src/NumberField.svelte create mode 100644 examples/svelte/with-tanstack-form/src/NumberFieldCell.svelte create mode 100644 examples/svelte/with-tanstack-form/src/SelectField.svelte create mode 100644 examples/svelte/with-tanstack-form/src/SelectFieldCell.svelte create mode 100644 examples/svelte/with-tanstack-form/src/SubmitButton.svelte create mode 100644 examples/svelte/with-tanstack-form/src/TextField.svelte create mode 100644 examples/svelte/with-tanstack-form/src/TextFieldCell.svelte create mode 100644 examples/svelte/with-tanstack-form/src/form-context.ts create mode 100644 examples/svelte/with-tanstack-form/src/form.ts create mode 100644 examples/svelte/with-tanstack-form/src/index.css create mode 100644 examples/svelte/with-tanstack-form/src/main.ts create mode 100644 examples/svelte/with-tanstack-form/src/makeData.ts create mode 100644 examples/svelte/with-tanstack-form/svelte.config.js create mode 100644 examples/svelte/with-tanstack-form/tsconfig.json create mode 100644 examples/svelte/with-tanstack-form/vite.config.js create mode 100644 examples/svelte/with-tanstack-query/.gitignore create mode 100644 examples/svelte/with-tanstack-query/index.html create mode 100644 examples/svelte/with-tanstack-query/package.json create mode 100644 examples/svelte/with-tanstack-query/src/App.svelte create mode 100644 examples/svelte/with-tanstack-query/src/Root.svelte create mode 100644 examples/svelte/with-tanstack-query/src/fetchData.ts create mode 100644 examples/svelte/with-tanstack-query/src/index.css create mode 100644 examples/svelte/with-tanstack-query/src/main.ts create mode 100644 examples/svelte/with-tanstack-query/svelte.config.js create mode 100644 examples/svelte/with-tanstack-query/tsconfig.json create mode 100644 examples/svelte/with-tanstack-query/vite.config.js create mode 100644 packages/svelte-table/src/AppCell.svelte create mode 100644 packages/svelte-table/src/AppHeader.svelte create mode 100644 packages/svelte-table/src/AppTable.svelte create mode 100644 packages/svelte-table/src/context-keys.ts delete mode 100644 packages/svelte-table/src/createTableHelper.ts create mode 100644 packages/svelte-table/src/createTableHook.svelte.ts create mode 100644 packages/svelte-table/src/merge-objects.ts diff --git a/docs/config.json b/docs/config.json index 3f534f5089..444326b981 100644 --- a/docs/config.json +++ b/docs/config.json @@ -832,16 +832,19 @@ { "label": "svelte", "children": [ - { "to": "framework/svelte/examples/basic", "label": "Basic" }, - { "to": "framework/svelte/examples/basic-snippets", "label": "Basic Snippets" }, - { "to": "framework/svelte/examples/basic-table-helper", "label": "Basic with Helpers" }, + { "to": "framework/svelte/examples/basic-create-table", "label": "Basic (createTable)" }, + { "to": "framework/svelte/examples/basic-app-table", "label": "Basic (createAppTable)" }, + { "to": "framework/svelte/examples/basic-snippets", "label": "Basic (Snippets)" }, + { "to": "framework/svelte/examples/basic-external-state", "label": "Basic (External State)" }, + { "to": "framework/svelte/examples/basic-external-store", "label": "Basic (External Store)" }, { "to": "framework/svelte/examples/column-groups", "label": "Header Groups" } ] }, { "label": "vue", "children": [ - { "to": "framework/vue/examples/basic", "label": "Basic" } + { "to": "framework/vue/examples/basic", "label": "Basic" }, + { "to": "framework/vue/examples/basic-use-app-table", "label": "Basic (useAppTable)" } ] }, { @@ -914,10 +917,21 @@ { "label": "solid", "children": [ + { "to": "framework/solid/examples/filters", "label": "Column Filters" }, + { "to": "framework/solid/examples/filters-faceted", "label": "Column Filters (Faceted)" }, + { "to": "framework/solid/examples/filters-fuzzy", "label": "Fuzzy Search Filters" }, { "to": "framework/solid/examples/column-ordering", "label": "Column Ordering" }, + { "to": "framework/solid/examples/column-pinning", "label": "Column Pinning" }, + { "to": "framework/solid/examples/column-pinning-split", "label": "Column Pinning (Split)" }, + { "to": "framework/solid/examples/column-pinning-sticky", "label": "Sticky Column Pinning" }, + { "to": "framework/solid/examples/column-sizing", "label": "Column Sizing" }, + { "to": "framework/solid/examples/column-resizing", "label": "Column Resizing" }, + { "to": "framework/solid/examples/column-resizing-performant", "label": "Performant Column Resizing" }, { "to": "framework/solid/examples/column-visibility", "label": "Column Visibility" }, - { "to": "framework/solid/examples/filters", "label": "Filters" }, - { "to": "framework/solid/examples/filters-faceted", "label": "Filters (Faceted)" }, + { "to": "framework/solid/examples/expanding", "label": "Expanding" }, + { "to": "framework/solid/examples/grouping", "label": "Grouping" }, + { "to": "framework/solid/examples/pagination", "label": "Pagination" }, + { "to": "framework/solid/examples/row-pinning", "label": "Row Pinning" }, { "to": "framework/solid/examples/row-selection", "label": "Row Selection" }, { "to": "framework/solid/examples/sorting", "label": "Sorting" } ] @@ -925,10 +939,21 @@ { "label": "svelte", "children": [ + { "to": "framework/svelte/examples/filtering", "label": "Column Filters" }, + { "to": "framework/svelte/examples/filters-faceted", "label": "Column Filters (Faceted)" }, + { "to": "framework/svelte/examples/filters-fuzzy", "label": "Fuzzy Search Filters" }, { "to": "framework/svelte/examples/column-ordering", "label": "Column Ordering" }, { "to": "framework/svelte/examples/column-pinning", "label": "Column Pinning" }, + { "to": "framework/svelte/examples/column-pinning-split", "label": "Column Pinning (Split)" }, + { "to": "framework/svelte/examples/column-pinning-sticky", "label": "Sticky Column Pinning" }, + { "to": "framework/svelte/examples/column-sizing", "label": "Column Sizing" }, + { "to": "framework/svelte/examples/column-resizing", "label": "Column Resizing" }, + { "to": "framework/svelte/examples/column-resizing-performant", "label": "Performant Column Resizing" }, { "to": "framework/svelte/examples/column-visibility", "label": "Column Visibility" }, - { "to": "framework/svelte/examples/filtering", "label": "Filtering" }, + { "to": "framework/svelte/examples/expanding", "label": "Expanding" }, + { "to": "framework/svelte/examples/grouping", "label": "Grouping" }, + { "to": "framework/svelte/examples/pagination", "label": "Pagination" }, + { "to": "framework/svelte/examples/row-pinning", "label": "Row Pinning" }, { "to": "framework/svelte/examples/row-selection", "label": "Row Selection" }, { "to": "framework/svelte/examples/sorting", "label": "Sorting" } ] @@ -1001,13 +1026,32 @@ { "label": "solid", "children": [ - { "to": "framework/solid/examples/bootstrap", "label": "Solid Bootstrap" }, { "to": "framework/solid/examples/composable-tables", "label": "Composable Tables" }, - { "to": "framework/solid/examples/with-tanstack-query", "label": "With TanStack Query" }] + { "to": "framework/solid/examples/sub-components", "label": "Sub Components" }, + { "to": "framework/solid/examples/virtualized-columns", "label": "With TanStack Virtual - Columns" }, + { "to": "framework/solid/examples/virtualized-rows", "label": "With TanStack Virtual - Rows" }, + { "to": "framework/solid/examples/virtualized-infinite-scrolling", "label": "With TanStack Virtual - Infinite Scrolling" }, + { "to": "framework/solid/examples/with-tanstack-form", "label": "With TanStack Form" }, + { "to": "framework/solid/examples/with-tanstack-query", "label": "With TanStack Query" }, + { "to": "framework/solid/examples/with-tanstack-router", "label": "With TanStack Router" } + ] + }, + { + "label": "svelte", + "children": [ + { "to": "framework/svelte/examples/composable-tables", "label": "Composable Tables" }, + { "to": "framework/svelte/examples/sub-components", "label": "Sub Components" }, + { "to": "framework/svelte/examples/virtualized-columns", "label": "With TanStack Virtual - Columns" }, + { "to": "framework/svelte/examples/virtualized-rows", "label": "With TanStack Virtual - Rows" }, + { "to": "framework/svelte/examples/virtualized-infinite-scrolling", "label": "With TanStack Virtual - Infinite Scrolling" }, + { "to": "framework/svelte/examples/with-tanstack-form", "label": "With TanStack Form" }, + { "to": "framework/svelte/examples/with-tanstack-query", "label": "With TanStack Query" } + ] }, { "label": "vue", "children": [ + { "to": "framework/vue/examples/composable-tables", "label": "Composable Tables" }, { "to": "framework/vue/examples/sub-components", "label": "Sub Components" }, { "to": "framework/vue/examples/virtualized-rows", "label": "With TanStack Virtual (Rows)" } ] diff --git a/examples/angular/basic/.gitignore b/examples/angular/basic-inject-table/.gitignore similarity index 100% rename from examples/angular/basic/.gitignore rename to examples/angular/basic-inject-table/.gitignore diff --git a/examples/angular/basic/README.md b/examples/angular/basic-inject-table/README.md similarity index 100% rename from examples/angular/basic/README.md rename to examples/angular/basic-inject-table/README.md diff --git a/examples/angular/basic/angular.json b/examples/angular/basic-inject-table/angular.json similarity index 100% rename from examples/angular/basic/angular.json rename to examples/angular/basic-inject-table/angular.json diff --git a/examples/angular/basic/package.json b/examples/angular/basic-inject-table/package.json similarity index 100% rename from examples/angular/basic/package.json rename to examples/angular/basic-inject-table/package.json diff --git a/examples/angular/basic/public/favicon.ico b/examples/angular/basic-inject-table/public/favicon.ico similarity index 100% rename from examples/angular/basic/public/favicon.ico rename to examples/angular/basic-inject-table/public/favicon.ico diff --git a/examples/angular/basic/src/app/app.config.ts b/examples/angular/basic-inject-table/src/app/app.config.ts similarity index 100% rename from examples/angular/basic/src/app/app.config.ts rename to examples/angular/basic-inject-table/src/app/app.config.ts diff --git a/examples/angular/basic/src/app/app.html b/examples/angular/basic-inject-table/src/app/app.html similarity index 100% rename from examples/angular/basic/src/app/app.html rename to examples/angular/basic-inject-table/src/app/app.html diff --git a/examples/angular/basic/src/app/app.routes.ts b/examples/angular/basic-inject-table/src/app/app.routes.ts similarity index 100% rename from examples/angular/basic/src/app/app.routes.ts rename to examples/angular/basic-inject-table/src/app/app.routes.ts diff --git a/examples/angular/basic/src/app/app.ts b/examples/angular/basic-inject-table/src/app/app.ts similarity index 100% rename from examples/angular/basic/src/app/app.ts rename to examples/angular/basic-inject-table/src/app/app.ts diff --git a/examples/angular/basic/src/index.html b/examples/angular/basic-inject-table/src/index.html similarity index 100% rename from examples/angular/basic/src/index.html rename to examples/angular/basic-inject-table/src/index.html diff --git a/examples/angular/basic/src/main.ts b/examples/angular/basic-inject-table/src/main.ts similarity index 100% rename from examples/angular/basic/src/main.ts rename to examples/angular/basic-inject-table/src/main.ts diff --git a/examples/angular/basic/src/styles.css b/examples/angular/basic-inject-table/src/styles.css similarity index 100% rename from examples/angular/basic/src/styles.css rename to examples/angular/basic-inject-table/src/styles.css diff --git a/examples/angular/basic/tsconfig.app.json b/examples/angular/basic-inject-table/tsconfig.app.json similarity index 100% rename from examples/angular/basic/tsconfig.app.json rename to examples/angular/basic-inject-table/tsconfig.app.json diff --git a/examples/angular/basic/tsconfig.json b/examples/angular/basic-inject-table/tsconfig.json similarity index 100% rename from examples/angular/basic/tsconfig.json rename to examples/angular/basic-inject-table/tsconfig.json diff --git a/examples/solid/basic-external-state/src/App.tsx b/examples/solid/basic-external-state/src/App.tsx index 4a0b248ad3..72ed260226 100644 --- a/examples/solid/basic-external-state/src/App.tsx +++ b/examples/solid/basic-external-state/src/App.tsx @@ -3,7 +3,7 @@ import { createPaginatedRowModel, createSortedRowModel, createTable, - flexRender, + FlexRender, rowPaginationFeature, rowSortingFeature, sortFns, @@ -93,10 +93,7 @@ function App() { } onClick={header.column.getToggleSortingHandler()} > - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {{ asc: ' 🔼', desc: ' 🔽', @@ -117,10 +114,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} diff --git a/examples/solid/basic-external-store/src/App.tsx b/examples/solid/basic-external-store/src/App.tsx index de969cbfc5..1894ba3eac 100644 --- a/examples/solid/basic-external-store/src/App.tsx +++ b/examples/solid/basic-external-store/src/App.tsx @@ -3,7 +3,7 @@ import { createPaginatedRowModel, createSortedRowModel, createTable, - flexRender, + FlexRender, getInitialTableState, rowPaginationFeature, rowSortingFeature, @@ -106,10 +106,7 @@ function App() { } onClick={header.column.getToggleSortingHandler()} > - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {{ asc: ' 🔼', desc: ' 🔽', @@ -130,10 +127,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} diff --git a/examples/solid/basic-use-table/src/App.tsx b/examples/solid/basic-use-table/src/App.tsx index ad9441e4c3..9edb668ebf 100644 --- a/examples/solid/basic-use-table/src/App.tsx +++ b/examples/solid/basic-use-table/src/App.tsx @@ -1,4 +1,4 @@ -import { createTable, flexRender, tableFeatures } from '@tanstack/solid-table' +import { createTable, FlexRender, tableFeatures } from '@tanstack/solid-table' import { For, createSignal } from 'solid-js' import type { ColumnDef } from '@tanstack/solid-table' @@ -103,12 +103,9 @@ function App() { {(header) => ( - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {header.isPlaceholder ? null : ( + + )} )} @@ -123,10 +120,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} @@ -141,12 +135,9 @@ function App() { {(header) => ( - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.footer, - header.getContext(), - )} + {header.isPlaceholder ? null : ( + + )} )} diff --git a/examples/solid/column-groups/src/App.tsx b/examples/solid/column-groups/src/App.tsx index 5a4662411c..0ebb899768 100644 --- a/examples/solid/column-groups/src/App.tsx +++ b/examples/solid/column-groups/src/App.tsx @@ -1,5 +1,5 @@ import { For, createSignal } from 'solid-js' -import { createTable, flexRender, tableFeatures } from '@tanstack/solid-table' +import { createTable, FlexRender, tableFeatures } from '@tanstack/solid-table' import type { ColumnDef } from '@tanstack/solid-table' type Person = { @@ -114,12 +114,9 @@ function App() { {(header) => ( - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {header.isPlaceholder ? null : ( + + )} )} @@ -134,10 +131,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} @@ -152,12 +146,9 @@ function App() { {(header) => ( - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.footer, - header.getContext(), - )} + {header.isPlaceholder ? null : ( + + )} )} diff --git a/examples/solid/column-ordering/src/App.tsx b/examples/solid/column-ordering/src/App.tsx index 8036eeaa76..9e995610e6 100644 --- a/examples/solid/column-ordering/src/App.tsx +++ b/examples/solid/column-ordering/src/App.tsx @@ -4,7 +4,7 @@ import { columnOrderingFeature, columnVisibilityFeature, createTable, - flexRender, + FlexRender, tableFeatures, } from '@tanstack/solid-table' import { makeData } from './makeData' @@ -133,10 +133,7 @@ function App() { {(header) => ( - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + )} @@ -152,10 +149,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} @@ -171,10 +165,7 @@ function App() { {(header) => ( - {flexRender( - header.column.columnDef.footer, - header.getContext(), - )} + )} diff --git a/examples/solid/column-visibility/src/App.tsx b/examples/solid/column-visibility/src/App.tsx index 67c12c2ce3..12f970d01a 100644 --- a/examples/solid/column-visibility/src/App.tsx +++ b/examples/solid/column-visibility/src/App.tsx @@ -1,7 +1,7 @@ import { columnVisibilityFeature, createTable, - flexRender, + FlexRender, tableFeatures, } from '@tanstack/solid-table' import { For, Show, createSignal } from 'solid-js' @@ -147,10 +147,7 @@ function App() { {(header) => ( - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + )} @@ -166,10 +163,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} @@ -185,10 +179,7 @@ function App() { {(header) => ( - {flexRender( - header.column.columnDef.footer, - header.getContext(), - )} + )} diff --git a/examples/solid/filters-faceted/src/App.tsx b/examples/solid/filters-faceted/src/App.tsx index 62572b2a0a..1ffcd3cdaa 100644 --- a/examples/solid/filters-faceted/src/App.tsx +++ b/examples/solid/filters-faceted/src/App.tsx @@ -7,7 +7,7 @@ import { createFilteredRowModel, createTable, filterFns, - flexRender, + FlexRender, globalFilteringFeature, tableFeatures, } from '@tanstack/solid-table' @@ -121,10 +121,7 @@ function App() { {header.isPlaceholder ? null : ( <> - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {header.column.getCanFilter() ? (
{(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} diff --git a/examples/solid/filters/src/App.tsx b/examples/solid/filters/src/App.tsx index 416fbeafc0..d6366b7935 100644 --- a/examples/solid/filters/src/App.tsx +++ b/examples/solid/filters/src/App.tsx @@ -7,7 +7,7 @@ import { createFilteredRowModel, createTable, filterFns, - flexRender, + FlexRender, globalFilteringFeature, tableFeatures, } from '@tanstack/solid-table' @@ -124,10 +124,7 @@ function App() { {header.isPlaceholder ? null : ( <> - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {header.column.getCanFilter() ? (
{(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} diff --git a/examples/solid/row-selection/src/App.tsx b/examples/solid/row-selection/src/App.tsx index 664cf9c00e..bc889e08d5 100644 --- a/examples/solid/row-selection/src/App.tsx +++ b/examples/solid/row-selection/src/App.tsx @@ -7,7 +7,7 @@ import { createPaginatedRowModel, createTable, filterFns, - flexRender, + FlexRender, globalFilteringFeature, rowPaginationFeature, rowSelectionFeature, @@ -152,10 +152,7 @@ function App() { <> - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} +
@@ -177,10 +174,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} diff --git a/examples/solid/sorting/src/App.tsx b/examples/solid/sorting/src/App.tsx index d7db1c69f2..149a320040 100644 --- a/examples/solid/sorting/src/App.tsx +++ b/examples/solid/sorting/src/App.tsx @@ -1,7 +1,7 @@ import { createSortedRowModel, createTable, - flexRender, + FlexRender, rowSortingFeature, sortFns, tableFeatures, @@ -100,10 +100,7 @@ function App() { } onClick={header.column.getToggleSortingHandler()} > - {flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {{ asc: ' 🔼', desc: ' 🔽', @@ -124,10 +121,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} diff --git a/examples/solid/with-tanstack-query/src/App.tsx b/examples/solid/with-tanstack-query/src/App.tsx index 9afad1a617..e52d647290 100644 --- a/examples/solid/with-tanstack-query/src/App.tsx +++ b/examples/solid/with-tanstack-query/src/App.tsx @@ -3,7 +3,7 @@ import { createStore, useStore } from '@tanstack/solid-store' import { createColumnHelper, createTable, - flexRender, + FlexRender, getInitialTableState, rowPaginationFeature, tableFeatures, @@ -84,12 +84,9 @@ function App() { {(header) => ( - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext(), - )} + {header.isPlaceholder ? null : ( + + )} )} @@ -104,10 +101,7 @@ function App() { {(cell) => ( - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} + )} diff --git a/examples/svelte/basic-table-helper/.gitignore b/examples/svelte/basic-app-table/.gitignore similarity index 100% rename from examples/svelte/basic-table-helper/.gitignore rename to examples/svelte/basic-app-table/.gitignore diff --git a/examples/svelte/basic-table-helper/README.md b/examples/svelte/basic-app-table/README.md similarity index 100% rename from examples/svelte/basic-table-helper/README.md rename to examples/svelte/basic-app-table/README.md diff --git a/examples/svelte/basic-table-helper/index.html b/examples/svelte/basic-app-table/index.html similarity index 100% rename from examples/svelte/basic-table-helper/index.html rename to examples/svelte/basic-app-table/index.html diff --git a/examples/svelte/basic-table-helper/package.json b/examples/svelte/basic-app-table/package.json similarity index 89% rename from examples/svelte/basic-table-helper/package.json rename to examples/svelte/basic-app-table/package.json index 5b0e66f9c0..183b91e671 100644 --- a/examples/svelte/basic-table-helper/package.json +++ b/examples/svelte/basic-app-table/package.json @@ -1,5 +1,5 @@ { - "name": "tanstack-table-example-svelte-basic-table-helper", + "name": "tanstack-table-example-svelte-basic-app-table", "version": "0.0.0", "private": true, "type": "module", diff --git a/examples/svelte/basic-app-table/src/App.svelte b/examples/svelte/basic-app-table/src/App.svelte new file mode 100644 index 0000000000..58bfe5c0f5 --- /dev/null +++ b/examples/svelte/basic-app-table/src/App.svelte @@ -0,0 +1,180 @@ + + + +
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + + + {#each table.getFooterGroups() as footerGroup (footerGroup.id)} + + {#each footerGroup.headers as header (header.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} +
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} +
+ {/if} +
+ +
+ {#if !header.isPlaceholder} + + {/if} +
+
+
{JSON.stringify(table.store.state, null, 2)}
+
diff --git a/examples/svelte/basic-table-helper/src/index.css b/examples/svelte/basic-app-table/src/index.css similarity index 100% rename from examples/svelte/basic-table-helper/src/index.css rename to examples/svelte/basic-app-table/src/index.css diff --git a/examples/svelte/basic-table-helper/src/main.ts b/examples/svelte/basic-app-table/src/main.ts similarity index 100% rename from examples/svelte/basic-table-helper/src/main.ts rename to examples/svelte/basic-app-table/src/main.ts diff --git a/examples/svelte/basic-table-helper/svelte.config.js b/examples/svelte/basic-app-table/svelte.config.js similarity index 100% rename from examples/svelte/basic-table-helper/svelte.config.js rename to examples/svelte/basic-app-table/svelte.config.js diff --git a/examples/svelte/basic-table-helper/tsconfig.json b/examples/svelte/basic-app-table/tsconfig.json similarity index 100% rename from examples/svelte/basic-table-helper/tsconfig.json rename to examples/svelte/basic-app-table/tsconfig.json diff --git a/examples/svelte/basic-table-helper/vite.config.js b/examples/svelte/basic-app-table/vite.config.js similarity index 100% rename from examples/svelte/basic-table-helper/vite.config.js rename to examples/svelte/basic-app-table/vite.config.js diff --git a/examples/svelte/basic/.gitignore b/examples/svelte/basic-create-table/.gitignore similarity index 100% rename from examples/svelte/basic/.gitignore rename to examples/svelte/basic-create-table/.gitignore diff --git a/examples/svelte/basic/README.md b/examples/svelte/basic-create-table/README.md similarity index 100% rename from examples/svelte/basic/README.md rename to examples/svelte/basic-create-table/README.md diff --git a/examples/svelte/basic/index.html b/examples/svelte/basic-create-table/index.html similarity index 100% rename from examples/svelte/basic/index.html rename to examples/svelte/basic-create-table/index.html diff --git a/examples/svelte/basic-create-table/package.json b/examples/svelte/basic-create-table/package.json new file mode 100644 index 0000000000..0856ef3fad --- /dev/null +++ b/examples/svelte/basic-create-table/package.json @@ -0,0 +1,23 @@ +{ + "name": "tanstack-table-example-svelte-basic-create-table", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/basic-create-table/src/App.svelte b/examples/svelte/basic-create-table/src/App.svelte new file mode 100644 index 0000000000..90f0656dfe --- /dev/null +++ b/examples/svelte/basic-create-table/src/App.svelte @@ -0,0 +1,150 @@ + + + +
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + + + {#each table.getFooterGroups() as footerGroup (footerGroup.id)} + + {#each footerGroup.headers as header (header.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + {/if} +
+ +
+ {#if !header.isPlaceholder} + + {/if} +
+
+ +
diff --git a/examples/svelte/basic/src/index.css b/examples/svelte/basic-create-table/src/index.css similarity index 100% rename from examples/svelte/basic/src/index.css rename to examples/svelte/basic-create-table/src/index.css diff --git a/examples/svelte/basic/src/main.ts b/examples/svelte/basic-create-table/src/main.ts similarity index 100% rename from examples/svelte/basic/src/main.ts rename to examples/svelte/basic-create-table/src/main.ts diff --git a/examples/svelte/basic/svelte.config.js b/examples/svelte/basic-create-table/svelte.config.js similarity index 100% rename from examples/svelte/basic/svelte.config.js rename to examples/svelte/basic-create-table/svelte.config.js diff --git a/examples/svelte/basic/tsconfig.json b/examples/svelte/basic-create-table/tsconfig.json similarity index 100% rename from examples/svelte/basic/tsconfig.json rename to examples/svelte/basic-create-table/tsconfig.json diff --git a/examples/svelte/basic/vite.config.js b/examples/svelte/basic-create-table/vite.config.js similarity index 100% rename from examples/svelte/basic/vite.config.js rename to examples/svelte/basic-create-table/vite.config.js diff --git a/examples/svelte/basic-external-state/index.html b/examples/svelte/basic-external-state/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/basic-external-state/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/basic-external-state/package.json b/examples/svelte/basic-external-state/package.json new file mode 100644 index 0000000000..ceb3a231b8 --- /dev/null +++ b/examples/svelte/basic-external-state/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-basic-external-state", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/basic-external-state/src/App.svelte b/examples/svelte/basic-external-state/src/App.svelte new file mode 100644 index 0000000000..defa4846b9 --- /dev/null +++ b/examples/svelte/basic-external-state/src/App.svelte @@ -0,0 +1,197 @@ + + +
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} +
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} +
+ {/if} +
+ +
+
+
+ + + + + +
Page
+ + {pagination().pageIndex + 1} of {table.getPageCount()} + +
+ + | Go to page: + { + const page = e.currentTarget.value + ? Number(e.currentTarget.value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
+
+    {JSON.stringify(
+      { sorting: sorting(), pagination: pagination() },
+      null,
+      2,
+    )}
+  
+
diff --git a/examples/svelte/basic-external-state/src/index.css b/examples/svelte/basic-external-state/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/basic-external-state/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/svelte/basic-external-state/src/main.ts b/examples/svelte/basic-external-state/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/basic-external-state/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/basic-external-state/src/makeData.ts b/examples/svelte/basic-external-state/src/makeData.ts new file mode 100644 index 0000000000..6311127267 --- /dev/null +++ b/examples/svelte/basic-external-state/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((): Person => { + return { + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + } + }) + } + + return makeDataLevel() +} diff --git a/examples/svelte/basic/src/vite-env.d.ts b/examples/svelte/basic-external-state/src/vite-env.d.ts similarity index 100% rename from examples/svelte/basic/src/vite-env.d.ts rename to examples/svelte/basic-external-state/src/vite-env.d.ts diff --git a/examples/svelte/basic-external-state/svelte.config.js b/examples/svelte/basic-external-state/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/basic-external-state/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/basic-external-state/tsconfig.json b/examples/svelte/basic-external-state/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/basic-external-state/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/basic-external-state/vite.config.js b/examples/svelte/basic-external-state/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/basic-external-state/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/basic-external-store/index.html b/examples/svelte/basic-external-store/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/basic-external-store/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/basic-external-store/package.json b/examples/svelte/basic-external-store/package.json new file mode 100644 index 0000000000..16084910d9 --- /dev/null +++ b/examples/svelte/basic-external-store/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-basic-external-store", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/basic-external-store/src/App.svelte b/examples/svelte/basic-external-store/src/App.svelte new file mode 100644 index 0000000000..99c8b4a21f --- /dev/null +++ b/examples/svelte/basic-external-store/src/App.svelte @@ -0,0 +1,211 @@ + + +
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} +
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} +
+ {/if} +
+ +
+
+
+ + + + + +
Page
+ + {tableState.pagination.pageIndex + 1} of {table.getPageCount()} + +
+ + | Go to page: + { + const page = (e.target as HTMLInputElement).value + ? Number((e.target as HTMLInputElement).value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
+
{JSON.stringify(tableState, null, 2)}
+
diff --git a/examples/svelte/basic-external-store/src/index.css b/examples/svelte/basic-external-store/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/basic-external-store/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/svelte/basic-external-store/src/main.ts b/examples/svelte/basic-external-store/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/basic-external-store/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/basic-external-store/src/makeData.ts b/examples/svelte/basic-external-store/src/makeData.ts new file mode 100644 index 0000000000..6311127267 --- /dev/null +++ b/examples/svelte/basic-external-store/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((): Person => { + return { + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + } + }) + } + + return makeDataLevel() +} diff --git a/examples/svelte/basic-external-store/src/vite-env.d.ts b/examples/svelte/basic-external-store/src/vite-env.d.ts new file mode 100644 index 0000000000..4078e7476a --- /dev/null +++ b/examples/svelte/basic-external-store/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples/svelte/basic-external-store/svelte.config.js b/examples/svelte/basic-external-store/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/basic-external-store/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/basic-external-store/tsconfig.json b/examples/svelte/basic-external-store/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/basic-external-store/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/basic-external-store/vite.config.js b/examples/svelte/basic-external-store/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/basic-external-store/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/basic-snippets/src/App.svelte b/examples/svelte/basic-snippets/src/App.svelte index 2d02a1884a..ba7e73ac4b 100644 --- a/examples/svelte/basic-snippets/src/App.svelte +++ b/examples/svelte/basic-snippets/src/App.svelte @@ -1,6 +1,6 @@ - - -
- - - {#each table.getHeaderGroups() as headerGroup} - - {#each headerGroup.headers as header} - - {/each} - - {/each} - - - {#each table.getRowModel().rows as row} - - {#each row.getAllCells() as cell} - - {/each} - - {/each} - - - {#each table.getFooterGroups() as footerGroup} - - {#each footerGroup.headers as header} - - {/each} - - {/each} - -
- {#if !header.isPlaceholder} - - {/if} -
- -
- {#if !header.isPlaceholder} - - {/if} -
-
-
diff --git a/examples/svelte/basic/src/App.svelte b/examples/svelte/basic/src/App.svelte deleted file mode 100644 index 03b9e67ed5..0000000000 --- a/examples/svelte/basic/src/App.svelte +++ /dev/null @@ -1,166 +0,0 @@ - - - -
- - - {#each table.getHeaderGroups() as headerGroup} - - {#each headerGroup.headers as header} - - {/each} - - {/each} - - - {#each table.getRowModel().rows as row} - - {#each row.getAllCells() as cell} - - {/each} - - {/each} - - - {#each table.getFooterGroups() as footerGroup} - - {#each footerGroup.headers as header} - - {/each} - - {/each} - -
- {#if !header.isPlaceholder} - - {/if} -
- -
- {#if !header.isPlaceholder} - - {/if} -
-
-
diff --git a/examples/svelte/column-groups/src/App.svelte b/examples/svelte/column-groups/src/App.svelte index fb22034297..112a7c4fbd 100644 --- a/examples/svelte/column-groups/src/App.svelte +++ b/examples/svelte/column-groups/src/App.svelte @@ -108,15 +108,12 @@
- {#each table.getHeaderGroups() as headerGroup} + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} - {#each headerGroup.headers as header} + {#each headerGroup.headers as header (header.id)} {/each} @@ -124,29 +121,23 @@ {/each} - {#each table.getRowModel().rows as row} + {#each table.getRowModel().rows as row (row.id)} - {#each row.getAllCells() as cell} + {#each row.getAllCells() as cell (cell.id)} {/each} {/each} - {#each table.getFooterGroups() as footerGroup} + {#each table.getFooterGroups() as footerGroup (footerGroup.id)} - {#each footerGroup.headers as header} + {#each footerGroup.headers as header (header.id)} {/each} diff --git a/examples/svelte/column-ordering/src/App.svelte b/examples/svelte/column-ordering/src/App.svelte index 2568ea35f1..9810b6c9a7 100644 --- a/examples/svelte/column-ordering/src/App.svelte +++ b/examples/svelte/column-ordering/src/App.svelte @@ -150,15 +150,12 @@
{#if !header.isPlaceholder} - + {/if}
- +
{#if !header.isPlaceholder} - + {/if}
- {#each table.getHeaderGroups() as headerGroup} + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} - {#each headerGroup.headers as header} + {#each headerGroup.headers as header (header.id)} {/each} @@ -166,14 +163,11 @@ {/each} - {#each table.getCoreRowModel().rows.slice(0, 20) as row} + {#each table.getCoreRowModel().rows.slice(0, 20) as row (row.id)} - {#each row.getVisibleCells() as cell} + {#each row.getVisibleCells() as cell (cell.id)} {/each} diff --git a/examples/svelte/column-pinning-split/.gitignore b/examples/svelte/column-pinning-split/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/column-pinning-split/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/column-pinning-split/index.html b/examples/svelte/column-pinning-split/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/column-pinning-split/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/column-pinning-split/package.json b/examples/svelte/column-pinning-split/package.json new file mode 100644 index 0000000000..b7b3773896 --- /dev/null +++ b/examples/svelte/column-pinning-split/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-column-pinning-split", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/column-pinning-split/src/App.svelte b/examples/svelte/column-pinning-split/src/App.svelte new file mode 100644 index 0000000000..fe58ef2b22 --- /dev/null +++ b/examples/svelte/column-pinning-split/src/App.svelte @@ -0,0 +1,313 @@ + + +
+
+
+ +
+ {#each table.getAllLeafColumns() as column} +
+ +
+ {/each} +
+
+
+ + +
+
+

+ This example takes advantage of the "splitting" APIs. (APIs that have + "left", "center", and "right" modifiers) +

+
+
{#if !header.isPlaceholder} - + {/if}
- +
+ + {#each table.getLeftHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows.slice(0, 20) as row (row.id)} + + {#each row.getLeftVisibleCells() as cell (cell.id)} + + {/each} + + {/each} + +
+
+ {#if !header.isPlaceholder} + + {/if} +
+ {#if !header.isPlaceholder && header.column.getCanPin()} +
+ {#if header.column.getIsPinned() !== 'left'} + + {/if} + {#if header.column.getIsPinned()} + + {/if} + {#if header.column.getIsPinned() !== 'right'} + + {/if} +
+ {/if} +
+ +
+ + + {#each table.getCenterHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows.slice(0, 20) as row (row.id)} + + {#each row.getCenterVisibleCells() as cell (cell.id)} + + {/each} + + {/each} + +
+
+ {#if !header.isPlaceholder} + + {/if} +
+ {#if !header.isPlaceholder && header.column.getCanPin()} +
+ {#if header.column.getIsPinned() !== 'left'} + + {/if} + {#if header.column.getIsPinned()} + + {/if} + {#if header.column.getIsPinned() !== 'right'} + + {/if} +
+ {/if} +
+ +
+ + + {#each table.getRightHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows.slice(0, 20) as row (row.id)} + + {#each row.getRightVisibleCells() as cell (cell.id)} + + {/each} + + {/each} + +
+
+ {#if !header.isPlaceholder} + + {/if} +
+ {#if !header.isPlaceholder && header.column.getCanPin()} +
+ {#if header.column.getIsPinned() !== 'left'} + + {/if} + {#if header.column.getIsPinned()} + + {/if} + {#if header.column.getIsPinned() !== 'right'} + + {/if} +
+ {/if} +
+ +
+
+
{JSON.stringify(table.state, null, 2)}
+
diff --git a/examples/svelte/column-pinning-split/src/index.css b/examples/svelte/column-pinning-split/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/column-pinning-split/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/svelte/column-pinning-split/src/main.ts b/examples/svelte/column-pinning-split/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/column-pinning-split/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/column-pinning-split/src/makeData.ts b/examples/svelte/column-pinning-split/src/makeData.ts new file mode 100644 index 0000000000..4f96799246 --- /dev/null +++ b/examples/svelte/column-pinning-split/src/makeData.ts @@ -0,0 +1,47 @@ +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((): Person => { + return { + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + } + }) + } + return makeDataLevel() +} diff --git a/examples/svelte/column-pinning-split/svelte.config.js b/examples/svelte/column-pinning-split/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/column-pinning-split/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/column-pinning-split/tsconfig.json b/examples/svelte/column-pinning-split/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/column-pinning-split/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/column-pinning-split/vite.config.js b/examples/svelte/column-pinning-split/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/column-pinning-split/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/column-pinning-sticky/.gitignore b/examples/svelte/column-pinning-sticky/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/column-pinning-sticky/index.html b/examples/svelte/column-pinning-sticky/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/column-pinning-sticky/package.json b/examples/svelte/column-pinning-sticky/package.json new file mode 100644 index 0000000000..6660dd8069 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-column-pinning-sticky", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/column-pinning-sticky/src/App.svelte b/examples/svelte/column-pinning-sticky/src/App.svelte new file mode 100644 index 0000000000..1c0e64d71e --- /dev/null +++ b/examples/svelte/column-pinning-sticky/src/App.svelte @@ -0,0 +1,246 @@ + + +
+
+
+ +
+ {#each table.getAllLeafColumns() as column} +
+ +
+ {/each} +
+
+
+ + +
+
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + {@const styles = getCommonPinningStyles(header.column)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getVisibleCells() as cell (cell.id)} + {@const styles = getCommonPinningStyles(cell.column)} + + {/each} + + {/each} + +
+
+ {#if !header.isPlaceholder} + + {' '} + {/if} + {header.column.getIndex(header.column.getIsPinned() || 'center')} +
+ {#if !header.isPlaceholder && header.column.getCanPin()} +
+ {#if header.column.getIsPinned() !== 'left'} + + {/if} + {#if header.column.getIsPinned()} + + {/if} + {#if header.column.getIsPinned() !== 'right'} + + {/if} +
+ {/if} + +
header.column.resetSize()} + onmousedown={header.getResizeHandler()} + ontouchstart={header.getResizeHandler()} + class="resizer {header.column.getIsResizing() ? 'isResizing' : ''}" + >
+
+ +
+
+
{JSON.stringify(table.state, null, 2)}
+
diff --git a/examples/svelte/column-pinning-sticky/src/index.css b/examples/svelte/column-pinning-sticky/src/index.css new file mode 100644 index 0000000000..799f30d2f4 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/src/index.css @@ -0,0 +1,49 @@ +html { + font-family: sans-serif; + font-size: 14px; +} + +.table-container { + border: 1px solid lightgray; + overflow-x: scroll; + width: 100%; + max-width: 960px; + position: relative; +} + +table { + border-collapse: separate !important; + border-spacing: 0; +} + +th { + background-color: lightgray; + border-bottom: 1px solid lightgray; + font-weight: bold; + height: 30px; + padding: 2px 4px; + position: relative; + text-align: center; +} + +td { + background-color: white; + padding: 2px 4px; +} + +.resizer { + background: rgba(0, 0, 0, 0.5); + cursor: col-resize; + height: 100%; + position: absolute; + right: 0; + top: 0; + touch-action: none; + user-select: none; + width: 5px; +} + +.resizer.isResizing { + background: blue; + opacity: 1; +} diff --git a/examples/svelte/column-pinning-sticky/src/main.ts b/examples/svelte/column-pinning-sticky/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/column-pinning-sticky/src/makeData.ts b/examples/svelte/column-pinning-sticky/src/makeData.ts new file mode 100644 index 0000000000..4f96799246 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/src/makeData.ts @@ -0,0 +1,47 @@ +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((): Person => { + return { + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + } + }) + } + return makeDataLevel() +} diff --git a/examples/svelte/column-pinning-sticky/svelte.config.js b/examples/svelte/column-pinning-sticky/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/column-pinning-sticky/tsconfig.json b/examples/svelte/column-pinning-sticky/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/column-pinning-sticky/vite.config.js b/examples/svelte/column-pinning-sticky/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/column-pinning-sticky/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/column-pinning/src/App.svelte b/examples/svelte/column-pinning/src/App.svelte index 70c02eb7bc..9800eaf3b4 100644 --- a/examples/svelte/column-pinning/src/App.svelte +++ b/examples/svelte/column-pinning/src/App.svelte @@ -127,10 +127,7 @@
{#if !header.isPlaceholder} - + {/if}
{#if !header.isPlaceholder && header.column.getCanPin()} @@ -226,23 +223,20 @@ {#if isSplit} - {#each table.getLeftHeaderGroups() as headerGroup} + {#each table.getLeftHeaderGroups() as headerGroup (headerGroup.id)} - {#each headerGroup.headers as header} + {#each headerGroup.headers as header (header.id)} {@render headerCell(header)} {/each} {/each} - {#each table.getCoreRowModel().rows.slice(0, 20) as row} + {#each table.getCoreRowModel().rows.slice(0, 20) as row (row.id)} - {#each row.getLeftVisibleCells() as cell} + {#each row.getLeftVisibleCells() as cell (cell.id)} {/each} @@ -252,23 +246,20 @@ {/if}
- +
- {#each isSplit ? table.getCenterHeaderGroups() : table.getHeaderGroups() as headerGroup} + {#each isSplit ? table.getCenterHeaderGroups() : table.getHeaderGroups() as headerGroup (headerGroup.id)} - {#each headerGroup.headers as header} + {#each headerGroup.headers as header (header.id)} {@render headerCell(header)} {/each} {/each} - {#each table.getCoreRowModel().rows.slice(0, 20) as row} + {#each table.getCoreRowModel().rows.slice(0, 20) as row (row.id)} - {#each isSplit ? row.getCenterVisibleCells() : row.getVisibleCells() as cell} + {#each isSplit ? row.getCenterVisibleCells() : row.getVisibleCells() as cell (cell.id)} {/each} @@ -278,23 +269,20 @@ {#if isSplit}
- +
- {#each table.getRightHeaderGroups() as headerGroup} + {#each table.getRightHeaderGroups() as headerGroup (headerGroup.id)} - {#each headerGroup.headers as header} + {#each headerGroup.headers as header (header.id)} {@render headerCell(header)} {/each} {/each} - {#each table.getRowModel().rows.slice(0, 20) as row} + {#each table.getRowModel().rows.slice(0, 20) as row (row.id)} - {#each row.getRightVisibleCells() as cell} + {#each row.getRightVisibleCells() as cell (cell.id)} {/each} diff --git a/examples/svelte/column-resizing-performant/.gitignore b/examples/svelte/column-resizing-performant/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/column-resizing-performant/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/column-resizing-performant/index.html b/examples/svelte/column-resizing-performant/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/column-resizing-performant/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/column-resizing-performant/package.json b/examples/svelte/column-resizing-performant/package.json new file mode 100644 index 0000000000..3aaa534c17 --- /dev/null +++ b/examples/svelte/column-resizing-performant/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-column-resizing-performant", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/column-resizing-performant/src/App.svelte b/examples/svelte/column-resizing-performant/src/App.svelte new file mode 100644 index 0000000000..952fb35523 --- /dev/null +++ b/examples/svelte/column-resizing-performant/src/App.svelte @@ -0,0 +1,163 @@ + + +
+ + This example has artificially slow cell renders to simulate complex usage + +
+
+    {JSON.stringify(table.store.state, null, 2)}
+  
+
+ ({data.length} rows) +
+
+
+ {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} +
+ {#each headerGroup.headers as header (header.id)} +
+ {#if !header.isPlaceholder} + + {/if} +
header.column.resetSize()} + onmousedown={header.getResizeHandler()} + ontouchstart={header.getResizeHandler()} + aria-hidden="true" + class="resizer {header.column.getIsResizing() + ? 'isResizing' + : ''}" + >
+
+ {/each} +
+ {/each} +
+
+ {#each table.getRowModel().rows as row (row.id)} +
+ {#each row.getAllCells() as cell (cell.id)} + {@const _ = (() => { + // simulate expensive render + for (const _i of Array.from({ length: 10000 })) { + Math.random() + } + })()} +
+ {cell.renderValue()} +
+ {/each} +
+ {/each} +
+
+
+
diff --git a/examples/svelte/column-resizing-performant/src/index.css b/examples/svelte/column-resizing-performant/src/index.css new file mode 100644 index 0000000000..e5ad2ab030 --- /dev/null +++ b/examples/svelte/column-resizing-performant/src/index.css @@ -0,0 +1,72 @@ +* { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + font-size: 14px; +} + +table, +.divTable { + border: 1px solid lightgray; + width: fit-content; +} + +.tr { + display: flex; +} + +tr, +.tr { + width: fit-content; + height: 30px; +} + +th, +.th, +td, +.td { + box-shadow: inset 0 0 0 1px lightgray; + padding: 0.25rem; +} + +th, +.th { + padding: 2px 4px; + position: relative; + font-weight: bold; + text-align: center; + height: 30px; +} + +td, +.td { + height: 30px; +} + +.resizer { + position: absolute; + top: 0; + height: 100%; + width: 5px; + background: rgba(0, 0, 0, 0.5); + cursor: col-resize; + user-select: none; + touch-action: none; +} + +.resizer.isResizing { + background: blue; + opacity: 1; +} + +@media (hover: hover) { + .resizer { + opacity: 0; + } + + *:hover > .resizer { + opacity: 1; + } +} diff --git a/examples/svelte/column-resizing-performant/src/main.ts b/examples/svelte/column-resizing-performant/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/column-resizing-performant/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/column-resizing-performant/src/makeData.ts b/examples/svelte/column-resizing-performant/src/makeData.ts new file mode 100644 index 0000000000..8675eacca6 --- /dev/null +++ b/examples/svelte/column-resizing-performant/src/makeData.ts @@ -0,0 +1,43 @@ +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 => ({ + 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( + (): Person => ({ + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + }), + ) + } + return makeDataLevel() +} diff --git a/examples/svelte/column-resizing-performant/svelte.config.js b/examples/svelte/column-resizing-performant/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/column-resizing-performant/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/column-resizing-performant/tsconfig.json b/examples/svelte/column-resizing-performant/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/column-resizing-performant/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/column-resizing-performant/vite.config.js b/examples/svelte/column-resizing-performant/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/column-resizing-performant/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/column-resizing/.gitignore b/examples/svelte/column-resizing/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/column-resizing/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/column-resizing/index.html b/examples/svelte/column-resizing/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/column-resizing/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/column-resizing/package.json b/examples/svelte/column-resizing/package.json new file mode 100644 index 0000000000..5a67e27942 --- /dev/null +++ b/examples/svelte/column-resizing/package.json @@ -0,0 +1,23 @@ +{ + "name": "tanstack-table-example-svelte-column-resizing", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/column-resizing/src/App.svelte b/examples/svelte/column-resizing/src/App.svelte new file mode 100644 index 0000000000..7f32c63b2c --- /dev/null +++ b/examples/svelte/column-resizing/src/App.svelte @@ -0,0 +1,300 @@ + + +
+ + +
+
+
{'
- +
'} +
+
+ + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + {/if} +
header.column.resetSize()} + onmousedown={header.getResizeHandler()} + ontouchstart={header.getResizeHandler()} + aria-hidden="true" + class="resizer {table.options + .columnResizeDirection} {header.column.getIsResizing() + ? 'isResizing' + : ''}" + style="transform: {resizerTransform(header)}" + >
+
+ +
+
+
+
{'
(relative)'}
+
+
+
+ {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} +
+ {#each headerGroup.headers as header (header.id)} +
+ {#if !header.isPlaceholder} + + {/if} +
header.column.resetSize()} + onmousedown={header.getResizeHandler()} + ontouchstart={header.getResizeHandler()} + aria-hidden="true" + class="resizer {table.options + .columnResizeDirection} {header.column.getIsResizing() + ? 'isResizing' + : ''}" + style="transform: {resizerTransform(header)}" + >
+
+ {/each} +
+ {/each} +
+
+ {#each table.getRowModel().rows as row (row.id)} +
+ {#each row.getAllCells() as cell (cell.id)} +
+ +
+ {/each} +
+ {/each} +
+
+
+
+
{'
(absolute positioning)'}
+
+
+
+ {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} +
+ {#each headerGroup.headers as header (header.id)} +
+ {#if !header.isPlaceholder} + + {/if} +
header.column.resetSize()} + onmousedown={header.getResizeHandler()} + ontouchstart={header.getResizeHandler()} + aria-hidden="true" + class="resizer {table.options + .columnResizeDirection} {header.column.getIsResizing() + ? 'isResizing' + : ''}" + style="transform: {resizerTransform(header)}" + >
+
+ {/each} +
+ {/each} +
+
+ {#each table.getRowModel().rows as row (row.id)} +
+ {#each row.getAllCells() as cell (cell.id)} +
+ +
+ {/each} +
+ {/each} +
+
+
+
+
+
{JSON.stringify(table.store.state, null, 2)}
+
diff --git a/examples/svelte/column-resizing/src/index.css b/examples/svelte/column-resizing/src/index.css new file mode 100644 index 0000000000..5a32330d58 --- /dev/null +++ b/examples/svelte/column-resizing/src/index.css @@ -0,0 +1,80 @@ +* { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + font-size: 14px; +} + +table, +.divTable { + border: 1px solid lightgray; + width: fit-content; +} + +.tr { + display: flex; +} + +tr, +.tr { + width: fit-content; + height: 30px; +} + +th, +.th, +td, +.td { + box-shadow: inset 0 0 0 1px lightgray; + padding: 0.25rem; +} + +th, +.th { + padding: 2px 4px; + position: relative; + font-weight: bold; + text-align: center; + height: 30px; +} + +td, +.td { + height: 30px; +} + +.resizer { + position: absolute; + top: 0; + height: 100%; + width: 5px; + background: rgba(0, 0, 0, 0.5); + cursor: col-resize; + user-select: none; + touch-action: none; +} + +.resizer.ltr { + right: 0; +} + +.resizer.rtl { + left: 0; +} + +.resizer.isResizing { + background: blue; + opacity: 1; +} + +@media (hover: hover) { + .resizer { + opacity: 0; + } + + *:hover > .resizer { + opacity: 1; + } +} diff --git a/examples/svelte/column-resizing/src/main.ts b/examples/svelte/column-resizing/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/column-resizing/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/column-resizing/svelte.config.js b/examples/svelte/column-resizing/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/column-resizing/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/column-resizing/tsconfig.json b/examples/svelte/column-resizing/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/column-resizing/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/column-resizing/vite.config.js b/examples/svelte/column-resizing/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/column-resizing/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/column-sizing/.gitignore b/examples/svelte/column-sizing/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/column-sizing/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/column-sizing/index.html b/examples/svelte/column-sizing/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/column-sizing/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/basic/package.json b/examples/svelte/column-sizing/package.json similarity index 90% rename from examples/svelte/basic/package.json rename to examples/svelte/column-sizing/package.json index b0cf8a287d..a48f8c8649 100644 --- a/examples/svelte/basic/package.json +++ b/examples/svelte/column-sizing/package.json @@ -1,5 +1,5 @@ { - "name": "tanstack-table-example-svelte-basic", + "name": "tanstack-table-example-svelte-column-sizing", "version": "0.0.0", "private": true, "type": "module", diff --git a/examples/svelte/column-sizing/src/App.svelte b/examples/svelte/column-sizing/src/App.svelte new file mode 100644 index 0000000000..efbba84ab9 --- /dev/null +++ b/examples/svelte/column-sizing/src/App.svelte @@ -0,0 +1,232 @@ + + +
+
+
Initial Column Sizes
+
+ {#each table.getAllColumns() as column} +
+ +
+ {/each} +
+
+
+
{''} +
+
+ + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + {/if} +
+
+ +
+
+
+
{'
(relative)'}
+
+
+
+ {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} +
+ {#each headerGroup.headers as header (header.id)} +
+ {#if !header.isPlaceholder} + + {/if} +
+
+ {/each} +
+ {/each} +
+
+ {#each table.getRowModel().rows as row (row.id)} +
+ {#each row.getAllCells() as cell (cell.id)} +
+ +
+ {/each} +
+ {/each} +
+
+
+
+
{'
(absolute positioning)'}
+
+
+
+ {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} +
+ {#each headerGroup.headers as header (header.id)} +
+ {#if !header.isPlaceholder} + + {/if} +
+
+ {/each} +
+ {/each} +
+
+ {#each table.getRowModel().rows as row (row.id)} +
+ {#each row.getAllCells() as cell (cell.id)} +
+ +
+ {/each} +
+ {/each} +
+
+
+
+
{JSON.stringify(table.store.state, null, 2)}
+
diff --git a/examples/svelte/column-sizing/src/index.css b/examples/svelte/column-sizing/src/index.css new file mode 100644 index 0000000000..6087a129fd --- /dev/null +++ b/examples/svelte/column-sizing/src/index.css @@ -0,0 +1,57 @@ +html { + font-family: sans-serif; + font-size: 14px; +} + +table, +.divTable { + 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; +} + +.tr { + display: flex; +} + +tr, +.tr { + width: fit-content; + height: 30px; +} + +th, +.th, +td, +.td { + box-shadow: inset 0 0 0 1px lightgray; + padding: 0.25rem; +} + +.th { + padding: 2px 4px; + position: relative; + font-weight: bold; + text-align: center; + height: 30px; +} + +.td { + height: 30px; +} diff --git a/examples/svelte/column-sizing/src/main.ts b/examples/svelte/column-sizing/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/column-sizing/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/column-sizing/svelte.config.js b/examples/svelte/column-sizing/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/column-sizing/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/column-sizing/tsconfig.json b/examples/svelte/column-sizing/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/column-sizing/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/column-sizing/vite.config.js b/examples/svelte/column-sizing/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/column-sizing/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/column-visibility/src/App.svelte b/examples/svelte/column-visibility/src/App.svelte index 11e36b13c6..8a4a43865d 100644 --- a/examples/svelte/column-visibility/src/App.svelte +++ b/examples/svelte/column-visibility/src/App.svelte @@ -156,15 +156,12 @@
- {#each table.getHeaderGroups() as headerGroup} + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} - {#each headerGroup.headers as header} + {#each headerGroup.headers as header (header.id)} {/each} @@ -172,29 +169,23 @@ {/each} - {#each table.getCoreRowModel().rows.slice(0, 20) as row} + {#each table.getCoreRowModel().rows.slice(0, 20) as row (row.id)} - {#each row.getVisibleCells() as cell} + {#each row.getVisibleCells() as cell (cell.id)} {/each} {/each} - {#each table.getFooterGroups() as footerGroup} + {#each table.getFooterGroups() as footerGroup (footerGroup.id)} - {#each footerGroup.headers as header} + {#each footerGroup.headers as header (header.id)} {/each} diff --git a/examples/svelte/composable-tables/.gitignore b/examples/svelte/composable-tables/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/composable-tables/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/composable-tables/index.html b/examples/svelte/composable-tables/index.html new file mode 100644 index 0000000000..29f9ba886c --- /dev/null +++ b/examples/svelte/composable-tables/index.html @@ -0,0 +1,13 @@ + + + + + + Svelte Composable Tables Example + + + +
+ + + diff --git a/examples/svelte/composable-tables/package.json b/examples/svelte/composable-tables/package.json new file mode 100644 index 0000000000..150095a24c --- /dev/null +++ b/examples/svelte/composable-tables/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-composable-tables", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/composable-tables/src/App.svelte b/examples/svelte/composable-tables/src/App.svelte new file mode 100644 index 0000000000..959c23e6d6 --- /dev/null +++ b/examples/svelte/composable-tables/src/App.svelte @@ -0,0 +1,22 @@ + + +
+

Composable Tables Example

+

+ Both tables below use the same createAppTable hook and + shareable components, but with different data types and column + configurations. +

+ + + + +
+ + + +
diff --git a/examples/svelte/composable-tables/src/components/CategoryCell.svelte b/examples/svelte/composable-tables/src/components/CategoryCell.svelte new file mode 100644 index 0000000000..573d15a14e --- /dev/null +++ b/examples/svelte/composable-tables/src/components/CategoryCell.svelte @@ -0,0 +1,11 @@ + + + +{cell.getValue()} diff --git a/examples/svelte/composable-tables/src/components/ColumnFilter.svelte b/examples/svelte/composable-tables/src/components/ColumnFilter.svelte new file mode 100644 index 0000000000..fa576cc879 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/ColumnFilter.svelte @@ -0,0 +1,22 @@ + + + +{#if header.column.getCanFilter()} + + +
e.stopPropagation()}> + header.column.setFilterValue(e.currentTarget.value)} + placeholder="Filter {header.column.id}..." + /> +
+{/if} diff --git a/examples/svelte/composable-tables/src/components/FooterColumnId.svelte b/examples/svelte/composable-tables/src/components/FooterColumnId.svelte new file mode 100644 index 0000000000..aa17e2761b --- /dev/null +++ b/examples/svelte/composable-tables/src/components/FooterColumnId.svelte @@ -0,0 +1,11 @@ + + + +{header.column.id} diff --git a/examples/svelte/composable-tables/src/components/FooterSum.svelte b/examples/svelte/composable-tables/src/components/FooterSum.svelte new file mode 100644 index 0000000000..1c68cbbe64 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/FooterSum.svelte @@ -0,0 +1,19 @@ + + + +{sum > 0 ? sum.toLocaleString() : '—'} diff --git a/examples/svelte/composable-tables/src/components/NumberCell.svelte b/examples/svelte/composable-tables/src/components/NumberCell.svelte new file mode 100644 index 0000000000..96b18adca0 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/NumberCell.svelte @@ -0,0 +1,11 @@ + + + +{cell.getValue().toLocaleString()} diff --git a/examples/svelte/composable-tables/src/components/PaginationControls.svelte b/examples/svelte/composable-tables/src/components/PaginationControls.svelte new file mode 100644 index 0000000000..4c8f2891b8 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/PaginationControls.svelte @@ -0,0 +1,65 @@ + + + + diff --git a/examples/svelte/composable-tables/src/components/PriceCell.svelte b/examples/svelte/composable-tables/src/components/PriceCell.svelte new file mode 100644 index 0000000000..4d771a41da --- /dev/null +++ b/examples/svelte/composable-tables/src/components/PriceCell.svelte @@ -0,0 +1,16 @@ + + + + + ${cell.getValue().toLocaleString(undefined, { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + })} + diff --git a/examples/svelte/composable-tables/src/components/ProductsTable.svelte b/examples/svelte/composable-tables/src/components/ProductsTable.svelte new file mode 100644 index 0000000000..faa84dee37 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/ProductsTable.svelte @@ -0,0 +1,162 @@ + + + + +
+ + + + +
{#if !header.isPlaceholder} - + {/if}
- +
{#if !header.isPlaceholder} - + {/if}
+ + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as h (h.id)} + + {#snippet children(header)} + + {/snippet} + + {/each} + + {/each} + + + {#each rows as row (row.id)} + + {#each row.getAllCells() as c (c.id)} + + {#snippet children(cell)} + + {/snippet} + + {/each} + + {/each} + + + {#each table.getFooterGroups() as footerGroup (footerGroup.id)} + + {#each footerGroup.headers as f (f.id)} + + {#snippet children(footer)} + + {/snippet} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + + + + {#if sorting.length > 1 && sorting.findIndex((s) => s.id === header.column.id) > -1} + + {sorting.findIndex((s) => s.id === header.column.id) + 1} + + {/if} + {/if} +
+ +
+ {#if !footer.isPlaceholder} + {#if footer.column.id === 'price' || footer.column.id === 'stock' || footer.column.id === 'rating'} + + {#if columnFilters.some((cf) => cf.id === footer.column.id)} + (filtered) + {/if} + {:else} + + {#if columnFilters.some((cf) => cf.id === footer.column.id)} + + {/if} + {/if} + {/if} +
+ + + + + + +
+ diff --git a/examples/svelte/composable-tables/src/components/ProgressCell.svelte b/examples/svelte/composable-tables/src/components/ProgressCell.svelte new file mode 100644 index 0000000000..1b50bff136 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/ProgressCell.svelte @@ -0,0 +1,13 @@ + + + +
+
+
diff --git a/examples/svelte/composable-tables/src/components/RowActionsCell.svelte b/examples/svelte/composable-tables/src/components/RowActionsCell.svelte new file mode 100644 index 0000000000..87b70baa1a --- /dev/null +++ b/examples/svelte/composable-tables/src/components/RowActionsCell.svelte @@ -0,0 +1,30 @@ + + + +
+ + + +
diff --git a/examples/svelte/composable-tables/src/components/RowCount.svelte b/examples/svelte/composable-tables/src/components/RowCount.svelte new file mode 100644 index 0000000000..0bc00e5fdc --- /dev/null +++ b/examples/svelte/composable-tables/src/components/RowCount.svelte @@ -0,0 +1,13 @@ + + + +
+ Showing {table.getRowModel().rows.length.toLocaleString()} of {table.getRowCount().toLocaleString()} rows +
diff --git a/examples/svelte/composable-tables/src/components/SortIndicator.svelte b/examples/svelte/composable-tables/src/components/SortIndicator.svelte new file mode 100644 index 0000000000..5bc7d031ed --- /dev/null +++ b/examples/svelte/composable-tables/src/components/SortIndicator.svelte @@ -0,0 +1,15 @@ + + + +{#if header.column.getIsSorted()} + + {header.column.getIsSorted() === 'asc' ? '🔼' : '🔽'} + +{/if} diff --git a/examples/svelte/composable-tables/src/components/StatusCell.svelte b/examples/svelte/composable-tables/src/components/StatusCell.svelte new file mode 100644 index 0000000000..eafb524662 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/StatusCell.svelte @@ -0,0 +1,11 @@ + + + +{cell.getValue()} diff --git a/examples/svelte/composable-tables/src/components/TableToolbar.svelte b/examples/svelte/composable-tables/src/components/TableToolbar.svelte new file mode 100644 index 0000000000..e328d77686 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/TableToolbar.svelte @@ -0,0 +1,31 @@ + + + +
+

{title}

+
+ + + {#if onRefresh} + + {/if} +
+
diff --git a/examples/svelte/composable-tables/src/components/TextCell.svelte b/examples/svelte/composable-tables/src/components/TextCell.svelte new file mode 100644 index 0000000000..1ced128ee5 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/TextCell.svelte @@ -0,0 +1,11 @@ + + + +{cell.getValue()} diff --git a/examples/svelte/composable-tables/src/components/UsersTable.svelte b/examples/svelte/composable-tables/src/components/UsersTable.svelte new file mode 100644 index 0000000000..b8ae4b9849 --- /dev/null +++ b/examples/svelte/composable-tables/src/components/UsersTable.svelte @@ -0,0 +1,176 @@ + + + + +
+ + + + + + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as h (h.id)} + + {#snippet children(header)} + + {/snippet} + + {/each} + + {/each} + + + {#each rows as row (row.id)} + + {#each row.getAllCells() as c (c.id)} + + {#snippet children(cell)} + + {/snippet} + + {/each} + + {/each} + + + {#each table.getFooterGroups() as footerGroup (footerGroup.id)} + + {#each footerGroup.headers as f (f.id)} + + {#snippet children(footer)} + + {/snippet} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + + + + {#if sorting.length > 1 && sorting.findIndex((s) => s.id === header.column.id) > -1} + + {sorting.findIndex((s) => s.id === header.column.id) + 1} + + {/if} + {/if} +
+ +
+ {#if !footer.isPlaceholder} + {#if footer.column.id === 'age' || footer.column.id === 'visits' || footer.column.id === 'progress'} + + {#if columnFilters.some((cf) => cf.id === footer.column.id)} + (filtered) + {/if} + {:else if footer.column.id === 'actions'} + + {:else} + + {#if columnFilters.some((cf) => cf.id === footer.column.id)} + + {/if} + {/if} + {/if} +
+ + + + + + +
+
diff --git a/examples/svelte/composable-tables/src/hooks/table.ts b/examples/svelte/composable-tables/src/hooks/table.ts new file mode 100644 index 0000000000..71ad486cf5 --- /dev/null +++ b/examples/svelte/composable-tables/src/hooks/table.ts @@ -0,0 +1,99 @@ +/** + * Custom table hook setup using createTableHook + * + * This file creates a custom createAppTable hook with pre-bound components. + * Features, row models, and default options are defined once here and shared across all tables. + * Context hooks and a pre-bound createAppColumnHelper are also exported. + */ +import { + columnFilteringFeature, + createFilteredRowModel, + createPaginatedRowModel, + createSortedRowModel, + createTableHook, + filterFns, + rowPaginationFeature, + rowSortingFeature, + sortFns, + tableFeatures, +} from '@tanstack/svelte-table' + +// Import table-level components +import PaginationControls from '../components/PaginationControls.svelte' +import RowCount from '../components/RowCount.svelte' +import TableToolbar from '../components/TableToolbar.svelte' + +// Import cell-level components +import CategoryCell from '../components/CategoryCell.svelte' +import NumberCell from '../components/NumberCell.svelte' +import PriceCell from '../components/PriceCell.svelte' +import ProgressCell from '../components/ProgressCell.svelte' +import RowActionsCell from '../components/RowActionsCell.svelte' +import StatusCell from '../components/StatusCell.svelte' +import TextCell from '../components/TextCell.svelte' + +// Import header/footer-level components (both use useHeaderContext) +import ColumnFilter from '../components/ColumnFilter.svelte' +import FooterColumnId from '../components/FooterColumnId.svelte' +import FooterSum from '../components/FooterSum.svelte' +import SortIndicator from '../components/SortIndicator.svelte' + +/** + * Create the custom table hook with all pre-bound components. + * This exports: + * - createAppColumnHelper: Create column definitions with TFeatures already bound + * - createAppTable: Hook for creating tables with TFeatures baked in + * - useTableContext: Access table instance in tableComponents + * - useCellContext: Access cell instance in cellComponents + * - useHeaderContext: Access header instance in headerComponents + */ +export const { + createAppColumnHelper, + createAppTable, + useTableContext, + useCellContext, + useHeaderContext, +} = createTableHook({ + // Features are set once here and shared across all tables + _features: tableFeatures({ + columnFilteringFeature, + rowPaginationFeature, + rowSortingFeature, + }), + + // Row models are set once here + _rowModels: { + sortedRowModel: createSortedRowModel(sortFns), + filteredRowModel: createFilteredRowModel(filterFns), + paginatedRowModel: createPaginatedRowModel(), + }, + + // set any default table options here too + getRowId: (row) => row.id, + + // Register table-level components (accessible via table.ComponentName) + tableComponents: { + PaginationControls, + RowCount, + TableToolbar, + }, + + // Register cell-level components (accessible via cell.ComponentName in AppCell) + cellComponents: { + TextCell, + NumberCell, + StatusCell, + ProgressCell, + RowActionsCell, + PriceCell, + CategoryCell, + }, + + // Register header/footer-level components (accessible via header.ComponentName in AppHeader/AppFooter) + headerComponents: { + SortIndicator, + ColumnFilter, + FooterColumnId, + FooterSum, + }, +}) diff --git a/examples/svelte/composable-tables/src/index.css b/examples/svelte/composable-tables/src/index.css new file mode 100644 index 0000000000..d7a5ed6c49 --- /dev/null +++ b/examples/svelte/composable-tables/src/index.css @@ -0,0 +1,249 @@ +html { + font-family: sans-serif; + font-size: 14px; +} + +table { + border: 1px solid lightgray; + border-collapse: collapse; + width: 100%; +} + +tbody { + border-bottom: 1px solid lightgray; +} + +th, +td { + border-bottom: 1px solid lightgray; + border-right: 1px solid lightgray; + padding: 8px 12px; + text-align: left; +} + +th { + background-color: #f5f5f5; + font-weight: 600; +} + +tfoot { + color: gray; +} + +tfoot th { + font-weight: normal; +} + +.table-container { + padding: 16px; + max-width: 1200px; + margin: 0 auto; +} + +.pagination { + display: flex; + align-items: center; + gap: 8px; + margin-top: 16px; + flex-wrap: wrap; +} + +.pagination button { + border: 1px solid #ccc; + border-radius: 4px; + padding: 4px 8px; + cursor: pointer; + background: white; +} + +.pagination button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.pagination input { + border: 1px solid #ccc; + border-radius: 4px; + padding: 4px; + width: 64px; +} + +.pagination select { + border: 1px solid #ccc; + border-radius: 4px; + padding: 4px; +} + +.sort-indicator { + margin-left: 4px; +} + +.column-filter { + margin-top: 4px; +} + +.column-filter input { + border: 1px solid #ccc; + border-radius: 4px; + padding: 4px; + width: 100%; + font-size: 12px; +} + +.sortable-header { + cursor: pointer; + user-select: none; +} + +.sortable-header:hover { + background-color: #e8e8e8; +} + +.row-actions { + display: flex; + gap: 4px; +} + +.row-actions button { + border: 1px solid #ccc; + border-radius: 4px; + padding: 2px 8px; + cursor: pointer; + background: white; + font-size: 12px; +} + +.row-actions button:hover { + background-color: #f0f0f0; +} + +.status-badge { + display: inline-block; + padding: 2px 8px; + border-radius: 12px; + font-size: 12px; + font-weight: 500; +} + +.status-badge.relationship { + background-color: #d4edda; + color: #155724; +} + +.status-badge.complicated { + background-color: #fff3cd; + color: #856404; +} + +.status-badge.single { + background-color: #cce5ff; + color: #004085; +} + +.progress-bar { + width: 100%; + height: 8px; + background-color: #e9ecef; + border-radius: 4px; + overflow: hidden; +} + +.progress-bar-fill { + height: 100%; + background-color: #007bff; + transition: width 0.2s; +} + +.table-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + flex-wrap: wrap; + gap: 8px; +} + +.table-toolbar h2 { + margin: 0; +} + +.table-toolbar button { + border: 1px solid #ccc; + border-radius: 4px; + padding: 8px 16px; + cursor: pointer; + background: white; +} + +.table-toolbar button:hover { + background-color: #f0f0f0; +} + +.row-count { + color: #666; + font-size: 14px; + margin-top: 8px; +} + +.app { + padding: 16px; +} + +.app h1 { + text-align: center; + margin-bottom: 8px; +} + +.description { + text-align: center; + color: #666; + margin-bottom: 32px; +} + +.description code { + background-color: #f5f5f5; + padding: 2px 6px; + border-radius: 4px; + font-size: 13px; +} + +.table-divider { + height: 48px; + border-bottom: 1px solid #e0e0e0; + margin: 32px auto; + max-width: 1200px; +} + +.category-badge { + display: inline-block; + padding: 2px 8px; + border-radius: 12px; + font-size: 12px; + font-weight: 500; + text-transform: capitalize; +} + +.category-badge.electronics { + background-color: #e3f2fd; + color: #1565c0; +} + +.category-badge.clothing { + background-color: #fce4ec; + color: #c2185b; +} + +.category-badge.food { + background-color: #e8f5e9; + color: #2e7d32; +} + +.category-badge.books { + background-color: #fff8e1; + color: #f57c00; +} + +.price { + font-weight: 600; + color: #2e7d32; +} diff --git a/examples/svelte/composable-tables/src/main.ts b/examples/svelte/composable-tables/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/composable-tables/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/composable-tables/src/makeData.ts b/examples/svelte/composable-tables/src/makeData.ts new file mode 100644 index 0000000000..17dec1c6de --- /dev/null +++ b/examples/svelte/composable-tables/src/makeData.ts @@ -0,0 +1,77 @@ +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 +} + +export type Product = { + id: string + name: string + category: 'electronics' | 'clothing' | 'food' | 'books' + price: number + stock: number + rating: number +} + +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], + } +} + +const newProduct = (): Product => { + return { + id: faker.string.uuid(), + name: faker.commerce.productName(), + category: faker.helpers.shuffle([ + 'electronics', + 'clothing', + 'food', + 'books', + ])[0], + price: parseFloat(faker.commerce.price({ min: 5, max: 500 })), + stock: faker.number.int({ min: 0, max: 200 }), + rating: faker.number.int({ min: 0, max: 100 }), + } +} + +export function makeData(...lens: Array) { + const makeDataLevel = (depth = 0): Array => { + const len = lens[depth] + return range(len).map((): Person => { + return { + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + } + }) + } + + return makeDataLevel() +} + +export function makeProductData(count: number): Array { + return range(count).map(() => newProduct()) +} diff --git a/examples/svelte/composable-tables/svelte.config.js b/examples/svelte/composable-tables/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/composable-tables/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/composable-tables/tsconfig.json b/examples/svelte/composable-tables/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/composable-tables/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/composable-tables/vite.config.js b/examples/svelte/composable-tables/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/composable-tables/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/expanding/.gitignore b/examples/svelte/expanding/.gitignore new file mode 100644 index 0000000000..91c18232e2 --- /dev/null +++ b/examples/svelte/expanding/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map \ No newline at end of file diff --git a/examples/svelte/expanding/index.html b/examples/svelte/expanding/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/expanding/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/expanding/package.json b/examples/svelte/expanding/package.json new file mode 100644 index 0000000000..53b1263fbc --- /dev/null +++ b/examples/svelte/expanding/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-expanding", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/expanding/src/App.svelte b/examples/svelte/expanding/src/App.svelte new file mode 100644 index 0000000000..ffbd3ac9b3 --- /dev/null +++ b/examples/svelte/expanding/src/App.svelte @@ -0,0 +1,296 @@ + + +
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} +
+ {#if header.id === 'firstName'} + + {' '} + + {' '} + First Name + {:else} + + {/if} + {#if header.column.getCanFilter()} +
+ {@render Filter(header.column, table)} +
+ {/if} +
+ {/if} +
+ {#if cell.column.id === 'firstName'} +
+
+ + {' '} + {#if row.getCanExpand()} + + {:else} + {'\u{1F535}'} + {/if} + {' '} + +
+
+ {:else} + + {/if} +
+
+
+ + + + + +
Page
+ + {table.state.pagination.pageIndex + 1} of{' '} + {table.getPageCount()} + +
+ + | Go to page: + { + const page = (e.target as HTMLInputElement).value + ? Number((e.target as HTMLInputElement).value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
{table.getRowModel().rows.length} Rows
+
+ +
+
{JSON.stringify(table.state, null, 2)}
+
+ +{#snippet Filter(column: Column, table: SvelteTable)} + {@const firstValue = table + .getPreFilteredRowModel() + .flatRows[0]?.getValue(column.id)} + + {#if typeof firstValue === 'number'} +
+ + column.setFilterValue((old: [number, number] | undefined) => [ + (e.target as HTMLInputElement).value, + old?.[1], + ]) + } + placeholder="Min" + class="w-24 border shadow rounded" + /> + + column.setFilterValue((old: [number, number] | undefined) => [ + old?.[0], + (e.target as HTMLInputElement).value, + ]) + } + placeholder="Max" + class="w-24 border shadow rounded" + /> +
+ {:else} + column.setFilterValue((e.target as HTMLInputElement).value)} + placeholder="Search..." + class="w-36 border shadow rounded" + /> + {/if} +{/snippet} diff --git a/examples/svelte/expanding/src/index.css b/examples/svelte/expanding/src/index.css new file mode 100644 index 0000000000..12d71033f0 --- /dev/null +++ b/examples/svelte/expanding/src/index.css @@ -0,0 +1,21 @@ +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/svelte/expanding/src/main.ts b/examples/svelte/expanding/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/expanding/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/expanding/src/makeData.ts b/examples/svelte/expanding/src/makeData.ts new file mode 100644 index 0000000000..8675eacca6 --- /dev/null +++ b/examples/svelte/expanding/src/makeData.ts @@ -0,0 +1,43 @@ +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 => ({ + 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( + (): Person => ({ + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + }), + ) + } + return makeDataLevel() +} diff --git a/examples/svelte/expanding/svelte.config.js b/examples/svelte/expanding/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/expanding/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/expanding/tsconfig.json b/examples/svelte/expanding/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/expanding/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/expanding/vite.config.js b/examples/svelte/expanding/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/expanding/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/filtering/package.json b/examples/svelte/filtering/package.json index 913643cf56..df28dba0fa 100644 --- a/examples/svelte/filtering/package.json +++ b/examples/svelte/filtering/package.json @@ -14,7 +14,6 @@ "@faker-js/faker": "^10.4.0", "@rollup/plugin-replace": "^6.0.3", "@sveltejs/vite-plugin-svelte": "^7.0.0", - "@tanstack/match-sorter-utils": "^9.0.0-alpha.4", "@tanstack/svelte-table": "^9.0.0-alpha.10", "@tsconfig/svelte": "^5.0.8", "svelte": "^5.55.1", diff --git a/examples/svelte/filtering/src/App.svelte b/examples/svelte/filtering/src/App.svelte index 1bbe66ed0a..5c830cb987 100644 --- a/examples/svelte/filtering/src/App.svelte +++ b/examples/svelte/filtering/src/App.svelte @@ -1,118 +1,158 @@ - table.setGlobalFilter(e.target.value)} -/> -
- - - {#each table.getHeaderGroups() as headerGroup} - - {#each headerGroup.headers as header, idx} - - {/each} - - {/each} - - - {#each table.getRowModel().rows as row} - - {#each row.getVisibleCells() as cell} - - {/each} - - {/each} - -
- {#if !header.isPlaceholder} - - {/if} -
- -
-
-
"globalFilter": "{table.state.globalFilter}"
+
+ table.setGlobalFilter(String(value))} + class="p-2 font-lg shadow border border-block" + placeholder="Search all columns..." + /> +
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows.slice(0, 10) as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + {#if header.column.getCanFilter()} +
+ +
+ {/if} + {/if} +
+ +
+
{table.getRowModel().rows.length} Rows
+
+ +
+ state} {table}> + {#snippet children(state)} +
{JSON.stringify(state, null, 2)}
+ {/snippet} +
+
diff --git a/examples/svelte/filtering/src/ColumnFilter.svelte b/examples/svelte/filtering/src/ColumnFilter.svelte new file mode 100644 index 0000000000..7878c63591 --- /dev/null +++ b/examples/svelte/filtering/src/ColumnFilter.svelte @@ -0,0 +1,68 @@ + + +{#if isNumber} +
+
+ + column.setFilterValue((old: [number, number] | undefined) => [ + value, + old?.[1] ?? '', + ]) + } + debounce={500} + placeholder="Min" + class="w-24 border shadow rounded" + /> + + column.setFilterValue((old: [number, number] | undefined) => [ + old?.[0] ?? '', + value, + ]) + } + debounce={500} + placeholder="Max" + class="w-24 border shadow rounded" + /> +
+
+{:else} +
+ column.setFilterValue(value)} + debounce={500} + placeholder="Search..." + class="w-36 border shadow rounded" + list="{column.id}list" + /> +
+{/if} diff --git a/examples/svelte/filtering/src/DebouncedInput.svelte b/examples/svelte/filtering/src/DebouncedInput.svelte new file mode 100644 index 0000000000..75e9c11427 --- /dev/null +++ b/examples/svelte/filtering/src/DebouncedInput.svelte @@ -0,0 +1,29 @@ + + + diff --git a/examples/svelte/filtering/src/main.ts b/examples/svelte/filtering/src/main.ts index 3b96aeccb8..2f4dd54dc3 100644 --- a/examples/svelte/filtering/src/main.ts +++ b/examples/svelte/filtering/src/main.ts @@ -1,17 +1,6 @@ // @ts-ignore import { mount } from 'svelte' import App from './App.svelte' -import type { FilterFn } from '@tanstack/svelte-table' -import type { RankingInfo } from '@tanstack/match-sorter-utils' - -declare module '@tanstack/svelte-table' { - interface FilterFns { - fuzzy: FilterFn - } - interface FilterMeta { - itemRank: RankingInfo - } -} const app = mount(App, { target: document.getElementById('root')!, diff --git a/examples/svelte/filters-faceted/.gitignore b/examples/svelte/filters-faceted/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/filters-faceted/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/filters-faceted/README.md b/examples/svelte/filters-faceted/README.md new file mode 100644 index 0000000000..b168d3c4b1 --- /dev/null +++ b/examples/svelte/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/svelte/filters-faceted/index.html b/examples/svelte/filters-faceted/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/filters-faceted/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/filters-faceted/package.json b/examples/svelte/filters-faceted/package.json new file mode 100644 index 0000000000..edaa44cb9e --- /dev/null +++ b/examples/svelte/filters-faceted/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-filters-faceted", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/filters-faceted/src/App.svelte b/examples/svelte/filters-faceted/src/App.svelte new file mode 100644 index 0000000000..0dfe3a083a --- /dev/null +++ b/examples/svelte/filters-faceted/src/App.svelte @@ -0,0 +1,155 @@ + + +
+ table.setGlobalFilter(String(value))} + class="p-2 font-lg shadow border border-block" + placeholder="Search all columns..." + /> +
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows.slice(0, 10) as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + {#if header.column.getCanFilter()} +
+ +
+ {/if} + {/if} +
+ +
+
{table.getRowModel().rows.length} Rows
+
+ +
+ state} {table}> + {#snippet children(state)} +
{JSON.stringify(state, null, 2)}
+ {/snippet} +
+
diff --git a/examples/svelte/filters-faceted/src/ColumnFilter.svelte b/examples/svelte/filters-faceted/src/ColumnFilter.svelte new file mode 100644 index 0000000000..52bb1101af --- /dev/null +++ b/examples/svelte/filters-faceted/src/ColumnFilter.svelte @@ -0,0 +1,78 @@ + + +{#if isNumber} +
+
+ + column.setFilterValue((old: [number, number]) => [ + value, + old?.[1], + ]) + } + debounce={500} + placeholder={`Min ${column.getFacetedMinMaxValues()?.[0] ? `(${column.getFacetedMinMaxValues()?.[0]})` : ''}`} + class="w-24 border shadow rounded" + /> + + column.setFilterValue((old: [number, number]) => [ + old?.[0], + value, + ]) + } + debounce={500} + placeholder={`Max ${column.getFacetedMinMaxValues()?.[1] ? `(${column.getFacetedMinMaxValues()?.[1]})` : ''}`} + class="w-24 border shadow rounded" + /> +
+
+{:else} +
+ + {#each getSortedUniqueValues().slice(0, 5000) as value} + + {/each} + + column.setFilterValue(value)} + debounce={500} + placeholder={`Search... (${column.getFacetedUniqueValues().size})`} + class="w-36 border shadow rounded" + list="{column.id}list" + /> +
+{/if} diff --git a/examples/svelte/filters-faceted/src/DebouncedInput.svelte b/examples/svelte/filters-faceted/src/DebouncedInput.svelte new file mode 100644 index 0000000000..75e9c11427 --- /dev/null +++ b/examples/svelte/filters-faceted/src/DebouncedInput.svelte @@ -0,0 +1,29 @@ + + + diff --git a/examples/svelte/filters-faceted/src/index.css b/examples/svelte/filters-faceted/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/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/svelte/filters-faceted/src/main.ts b/examples/svelte/filters-faceted/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/filters-faceted/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/filters-faceted/src/makeData.ts b/examples/svelte/filters-faceted/src/makeData.ts new file mode 100644 index 0000000000..b9fb014aba --- /dev/null +++ b/examples/svelte/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/svelte/filters-faceted/svelte.config.js b/examples/svelte/filters-faceted/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/filters-faceted/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/filters-faceted/tsconfig.json b/examples/svelte/filters-faceted/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/filters-faceted/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/filters-faceted/vite.config.js b/examples/svelte/filters-faceted/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/filters-faceted/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/filters-fuzzy/.gitignore b/examples/svelte/filters-fuzzy/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/filters-fuzzy/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/filters-fuzzy/README.md b/examples/svelte/filters-fuzzy/README.md new file mode 100644 index 0000000000..b168d3c4b1 --- /dev/null +++ b/examples/svelte/filters-fuzzy/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/svelte/filters-fuzzy/index.html b/examples/svelte/filters-fuzzy/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/filters-fuzzy/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/filters-fuzzy/package.json b/examples/svelte/filters-fuzzy/package.json new file mode 100644 index 0000000000..3f10191673 --- /dev/null +++ b/examples/svelte/filters-fuzzy/package.json @@ -0,0 +1,25 @@ +{ + "name": "tanstack-table-example-svelte-filters-fuzzy", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/match-sorter-utils": "^9.0.0-alpha.4", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/filters-fuzzy/src/App.svelte b/examples/svelte/filters-fuzzy/src/App.svelte new file mode 100644 index 0000000000..c6a41c28c4 --- /dev/null +++ b/examples/svelte/filters-fuzzy/src/App.svelte @@ -0,0 +1,255 @@ + + +
+
+ table.setGlobalFilter(String(value))} + class="p-2 font-lg shadow border border-block" + placeholder="Search all columns..." + /> +
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} +
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} +
+ {#if header.column.getCanFilter()} +
+ header.column.setFilterValue(value)} + placeholder="Search..." + class="w-36 border shadow rounded" + /> +
+ {/if} + {/if} +
+ +
+
+
+ + + + + +
Page
+ + {table.state.pagination.pageIndex + 1} of{' '} + {table.getPageCount()} + +
+ + | Go to page: + { + const page = e.currentTarget.value + ? Number(e.currentTarget.value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
{table.getPrePaginatedRowModel().rows.length} Rows
+
+ +
+ state} {table}> + {#snippet children(state)} +
{JSON.stringify(state, null, 2)}
+ {/snippet} +
+
diff --git a/examples/svelte/filters-fuzzy/src/DebouncedInput.svelte b/examples/svelte/filters-fuzzy/src/DebouncedInput.svelte new file mode 100644 index 0000000000..75e9c11427 --- /dev/null +++ b/examples/svelte/filters-fuzzy/src/DebouncedInput.svelte @@ -0,0 +1,29 @@ + + + diff --git a/examples/svelte/filters-fuzzy/src/index.css b/examples/svelte/filters-fuzzy/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/filters-fuzzy/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/svelte/filters-fuzzy/src/main.ts b/examples/svelte/filters-fuzzy/src/main.ts new file mode 100644 index 0000000000..a2f1b40ec8 --- /dev/null +++ b/examples/svelte/filters-fuzzy/src/main.ts @@ -0,0 +1,20 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' +import type { FilterFn } from '@tanstack/svelte-table' +import type { RankingInfo } from '@tanstack/match-sorter-utils' + +declare module '@tanstack/svelte-table' { + interface FilterFns { + fuzzy: FilterFn + } + interface FilterMeta { + itemRank?: RankingInfo + } +} + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/filters-fuzzy/src/makeData.ts b/examples/svelte/filters-fuzzy/src/makeData.ts new file mode 100644 index 0000000000..396d62185b --- /dev/null +++ b/examples/svelte/filters-fuzzy/src/makeData.ts @@ -0,0 +1,45 @@ +import { faker } from '@faker-js/faker' + +export type Person = { + id: number + 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 = (num: number): Person => ({ + id: num, + 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( + (index): Person => ({ + ...newPerson(index), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + }), + ) + } + return makeDataLevel() +} diff --git a/examples/svelte/filters-fuzzy/svelte.config.js b/examples/svelte/filters-fuzzy/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/filters-fuzzy/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/filters-fuzzy/tsconfig.json b/examples/svelte/filters-fuzzy/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/filters-fuzzy/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/filters-fuzzy/vite.config.js b/examples/svelte/filters-fuzzy/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/filters-fuzzy/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/grouping/.gitignore b/examples/svelte/grouping/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/grouping/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/grouping/index.html b/examples/svelte/grouping/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/grouping/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/grouping/package.json b/examples/svelte/grouping/package.json new file mode 100644 index 0000000000..ea060791bc --- /dev/null +++ b/examples/svelte/grouping/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-grouping", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/grouping/src/App.svelte b/examples/svelte/grouping/src/App.svelte new file mode 100644 index 0000000000..d6c924e6bf --- /dev/null +++ b/examples/svelte/grouping/src/App.svelte @@ -0,0 +1,236 @@ + + +
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} +
+ {#if header.column.getCanGroup()} + + {/if} + {' '} + +
+ {/if} +
+ {#if cell.getIsGrouped()} + + {:else if cell.getIsAggregated()} + + {:else if !cell.getIsPlaceholder()} + + {/if} +
+
+
+ + + + + +
Page
+ + {table.state.pagination.pageIndex + 1} of{' '} + {table.getPageCount()} + +
+ + | Go to page: + { + const page = (e.target as HTMLInputElement).value + ? Number((e.target as HTMLInputElement).value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
{table.getRowModel().rows.length} Rows
+
+ +
+
{JSON.stringify(table.state, null, 2)}
+
diff --git a/examples/svelte/grouping/src/index.css b/examples/svelte/grouping/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/grouping/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/svelte/grouping/src/main.ts b/examples/svelte/grouping/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/grouping/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/grouping/src/makeData.ts b/examples/svelte/grouping/src/makeData.ts new file mode 100644 index 0000000000..fd3637a468 --- /dev/null +++ b/examples/svelte/grouping/src/makeData.ts @@ -0,0 +1,47 @@ +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( + (): Person => ({ + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + }), + ) + } + return makeDataLevel() +} diff --git a/examples/svelte/grouping/svelte.config.js b/examples/svelte/grouping/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/grouping/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/grouping/tsconfig.json b/examples/svelte/grouping/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/grouping/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/grouping/vite.config.js b/examples/svelte/grouping/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/grouping/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/pagination/.gitignore b/examples/svelte/pagination/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/pagination/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/pagination/index.html b/examples/svelte/pagination/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/pagination/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/pagination/package.json b/examples/svelte/pagination/package.json new file mode 100644 index 0000000000..5d5be5a465 --- /dev/null +++ b/examples/svelte/pagination/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-pagination", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/pagination/src/App.svelte b/examples/svelte/pagination/src/App.svelte new file mode 100644 index 0000000000..9e8ef0782e --- /dev/null +++ b/examples/svelte/pagination/src/App.svelte @@ -0,0 +1,264 @@ + + +{#snippet filterSnippet(column: Column)} + {@const firstValue = getFirstValue(table, column.id)} + {@const filterValue = getFilterValue(column)} + {#if typeof firstValue === 'number'} +
+ + column.setFilterValue((old: [number, number]) => [ + (e.target as HTMLInputElement).value, + old?.[1], + ])} + placeholder="Min" + class="w-24 border shadow rounded" + /> + + column.setFilterValue((old: [number, number]) => [ + old?.[0], + (e.target as HTMLInputElement).value, + ])} + placeholder="Max" + class="w-24 border shadow rounded" + /> +
+ {:else} + + column.setFilterValue((e.target as HTMLInputElement).value)} + onclick={(e: MouseEvent) => e.stopPropagation()} + placeholder="Search..." + type="text" + value={(filterValue ?? '') as string} + /> + {/if} +{/snippet} + +
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + {#if !header.isPlaceholder} + + {/if} + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} + {#if header.column.getCanFilter()} +
+ {@render filterSnippet(header.column)} +
+ {/if} +
+
+ +
+
+
+ + + + + +
Page
+ + {table.state.pagination.pageIndex + 1} of{' '} + {table.getPageCount().toLocaleString()} + +
+ + | Go to page: + { + const page = (e.target as HTMLInputElement).value + ? Number((e.target as HTMLInputElement).value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
+ Showing {table.getRowModel().rows.length.toLocaleString()} of{' '} + {table.getRowCount().toLocaleString()} Rows +
+
+
+ +
+ state} {table}> + {#snippet children(state)} +
{JSON.stringify(state, null, 2)}
+ {/snippet} +
+
diff --git a/examples/svelte/pagination/src/index.css b/examples/svelte/pagination/src/index.css new file mode 100644 index 0000000000..12d71033f0 --- /dev/null +++ b/examples/svelte/pagination/src/index.css @@ -0,0 +1,21 @@ +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/svelte/pagination/src/main.ts b/examples/svelte/pagination/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/pagination/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/pagination/src/makeData.ts b/examples/svelte/pagination/src/makeData.ts new file mode 100644 index 0000000000..8675eacca6 --- /dev/null +++ b/examples/svelte/pagination/src/makeData.ts @@ -0,0 +1,43 @@ +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 => ({ + 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( + (): Person => ({ + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + }), + ) + } + return makeDataLevel() +} diff --git a/examples/svelte/pagination/svelte.config.js b/examples/svelte/pagination/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/pagination/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/pagination/tsconfig.json b/examples/svelte/pagination/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/pagination/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/pagination/vite.config.js b/examples/svelte/pagination/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/pagination/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/row-pinning/.gitignore b/examples/svelte/row-pinning/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/row-pinning/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/row-pinning/index.html b/examples/svelte/row-pinning/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/row-pinning/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/row-pinning/package.json b/examples/svelte/row-pinning/package.json new file mode 100644 index 0000000000..42cb61b5ec --- /dev/null +++ b/examples/svelte/row-pinning/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-table-example-svelte-row-pinning", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/row-pinning/src/App.svelte b/examples/svelte/row-pinning/src/App.svelte new file mode 100644 index 0000000000..12ce295744 --- /dev/null +++ b/examples/svelte/row-pinning/src/App.svelte @@ -0,0 +1,385 @@ + + +{#snippet PinCell(row: ReturnType['rows'][0])} + {#if row.getIsPinned()} + + {:else} +
+ + +
+ {/if} +{/snippet} + +{#snippet ExpandCell(row: ReturnType['rows'][0])} +
+ {#if row.getCanExpand()} + + {:else} + * + {/if} +
+{/snippet} + +{#snippet ExpandAllButton()} + +{/snippet} + +{#snippet PinnedRow(row: ReturnType['rows'][0])} + + {#each row.getAllCells() as cell (cell.id)} + + {#if cell.column.id === 'pin'} + {@render PinCell(row)} + {:else if cell.column.id === 'firstName'} + {@render ExpandCell(row)} + + {:else} + + {/if} + + {/each} + +{/snippet} + +{#snippet Filter(column: Column, tableRef: SvelteTable)} + {@const firstValue = tableRef + .getPreFilteredRowModel() + .flatRows[0]?.getValue(column.id)} + + {#if typeof firstValue === 'number'} +
+ + column.setFilterValue((old: any) => [(e.target as HTMLInputElement).value, old?.[1]]) + } + placeholder="Min" + class="w-24 border shadow rounded" + /> + + column.setFilterValue((old: any) => [old?.[0], (e.target as HTMLInputElement).value]) + } + placeholder="Max" + class="w-24 border shadow rounded" + /> +
+ {:else} + column.setFilterValue((e.target as HTMLInputElement).value)} + placeholder="Search..." + class="w-36 border shadow rounded" + /> + {/if} +{/snippet} + +
+
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getTopRows() as row (row.id)} + {@render PinnedRow(row)} + {/each} + {#each copyPinnedRows ? table.getRowModel().rows : table.getCenterRows() as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + {#each table.getBottomRows() as row (row.id)} + {@render PinnedRow(row)} + {/each} + +
+ {#if !header.isPlaceholder} + {#if header.column.id === 'firstName'} + {@render ExpandAllButton()} + {:else} + + {/if} + {#if header.column.getCanFilter()} +
+ {@render Filter(header.column, table)} +
+ {/if} + {/if} +
+ {#if cell.column.id === 'pin'} + {@render PinCell(row)} + {:else if cell.column.id === 'firstName'} + {@render ExpandCell(row)} + + {:else} + + {/if} +
+
+ +
+
+ + + + + +
Page
+ + {table.state.pagination.pageIndex + 1} of{' '} + {table.getPageCount()} + +
+ + | Go to page: + { + const page = (e.target as HTMLInputElement).value + ? Number((e.target as HTMLInputElement).value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
{JSON.stringify(table.state.rowPinning, null, 2)}
+
diff --git a/examples/svelte/row-pinning/src/index.css b/examples/svelte/row-pinning/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/row-pinning/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/svelte/row-pinning/src/main.ts b/examples/svelte/row-pinning/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/row-pinning/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/row-pinning/src/makeData.ts b/examples/svelte/row-pinning/src/makeData.ts new file mode 100644 index 0000000000..8675eacca6 --- /dev/null +++ b/examples/svelte/row-pinning/src/makeData.ts @@ -0,0 +1,43 @@ +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 => ({ + 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( + (): Person => ({ + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + }), + ) + } + return makeDataLevel() +} diff --git a/examples/svelte/row-pinning/svelte.config.js b/examples/svelte/row-pinning/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/row-pinning/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/row-pinning/tsconfig.json b/examples/svelte/row-pinning/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/row-pinning/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/row-pinning/vite.config.js b/examples/svelte/row-pinning/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/row-pinning/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/row-selection/src/App.svelte b/examples/svelte/row-selection/src/App.svelte index 8aaa059727..8de57f26c5 100644 --- a/examples/svelte/row-selection/src/App.svelte +++ b/examples/svelte/row-selection/src/App.svelte @@ -5,7 +5,7 @@ createPaginatedRowModel, createTable, filterFns, - flexRender, + FlexRender, globalFilteringFeature, rowPaginationFeature, rowSelectionFeature, @@ -32,6 +32,16 @@ data = makeData(100_000) // stress test } + // Svelte action to set indeterminate property on checkbox inputs + function setIndeterminate(node: HTMLInputElement, value: boolean) { + node.indeterminate = value + return { + update(newValue: boolean) { + node.indeterminate = newValue + }, + } + } + // Create table with selector to track specific state const table = createTable( { @@ -109,46 +119,39 @@ pagination: state.pagination, }), ) - - // Access selected state reactively - $effect(() => { - // Access table.state to create reactive dependency - table.state - })
table.setGlobalFilter(e.target.value)} + oninput={(e) => table.setGlobalFilter((e.target as HTMLInputElement).value)} class="p-2 font-lg shadow border border-block" placeholder="Search all columns..." />
-
+
- {#each table.getHeaderGroups() as headerGroup} + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} - {#each headerGroup.headers as header} + {#each headerGroup.headers as header (header.id)} - {#each table.getRowModel().rows as row} + {#each table.getRowModel().rows as row (row.id)} - {#each row.getAllCells() as cell} + {#each row.getAllCells() as cell (cell.id)} {/each} @@ -183,17 +185,19 @@
{#if !header.isPlaceholder} {#if header.id === 'select'} - {:else} - + {/if} {#if header.column.getCanFilter()}
- + {@render Filter(header.column, table)}
{/if} {/if} @@ -158,22 +161,21 @@ {/each}
{#if cell.column.id === 'select'} - {:else} - + {/if}
- Page Rows ({table.getRowModel().rows.length})
-
+
diff --git a/examples/svelte/sub-components/src/index.css b/examples/svelte/sub-components/src/index.css new file mode 100644 index 0000000000..12d71033f0 --- /dev/null +++ b/examples/svelte/sub-components/src/index.css @@ -0,0 +1,21 @@ +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/svelte/sub-components/src/main.ts b/examples/svelte/sub-components/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/sub-components/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/sub-components/src/makeData.ts b/examples/svelte/sub-components/src/makeData.ts new file mode 100644 index 0000000000..8675eacca6 --- /dev/null +++ b/examples/svelte/sub-components/src/makeData.ts @@ -0,0 +1,43 @@ +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 => ({ + 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( + (): Person => ({ + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + }), + ) + } + return makeDataLevel() +} diff --git a/examples/svelte/sub-components/svelte.config.js b/examples/svelte/sub-components/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/sub-components/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/sub-components/tsconfig.json b/examples/svelte/sub-components/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/sub-components/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/sub-components/vite.config.js b/examples/svelte/sub-components/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/sub-components/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/virtualized-columns/index.html b/examples/svelte/virtualized-columns/index.html new file mode 100644 index 0000000000..392fecf932 --- /dev/null +++ b/examples/svelte/virtualized-columns/index.html @@ -0,0 +1,13 @@ + + + + + + Svelte Table - Virtualized Columns + + + +
+ + + diff --git a/examples/svelte/virtualized-columns/package.json b/examples/svelte/virtualized-columns/package.json new file mode 100644 index 0000000000..f49ccc007a --- /dev/null +++ b/examples/svelte/virtualized-columns/package.json @@ -0,0 +1,25 @@ +{ + "name": "tanstack-table-example-svelte-virtualized-columns", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tanstack/svelte-virtual": "^3.13.23", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/virtualized-columns/src/App.svelte b/examples/svelte/virtualized-columns/src/App.svelte new file mode 100644 index 0000000000..f66b1782c9 --- /dev/null +++ b/examples/svelte/virtualized-columns/src/App.svelte @@ -0,0 +1,199 @@ + + +
+
({columns.length.toLocaleString()} columns)
+
({data.length.toLocaleString()} rows)
+ +
+ + + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#if virtualPaddingLeft} + + + {/if} + {#each $columnVirtualizer.getVirtualItems() as virtualColumn (virtualColumn.index)} + {@const header = headerGroup.headers[virtualColumn.index]} + + {/each} + {#if virtualPaddingRight} + + + {/if} + + {/each} + + + {#each $rowVirtualizer.getVirtualItems() as virtualRow (virtualRow.index)} + {@const row = rows[virtualRow.index]} + {@const visibleCells = row.getVisibleCells()} + + {#if virtualPaddingLeft} + + + {/if} + {#each $columnVirtualizer.getVirtualItems() as virtualColumn (virtualColumn.index)} + {@const cell = visibleCells[virtualColumn.index]} + + {/each} + {#if virtualPaddingRight} + + + {/if} + + {/each} + +
+
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} +
+
+ +
+
+
diff --git a/examples/svelte/virtualized-columns/src/index.css b/examples/svelte/virtualized-columns/src/index.css new file mode 100644 index 0000000000..6402cb4b8b --- /dev/null +++ b/examples/svelte/virtualized-columns/src/index.css @@ -0,0 +1,40 @@ +html { + font-family: sans-serif; + font-size: 14px; +} + +table { + border-collapse: collapse; + border-spacing: 0; + font-family: arial, sans-serif; + table-layout: fixed; +} + +thead { + background: lightgray; +} + +tr { + border-bottom: 1px solid lightgray; +} + +th { + border-bottom: 1px solid lightgray; + border-right: 1px solid lightgray; + padding: 2px 4px; + text-align: left; +} + +td { + padding: 6px; +} + +.container { + border: 1px solid lightgray; + margin: 1rem auto; +} + +.app { + margin: 1rem auto; + text-align: center; +} diff --git a/examples/svelte/virtualized-columns/src/main.ts b/examples/svelte/virtualized-columns/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/virtualized-columns/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/virtualized-columns/src/makeData.ts b/examples/svelte/virtualized-columns/src/makeData.ts new file mode 100644 index 0000000000..837114e211 --- /dev/null +++ b/examples/svelte/virtualized-columns/src/makeData.ts @@ -0,0 +1,17 @@ +import { faker } from '@faker-js/faker' + +export const makeColumns = (num: number) => + [...Array(num)].map((_, i) => ({ + accessorKey: i.toString(), + header: 'Column ' + i.toString(), + size: Math.floor(Math.random() * 150) + 100, + })) + +export const makeData = (num: number, columns: Array) => + [...Array(num)].map(() => ({ + ...Object.fromEntries( + columns.map((col: any) => [col.accessorKey, faker.person.firstName()]), + ), + })) + +export type Person = ReturnType[0] diff --git a/examples/svelte/virtualized-columns/src/vite-env.d.ts b/examples/svelte/virtualized-columns/src/vite-env.d.ts new file mode 100644 index 0000000000..4078e7476a --- /dev/null +++ b/examples/svelte/virtualized-columns/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples/svelte/virtualized-columns/svelte.config.js b/examples/svelte/virtualized-columns/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/virtualized-columns/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/virtualized-columns/tsconfig.json b/examples/svelte/virtualized-columns/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/virtualized-columns/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/virtualized-columns/vite.config.js b/examples/svelte/virtualized-columns/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/virtualized-columns/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/virtualized-infinite-scrolling/index.html b/examples/svelte/virtualized-infinite-scrolling/index.html new file mode 100644 index 0000000000..a32d7d57d9 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/index.html @@ -0,0 +1,13 @@ + + + + + + Svelte Table - Virtualized Infinite Scrolling + + + +
+ + + diff --git a/examples/svelte/virtualized-infinite-scrolling/package.json b/examples/svelte/virtualized-infinite-scrolling/package.json new file mode 100644 index 0000000000..3bf4948581 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/package.json @@ -0,0 +1,26 @@ +{ + "name": "tanstack-table-example-svelte-virtualized-infinite-scrolling", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-query": "^6.1.13", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tanstack/svelte-virtual": "^3.13.23", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/virtualized-infinite-scrolling/src/App.svelte b/examples/svelte/virtualized-infinite-scrolling/src/App.svelte new file mode 100644 index 0000000000..54c2379472 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/src/App.svelte @@ -0,0 +1,243 @@ + + +
+ {#if import.meta.env.DEV} +

+ Notice: You are currently running Svelte in development mode. + Virtualized rendering performance will be slightly degraded until this + application is built for production. +

+ {/if} + ({totalFetched} of {totalDBRowCount} rows fetched) +
fetchMoreOnBottomReached(e.currentTarget as HTMLDivElement)} + bind:this={tableContainerRef} + style="overflow: auto; position: relative; height: 600px;" + > + + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each $rowVirtualizer.getVirtualItems() as virtualRow (virtualRow.index)} + {@const row = rows[virtualRow.index]} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} +
+
+ +
+
+ {#if query.isFetching} +
Fetching More...
+ {/if} +
diff --git a/examples/svelte/virtualized-infinite-scrolling/src/Root.svelte b/examples/svelte/virtualized-infinite-scrolling/src/Root.svelte new file mode 100644 index 0000000000..cda9d6aac9 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/src/Root.svelte @@ -0,0 +1,10 @@ + + + + + diff --git a/examples/svelte/virtualized-infinite-scrolling/src/index.css b/examples/svelte/virtualized-infinite-scrolling/src/index.css new file mode 100644 index 0000000000..6402cb4b8b --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/src/index.css @@ -0,0 +1,40 @@ +html { + font-family: sans-serif; + font-size: 14px; +} + +table { + border-collapse: collapse; + border-spacing: 0; + font-family: arial, sans-serif; + table-layout: fixed; +} + +thead { + background: lightgray; +} + +tr { + border-bottom: 1px solid lightgray; +} + +th { + border-bottom: 1px solid lightgray; + border-right: 1px solid lightgray; + padding: 2px 4px; + text-align: left; +} + +td { + padding: 6px; +} + +.container { + border: 1px solid lightgray; + margin: 1rem auto; +} + +.app { + margin: 1rem auto; + text-align: center; +} diff --git a/examples/svelte/virtualized-infinite-scrolling/src/main.ts b/examples/svelte/virtualized-infinite-scrolling/src/main.ts new file mode 100644 index 0000000000..147baab20e --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import Root from './Root.svelte' + +const app = mount(Root, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/virtualized-infinite-scrolling/src/makeData.ts b/examples/svelte/virtualized-infinite-scrolling/src/makeData.ts new file mode 100644 index 0000000000..f482393d88 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/src/makeData.ts @@ -0,0 +1,89 @@ +import { faker } from '@faker-js/faker' +import type { SortingState } from '@tanstack/svelte-table' + +export type Person = { + id: number + firstName: string + lastName: string + age: number + visits: number + progress: number + status: 'relationship' | 'complicated' | 'single' + createdAt: Date +} + +export type PersonApiResponse = { + data: Array + meta: { + totalRowCount: number + } +} + +const range = (len: number) => { + const arr: Array = [] + for (let i = 0; i < len; i++) { + arr.push(i) + } + return arr +} + +const newPerson = (index: number): Person => { + return { + id: index + 1, + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + age: faker.number.int(40), + visits: faker.number.int(1000), + progress: faker.number.int(100), + createdAt: faker.date.anytime(), + 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(d), + } + }) + } + + return makeDataLevel() +} + +const data = makeData(1000) + +// simulates a backend api +export const fetchData = async ( + start: number, + size: number, + sorting: SortingState, +) => { + const dbData = [...data] + if (sorting.length) { + const sort = sorting[0] + const { id, desc } = sort as { id: keyof Person; desc: boolean } + dbData.sort((a, b) => { + if (desc) { + return a[id] < b[id] ? 1 : -1 + } + return a[id] > b[id] ? 1 : -1 + }) + } + + // simulate a backend api + await new Promise((resolve) => setTimeout(resolve, 200)) + + return { + data: dbData.slice(start, start + size), + meta: { + totalRowCount: dbData.length, + }, + } +} diff --git a/examples/svelte/virtualized-infinite-scrolling/src/vite-env.d.ts b/examples/svelte/virtualized-infinite-scrolling/src/vite-env.d.ts new file mode 100644 index 0000000000..4078e7476a --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples/svelte/virtualized-infinite-scrolling/svelte.config.js b/examples/svelte/virtualized-infinite-scrolling/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/virtualized-infinite-scrolling/tsconfig.json b/examples/svelte/virtualized-infinite-scrolling/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/virtualized-infinite-scrolling/vite.config.js b/examples/svelte/virtualized-infinite-scrolling/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/virtualized-infinite-scrolling/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/virtualized-rows/index.html b/examples/svelte/virtualized-rows/index.html new file mode 100644 index 0000000000..f728c10d59 --- /dev/null +++ b/examples/svelte/virtualized-rows/index.html @@ -0,0 +1,13 @@ + + + + + + Svelte Table - Virtualized Rows + + + +
+ + + diff --git a/examples/svelte/virtualized-rows/package.json b/examples/svelte/virtualized-rows/package.json new file mode 100644 index 0000000000..e492a5fe17 --- /dev/null +++ b/examples/svelte/virtualized-rows/package.json @@ -0,0 +1,25 @@ +{ + "name": "tanstack-table-example-svelte-virtualized-rows", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "@tanstack/svelte-virtual": "^3.13.23", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + } +} diff --git a/examples/svelte/virtualized-rows/src/App.svelte b/examples/svelte/virtualized-rows/src/App.svelte new file mode 100644 index 0000000000..3f14d4c24c --- /dev/null +++ b/examples/svelte/virtualized-rows/src/App.svelte @@ -0,0 +1,182 @@ + + +
+ ({data.length.toLocaleString()} rows) + +
+ + + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each $rowVirtualizer.getVirtualItems() as virtualRow (virtualRow.index)} + {@const row = rows[virtualRow.index]} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+
{ + if (e.key === 'Enter' || e.key === ' ') { + header.column.getToggleSortingHandler()?.(e) + } + }} + > + + {#if header.column.getIsSorted() === 'asc'} + {' '}🔼 + {:else if header.column.getIsSorted() === 'desc'} + {' '}🔽 + {/if} +
+
+ +
+
+
diff --git a/examples/svelte/virtualized-rows/src/index.css b/examples/svelte/virtualized-rows/src/index.css new file mode 100644 index 0000000000..6402cb4b8b --- /dev/null +++ b/examples/svelte/virtualized-rows/src/index.css @@ -0,0 +1,40 @@ +html { + font-family: sans-serif; + font-size: 14px; +} + +table { + border-collapse: collapse; + border-spacing: 0; + font-family: arial, sans-serif; + table-layout: fixed; +} + +thead { + background: lightgray; +} + +tr { + border-bottom: 1px solid lightgray; +} + +th { + border-bottom: 1px solid lightgray; + border-right: 1px solid lightgray; + padding: 2px 4px; + text-align: left; +} + +td { + padding: 6px; +} + +.container { + border: 1px solid lightgray; + margin: 1rem auto; +} + +.app { + margin: 1rem auto; + text-align: center; +} diff --git a/examples/svelte/virtualized-rows/src/main.ts b/examples/svelte/virtualized-rows/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/virtualized-rows/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/virtualized-rows/src/makeData.ts b/examples/svelte/virtualized-rows/src/makeData.ts new file mode 100644 index 0000000000..aa621f5bba --- /dev/null +++ b/examples/svelte/virtualized-rows/src/makeData.ts @@ -0,0 +1,41 @@ +import { faker } from '@faker-js/faker' + +export type Person = { + id: number + firstName: string + lastName: string + age: number + visits: number + progress: number + status: 'relationship' | 'complicated' | 'single' + createdAt: Date +} + +const range = (len: number) => { + const arr: Array = [] + for (let i = 0; i < len; i++) arr.push(i) + return arr +} + +const newPerson = (index: number): Person => ({ + id: index + 1, + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + age: faker.number.int(40), + visits: faker.number.int(1000), + progress: faker.number.int(100), + createdAt: faker.date.anytime(), + 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 => ({ ...newPerson(d) })) + } + return makeDataLevel() +} diff --git a/examples/svelte/virtualized-rows/src/vite-env.d.ts b/examples/svelte/virtualized-rows/src/vite-env.d.ts new file mode 100644 index 0000000000..4078e7476a --- /dev/null +++ b/examples/svelte/virtualized-rows/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples/svelte/virtualized-rows/svelte.config.js b/examples/svelte/virtualized-rows/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/virtualized-rows/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/virtualized-rows/tsconfig.json b/examples/svelte/virtualized-rows/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/virtualized-rows/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/virtualized-rows/vite.config.js b/examples/svelte/virtualized-rows/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/virtualized-rows/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/with-tanstack-form/.gitignore b/examples/svelte/with-tanstack-form/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/with-tanstack-form/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/with-tanstack-form/index.html b/examples/svelte/with-tanstack-form/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/with-tanstack-form/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/with-tanstack-form/package.json b/examples/svelte/with-tanstack-form/package.json new file mode 100644 index 0000000000..a9df0b6604 --- /dev/null +++ b/examples/svelte/with-tanstack-form/package.json @@ -0,0 +1,29 @@ +{ + "name": "tanstack-table-example-svelte-with-tanstack-form", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + }, + "dependencies": { + "@tanstack/form-core": "^1.12.2", + "@tanstack/svelte-form": "^1.12.2", + "@tanstack/svelte-table": "^9.0.0-alpha.10", + "zod": "^3.24.4" + } +} diff --git a/examples/svelte/with-tanstack-form/src/App.svelte b/examples/svelte/with-tanstack-form/src/App.svelte new file mode 100644 index 0000000000..86cbbe100a --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/App.svelte @@ -0,0 +1,374 @@ + + +{#snippet filterSnippet(column: Column)} + {@const firstValue = getFirstValue(table, column.id)} + {@const filterValue = getFilterValue(column)} + {#if typeof firstValue === 'number'} +
+ + column.setFilterValue((old: [number, number]) => [ + (e.target as HTMLInputElement).value, + old?.[1], + ])} + placeholder="Min" + class="w-24 border shadow rounded" + /> + + column.setFilterValue((old: [number, number]) => [ + old?.[0], + (e.target as HTMLInputElement).value, + ])} + placeholder="Max" + class="w-24 border shadow rounded" + /> +
+ {:else} + + column.setFilterValue((e.target as HTMLInputElement).value)} + placeholder="Search..." + type="text" + value={(filterValue ?? '') as string} + /> + {/if} +{/snippet} + +
+
{ + e.preventDefault() + e.stopPropagation() + void form.handleSubmit() + }} + > + +
+ + {#snippet children()} + + {/snippet} + + + {#snippet children()} + + {/snippet} + + + +
+ + +
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} +
+ + {#if header.column.getCanFilter()} +
+ {@render filterSnippet(header.column)} +
+ {/if} +
+ {/if} +
+ +
+ + +
+
+ + + + + +
Page
+ + {table.state.pagination.pageIndex + 1} of{' '} + {table.getPageCount().toLocaleString()} + +
+ + | Go to page: + { + const page = (e.target as HTMLInputElement).value + ? Number((e.target as HTMLInputElement).value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + +
+
+ Showing {table.getRowModel().rows.length.toLocaleString()} of{' '} + {table.getRowCount().toLocaleString()} Rows +
+
+
+
diff --git a/examples/svelte/with-tanstack-form/src/FormStateIndicator.svelte b/examples/svelte/with-tanstack-form/src/FormStateIndicator.svelte new file mode 100644 index 0000000000..0b7759c6a6 --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/FormStateIndicator.svelte @@ -0,0 +1,29 @@ + + + ({ + isDirty: state.isDirty, + isValid: state.isValid, + errorMap: state.errorMap, + })} +> + {#snippet children({ isDirty, isValid, errorMap })} +
+ + {isDirty ? '● Modified' : '○ Pristine'} + + + {isValid ? '✓ Valid' : '✗ Invalid'} + + {#if Object.keys(errorMap).length > 0} + + Errors: {JSON.stringify(errorMap)} + + {/if} +
+ {/snippet} +
diff --git a/examples/svelte/with-tanstack-form/src/NumberField.svelte b/examples/svelte/with-tanstack-form/src/NumberField.svelte new file mode 100644 index 0000000000..3da71f2bc8 --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/NumberField.svelte @@ -0,0 +1,19 @@ + + +
+ + field.handleChange(Number((e.target as HTMLInputElement).value))} + onblur={() => field.handleBlur()} + /> + {#if field.state.meta.errors.length > 0} +
{field.state.meta.errors.join(', ')}
+ {/if} +
diff --git a/examples/svelte/with-tanstack-form/src/NumberFieldCell.svelte b/examples/svelte/with-tanstack-form/src/NumberFieldCell.svelte new file mode 100644 index 0000000000..fda51276aa --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/NumberFieldCell.svelte @@ -0,0 +1,29 @@ + + + + {#snippet children(field: any)} + + {/snippet} + diff --git a/examples/svelte/with-tanstack-form/src/SelectField.svelte b/examples/svelte/with-tanstack-form/src/SelectField.svelte new file mode 100644 index 0000000000..61a9c1a19d --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/SelectField.svelte @@ -0,0 +1,24 @@ + + +
+ + {#if field.state.meta.errors.length > 0} +
{field.state.meta.errors.join(', ')}
+ {/if} +
diff --git a/examples/svelte/with-tanstack-form/src/SelectFieldCell.svelte b/examples/svelte/with-tanstack-form/src/SelectFieldCell.svelte new file mode 100644 index 0000000000..6d3192dafa --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/SelectFieldCell.svelte @@ -0,0 +1,14 @@ + + + + {#snippet children(field: any)} + + {/snippet} + diff --git a/examples/svelte/with-tanstack-form/src/SubmitButton.svelte b/examples/svelte/with-tanstack-form/src/SubmitButton.svelte new file mode 100644 index 0000000000..26bfb3a56d --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/SubmitButton.svelte @@ -0,0 +1,24 @@ + + + ({ + isSubmitting: state.isSubmitting, + canSubmit: state.canSubmit, + })} +> + {#snippet children({ isSubmitting, canSubmit })} + + {/snippet} + diff --git a/examples/svelte/with-tanstack-form/src/TextField.svelte b/examples/svelte/with-tanstack-form/src/TextField.svelte new file mode 100644 index 0000000000..9ebd865f26 --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/TextField.svelte @@ -0,0 +1,18 @@ + + +
+ + field.handleChange((e.target as HTMLInputElement).value)} + onblur={() => field.handleBlur()} + /> + {#if field.state.meta.errors.length > 0} +
{field.state.meta.errors.join(', ')}
+ {/if} +
diff --git a/examples/svelte/with-tanstack-form/src/TextFieldCell.svelte b/examples/svelte/with-tanstack-form/src/TextFieldCell.svelte new file mode 100644 index 0000000000..fe28f99e79 --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/TextFieldCell.svelte @@ -0,0 +1,21 @@ + + + + {#snippet children(field: any)} + + {/snippet} + diff --git a/examples/svelte/with-tanstack-form/src/form-context.ts b/examples/svelte/with-tanstack-form/src/form-context.ts new file mode 100644 index 0000000000..40989db7f5 --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/form-context.ts @@ -0,0 +1,3 @@ +import { createFormCreatorContexts } from '@tanstack/svelte-form' + +export const { useFieldContext, useFormContext } = createFormCreatorContexts() diff --git a/examples/svelte/with-tanstack-form/src/form.ts b/examples/svelte/with-tanstack-form/src/form.ts new file mode 100644 index 0000000000..c796c870e1 --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/form.ts @@ -0,0 +1,18 @@ +import { createFormCreator } from '@tanstack/svelte-form' +import TextField from './TextField.svelte' +import NumberField from './NumberField.svelte' +import SelectField from './SelectField.svelte' +import SubmitButton from './SubmitButton.svelte' +import FormStateIndicator from './FormStateIndicator.svelte' + +export const { createAppForm } = createFormCreator({ + fieldComponents: { + TextField, + NumberField, + SelectField, + }, + formComponents: { + SubmitButton, + FormStateIndicator, + }, +}) diff --git a/examples/svelte/with-tanstack-form/src/index.css b/examples/svelte/with-tanstack-form/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/with-tanstack-form/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/svelte/with-tanstack-form/src/main.ts b/examples/svelte/with-tanstack-form/src/main.ts new file mode 100644 index 0000000000..2f4dd54dc3 --- /dev/null +++ b/examples/svelte/with-tanstack-form/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/with-tanstack-form/src/makeData.ts b/examples/svelte/with-tanstack-form/src/makeData.ts new file mode 100644 index 0000000000..b9055b2d8c --- /dev/null +++ b/examples/svelte/with-tanstack-form/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/svelte/with-tanstack-form/svelte.config.js b/examples/svelte/with-tanstack-form/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/with-tanstack-form/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/with-tanstack-form/tsconfig.json b/examples/svelte/with-tanstack-form/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/with-tanstack-form/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/with-tanstack-form/vite.config.js b/examples/svelte/with-tanstack-form/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/with-tanstack-form/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/svelte/with-tanstack-query/.gitignore b/examples/svelte/with-tanstack-query/.gitignore new file mode 100644 index 0000000000..2de1736a62 --- /dev/null +++ b/examples/svelte/with-tanstack-query/.gitignore @@ -0,0 +1,8 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local + +src/**/*.d.ts +src/**/*.map diff --git a/examples/svelte/with-tanstack-query/index.html b/examples/svelte/with-tanstack-query/index.html new file mode 100644 index 0000000000..6ab1dd7e51 --- /dev/null +++ b/examples/svelte/with-tanstack-query/index.html @@ -0,0 +1,14 @@ + + + + + + Vite App + + + + +
+ + + diff --git a/examples/svelte/with-tanstack-query/package.json b/examples/svelte/with-tanstack-query/package.json new file mode 100644 index 0000000000..8fe71d9d7a --- /dev/null +++ b/examples/svelte/with-tanstack-query/package.json @@ -0,0 +1,27 @@ +{ + "name": "tanstack-table-example-svelte-with-tanstack-query", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "serve": "vite preview", + "test:types": "svelte-check --tsconfig ./tsconfig.json", + "lint": "eslint ./src" + }, + "devDependencies": { + "@faker-js/faker": "^10.4.0", + "@rollup/plugin-replace": "^6.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@tsconfig/svelte": "^5.0.8", + "svelte": "^5.55.1", + "svelte-check": "^4.4.6", + "typescript": "6.0.2", + "vite": "^8.0.3" + }, + "dependencies": { + "@tanstack/svelte-query": "^6.1.13", + "@tanstack/svelte-table": "^9.0.0-alpha.10" + } +} diff --git a/examples/svelte/with-tanstack-query/src/App.svelte b/examples/svelte/with-tanstack-query/src/App.svelte new file mode 100644 index 0000000000..482ed6ac75 --- /dev/null +++ b/examples/svelte/with-tanstack-query/src/App.svelte @@ -0,0 +1,190 @@ + + +
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getAllCells() as cell (cell.id)} + + {/each} + + {/each} + +
+ {#if !header.isPlaceholder} + + {/if} +
+ +
+
+
+ + + + + +
Page
+ + {pagination.pageIndex + 1} of{' '} + {table.getPageCount().toLocaleString()} + +
+ + | Go to page: + { + const page = (e.target as HTMLInputElement).value + ? Number((e.target as HTMLInputElement).value) - 1 + : 0 + table.setPageIndex(page) + }} + class="border p-1 rounded w-16" + /> + + + {#if dataQuery.isFetching} + Loading... + {/if} +
+
+ Showing {table.getRowModel().rows.length.toLocaleString()} of{' '} + {dataQuery.data?.rowCount?.toLocaleString() ?? 0} Rows +
+ state} {table}> + {#snippet children(state)} +
{JSON.stringify(state, null, 2)}
+ {/snippet} +
+
diff --git a/examples/svelte/with-tanstack-query/src/Root.svelte b/examples/svelte/with-tanstack-query/src/Root.svelte new file mode 100644 index 0000000000..0f8018b132 --- /dev/null +++ b/examples/svelte/with-tanstack-query/src/Root.svelte @@ -0,0 +1,10 @@ + + + + + diff --git a/examples/svelte/with-tanstack-query/src/fetchData.ts b/examples/svelte/with-tanstack-query/src/fetchData.ts new file mode 100644 index 0000000000..0ad745b375 --- /dev/null +++ b/examples/svelte/with-tanstack-query/src/fetchData.ts @@ -0,0 +1,66 @@ +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], + } +} + +function makeData(...lens: Array) { + const makeDataLevel = (depth = 0): Array => { + const len = lens[depth] + return range(len).map((): Person => { + return { + ...newPerson(), + subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined, + } + }) + } + + return makeDataLevel() +} + +const data = makeData(10000) + +export async function fetchData(options: { + pageIndex: number + pageSize: number +}) { + await new Promise((resolve) => setTimeout(resolve, 500)) + + return { + rows: data.slice( + options.pageIndex * options.pageSize, + (options.pageIndex + 1) * options.pageSize, + ), + pageCount: Math.ceil(data.length / options.pageSize), + rowCount: data.length, + } +} diff --git a/examples/svelte/with-tanstack-query/src/index.css b/examples/svelte/with-tanstack-query/src/index.css new file mode 100644 index 0000000000..43c09e0f6b --- /dev/null +++ b/examples/svelte/with-tanstack-query/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/svelte/with-tanstack-query/src/main.ts b/examples/svelte/with-tanstack-query/src/main.ts new file mode 100644 index 0000000000..147baab20e --- /dev/null +++ b/examples/svelte/with-tanstack-query/src/main.ts @@ -0,0 +1,9 @@ +// @ts-ignore +import { mount } from 'svelte' +import Root from './Root.svelte' + +const app = mount(Root, { + target: document.getElementById('root')!, +}) + +export default app diff --git a/examples/svelte/with-tanstack-query/svelte.config.js b/examples/svelte/with-tanstack-query/svelte.config.js new file mode 100644 index 0000000000..8abe4369b8 --- /dev/null +++ b/examples/svelte/with-tanstack-query/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + preprocess: vitePreprocess(), +} diff --git a/examples/svelte/with-tanstack-query/tsconfig.json b/examples/svelte/with-tanstack-query/tsconfig.json new file mode 100644 index 0000000000..e44d928411 --- /dev/null +++ b/examples/svelte/with-tanstack-query/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "module": "esnext", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/svelte/with-tanstack-query/vite.config.js b/examples/svelte/with-tanstack-query/vite.config.js new file mode 100644 index 0000000000..c6ced40a24 --- /dev/null +++ b/examples/svelte/with-tanstack-query/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' +import rollupReplace from '@rollup/plugin-replace' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + rollupReplace({ + preventAssignment: true, + values: { + __DEV__: JSON.stringify(true), + 'process.env.NODE_ENV': JSON.stringify('development'), + }, + }), + svelte(), + ], +}) diff --git a/examples/vue/basic/src/App.vue b/examples/vue/basic/src/App.vue index 923ff0bfa6..ee43aaa070 100644 --- a/examples/vue/basic/src/App.vue +++ b/examples/vue/basic/src/App.vue @@ -123,21 +123,14 @@ const table = useTable({ :key="header.id" :colSpan="header.colSpan" > - + - + @@ -151,11 +144,7 @@ const table = useTable({ :key="header.id" :colSpan="header.colSpan" > - + diff --git a/examples/vue/column-ordering/src/App.vue b/examples/vue/column-ordering/src/App.vue index a45f96d7fa..f827e12f00 100644 --- a/examples/vue/column-ordering/src/App.vue +++ b/examples/vue/column-ordering/src/App.vue @@ -158,21 +158,14 @@ function toggleAllColumnsVisibility() { :key="header.id" :colSpan="header.colSpan" > - + - + @@ -186,11 +179,7 @@ function toggleAllColumnsVisibility() { :key="header.id" :colSpan="header.colSpan" > - + diff --git a/examples/vue/column-pinning/src/App.vue b/examples/vue/column-pinning/src/App.vue index 6dcd00d65f..db9f7f0027 100644 --- a/examples/vue/column-pinning/src/App.vue +++ b/examples/vue/column-pinning/src/App.vue @@ -170,11 +170,7 @@ function toggleAllColumnsVisibility() { :colSpan="header.colSpan" >
- +
- + @@ -234,11 +227,7 @@ function toggleAllColumnsVisibility() { :colSpan="header.colSpan" >
- +
- + @@ -301,11 +287,7 @@ function toggleAllColumnsVisibility() { :colSpan="header.colSpan" >
- +
- + diff --git a/examples/vue/pagination-controlled/src/App.vue b/examples/vue/pagination-controlled/src/App.vue index c457c4a364..e4b78f0611 100644 --- a/examples/vue/pagination-controlled/src/App.vue +++ b/examples/vue/pagination-controlled/src/App.vue @@ -115,21 +115,14 @@ function handlePageSizeChange(e: any) { :key="header.id" :colSpan="header.colSpan" > - + - + diff --git a/examples/vue/pagination/src/App.vue b/examples/vue/pagination/src/App.vue index c4bca2bc44..3d6c07bb16 100644 --- a/examples/vue/pagination/src/App.vue +++ b/examples/vue/pagination/src/App.vue @@ -115,21 +115,14 @@ function handlePageSizeChange(e: any) { :key="header.id" :colSpan="header.colSpan" > - + - + @@ -143,11 +136,7 @@ function handlePageSizeChange(e: any) { :key="header.id" :colSpan="header.colSpan" > - + diff --git a/examples/vue/row-selection/src/App.vue b/examples/vue/row-selection/src/App.vue index f821ba692e..833b1c2cc9 100644 --- a/examples/vue/row-selection/src/App.vue +++ b/examples/vue/row-selection/src/App.vue @@ -127,21 +127,14 @@ const table = useTable( :key="header.id" :colSpan="header.colSpan" > - + - + diff --git a/examples/vue/sorting/src/App.vue b/examples/vue/sorting/src/App.vue index 0d163a5382..1a7e56d724 100644 --- a/examples/vue/sorting/src/App.vue +++ b/examples/vue/sorting/src/App.vue @@ -88,10 +88,7 @@ const table = useTable( @click="header.column.getToggleSortingHandler()?.($event)" >