compote-ui 0.56.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/data-table-v9/create-table.svelte.js +14 -10
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/package.json +6 -19
- package/dist/components/data-table-v8/column-helper.d.ts +0 -12
- package/dist/components/data-table-v8/column-helper.js +0 -42
- package/dist/components/data-table-v8/create-svelte-table.svelte.d.ts +0 -8
- package/dist/components/data-table-v8/create-svelte-table.svelte.js +0 -85
- package/dist/components/data-table-v8/create-table.svelte.d.ts +0 -35
- package/dist/components/data-table-v8/create-table.svelte.js +0 -234
- package/dist/components/data-table-v8/data-table-foot.svelte +0 -96
- package/dist/components/data-table-v8/data-table-foot.svelte.d.ts +0 -33
- package/dist/components/data-table-v8/data-table-head.svelte +0 -196
- package/dist/components/data-table-v8/data-table-head.svelte.d.ts +0 -35
- package/dist/components/data-table-v8/data-table-title.svelte +0 -16
- package/dist/components/data-table-v8/data-table-title.svelte.d.ts +0 -10
- package/dist/components/data-table-v8/data-table-utils.d.ts +0 -32
- package/dist/components/data-table-v8/data-table-utils.js +0 -160
- package/dist/components/data-table-v8/data-table.svelte +0 -273
- package/dist/components/data-table-v8/data-table.svelte.d.ts +0 -41
- package/dist/components/data-table-v8/flex-render.svelte +0 -35
- package/dist/components/data-table-v8/flex-render.svelte.d.ts +0 -28
- package/dist/components/data-table-v8/index.d.ts +0 -12
- package/dist/components/data-table-v8/index.js +0 -10
- package/dist/components/data-table-v8/render-helpers.d.ts +0 -13
- package/dist/components/data-table-v8/render-helpers.js +0 -23
- package/dist/components/data-table-v8/toolbar/data-table-column-filter.svelte +0 -373
- package/dist/components/data-table-v8/toolbar/data-table-column-filter.svelte.d.ts +0 -29
- package/dist/components/data-table-v8/toolbar/data-table-column-visibility.svelte +0 -73
- package/dist/components/data-table-v8/toolbar/data-table-column-visibility.svelte.d.ts +0 -29
- package/dist/components/data-table-v8/toolbar/data-table-search.svelte +0 -57
- package/dist/components/data-table-v8/toolbar/data-table-search.svelte.d.ts +0 -31
- package/dist/components/data-table-v8/toolbar/data-table-toolbar.svelte +0 -39
- package/dist/components/data-table-v8/toolbar/data-table-toolbar.svelte.d.ts +0 -12
- package/dist/components/data-table-v8/types.d.ts +0 -73
- package/dist/components/data-table-v8/types.js +0 -1
- package/dist/components/data-table-v8/virtual/data-table-virtual-rows.svelte +0 -176
- package/dist/components/data-table-v8/virtual/data-table-virtual-rows.svelte.d.ts +0 -40
- package/dist/components/data-table-v8/virtual/data-table-virtualized.svelte +0 -146
- package/dist/components/data-table-v8/virtual/data-table-virtualized.svelte.d.ts +0 -41
- package/dist/components/data-table-v8/virtual/index.d.ts +0 -3
- package/dist/components/data-table-v8/virtual/index.js +0 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createTable as createSvelteTable, createSortedRowModel, createFilteredRowModel, createFacetedRowModel, createFacetedUniqueValues, createFacetedMinMaxValues, sortFns, filterFns } from '@tanstack/svelte-table';
|
|
2
2
|
import { useLocaleContext } from '@ark-ui/svelte/locale';
|
|
3
|
-
import { untrack } from 'svelte';
|
|
3
|
+
import { onDestroy, untrack } from 'svelte';
|
|
4
4
|
import { renderComponent, renderSnippet } from '@tanstack/svelte-table';
|
|
5
5
|
import { dataTableFeatures } from './features';
|
|
6
6
|
import { TYPE_NUMBER_FORMAT_DEFAULTS } from './data-table-utils';
|
|
@@ -72,19 +72,23 @@ export function createTable(options) {
|
|
|
72
72
|
}));
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
|
-
// Notify consumers of visibility changes without taking control of the slice
|
|
76
|
-
//
|
|
77
|
-
//
|
|
75
|
+
// Notify consumers of visibility changes without taking control of the slice
|
|
76
|
+
// (overriding the table's own `onColumnVisibilityChange` option would suppress
|
|
77
|
+
// internal updates). The atom's `subscribe` is an explicit observer that runs
|
|
78
|
+
// the callback outside Svelte's dependency tracking, so consumer-side reads
|
|
79
|
+
// (e.g. a persisted-state proxy the callback writes into) can never become
|
|
80
|
+
// dependencies that re-trigger the notification — the failure mode of
|
|
81
|
+
// observing via $effect. The initial-replay guard compares by reference:
|
|
82
|
+
// table state updates are immutable, so only the subscription's initial
|
|
83
|
+
// emission (if the atom flavor emits one) can match the snapshot.
|
|
78
84
|
if (options.onColumnVisibilityChange) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (first) {
|
|
83
|
-
first = false;
|
|
85
|
+
const initialVisibility = table.atoms.columnVisibility.get();
|
|
86
|
+
const subscription = table.atoms.columnVisibility.subscribe((visibility) => {
|
|
87
|
+
if (visibility === initialVisibility)
|
|
84
88
|
return;
|
|
85
|
-
}
|
|
86
89
|
options.onColumnVisibilityChange?.(visibility);
|
|
87
90
|
});
|
|
91
|
+
onDestroy(() => subscription.unsubscribe());
|
|
88
92
|
}
|
|
89
93
|
return table;
|
|
90
94
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,8 +25,6 @@ export { default as AlertDialog } from './components/dialog/alert-dialog.svelte'
|
|
|
25
25
|
export type { AlertDialogProps } from './components/dialog/dialog.types';
|
|
26
26
|
export * as DataTable from './components/data-table-v9';
|
|
27
27
|
export * as VirtualDataTable from './components/data-table-v9/virtual';
|
|
28
|
-
export * as DataTableV8 from './components/data-table-v8';
|
|
29
|
-
export * as VirtualDataTableV8 from './components/data-table-v8/virtual';
|
|
30
28
|
export * as Drawer from './components/drawer';
|
|
31
29
|
export { default as FileUploadDropzone } from './components/file-upload/file-upload-dropzone.svelte';
|
|
32
30
|
export { default as FileUpload } from './components/file-upload/file-upload.svelte';
|
package/dist/index.js
CHANGED
|
@@ -19,8 +19,6 @@ export * as Dialog from './components/dialog';
|
|
|
19
19
|
export { default as AlertDialog } from './components/dialog/alert-dialog.svelte';
|
|
20
20
|
export * as DataTable from './components/data-table-v9';
|
|
21
21
|
export * as VirtualDataTable from './components/data-table-v9/virtual';
|
|
22
|
-
export * as DataTableV8 from './components/data-table-v8';
|
|
23
|
-
export * as VirtualDataTableV8 from './components/data-table-v8/virtual';
|
|
24
22
|
export * as Drawer from './components/drawer';
|
|
25
23
|
export { default as FileUploadDropzone } from './components/file-upload/file-upload-dropzone.svelte';
|
|
26
24
|
export { default as FileUpload } from './components/file-upload/file-upload.svelte';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "compote-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev --open",
|
|
@@ -40,26 +40,14 @@
|
|
|
40
40
|
"types": "./dist/components/data-table-v9/virtual/index.d.ts",
|
|
41
41
|
"svelte": "./dist/components/data-table-v9/virtual/index.js"
|
|
42
42
|
},
|
|
43
|
-
"./data-table-v8": {
|
|
44
|
-
"types": "./dist/components/data-table-v8/index.d.ts",
|
|
45
|
-
"svelte": "./dist/components/data-table-v8/index.js"
|
|
46
|
-
},
|
|
47
|
-
"./data-table-v8/virtual": {
|
|
48
|
-
"types": "./dist/components/data-table-v8/virtual/index.d.ts",
|
|
49
|
-
"svelte": "./dist/components/data-table-v8/virtual/index.js"
|
|
50
|
-
},
|
|
51
43
|
"./theme.css": "./dist/theme.css"
|
|
52
44
|
},
|
|
53
45
|
"peerDependencies": {
|
|
54
46
|
"@tanstack/svelte-table": ">=9.0.0-beta.6 <10",
|
|
55
|
-
"@tanstack/table-core": ">=8.0.0",
|
|
56
47
|
"@tanstack/svelte-virtual": ">=3.0.0",
|
|
57
48
|
"svelte": "^5.0.0"
|
|
58
49
|
},
|
|
59
50
|
"peerDependenciesMeta": {
|
|
60
|
-
"@tanstack/table-core": {
|
|
61
|
-
"optional": true
|
|
62
|
-
},
|
|
63
51
|
"@tanstack/svelte-virtual": {
|
|
64
52
|
"optional": true
|
|
65
53
|
}
|
|
@@ -70,28 +58,27 @@
|
|
|
70
58
|
"@iconify-json/ph": "^1.2.2",
|
|
71
59
|
"@sveltejs/adapter-auto": "^7.0.0",
|
|
72
60
|
"@sveltejs/adapter-cloudflare": "^7.2.8",
|
|
73
|
-
"@sveltejs/kit": "^2.
|
|
61
|
+
"@sveltejs/kit": "^2.65.0",
|
|
74
62
|
"@sveltejs/package": "^2.5.8",
|
|
75
63
|
"@sveltejs/vite-plugin-svelte": "7.1.2",
|
|
76
64
|
"@tailwindcss/vite": "^4.2.4",
|
|
77
65
|
"@tanstack/svelte-table": "9.0.0-beta.6",
|
|
78
66
|
"@tanstack/svelte-virtual": "^3.13.28",
|
|
79
|
-
"@tanstack/table-core": "^8.21.3",
|
|
80
67
|
"@types/node": "^22.19.18",
|
|
81
68
|
"eslint": "^10.4.1",
|
|
82
69
|
"eslint-config-prettier": "^10.1.8",
|
|
83
70
|
"eslint-plugin-svelte": "^3.19.0",
|
|
84
71
|
"globals": "^17.5.0",
|
|
85
|
-
"prettier": "^3.8.
|
|
72
|
+
"prettier": "^3.8.4",
|
|
86
73
|
"prettier-plugin-svelte": "^4.1.0",
|
|
87
74
|
"prettier-plugin-tailwindcss": "^0.8.0",
|
|
88
75
|
"publint": "^0.3.21",
|
|
89
|
-
"svelte": "^5.56.
|
|
76
|
+
"svelte": "^5.56.3",
|
|
90
77
|
"svelte-check": "^4.6.0",
|
|
91
78
|
"tailwindcss": "^4.2.4",
|
|
92
79
|
"tw-animate-css": "^1.4.0",
|
|
93
80
|
"typescript": "^6.0.3",
|
|
94
|
-
"typescript-eslint": "^8.
|
|
81
|
+
"typescript-eslint": "^8.61.0",
|
|
95
82
|
"unplugin-icons": "^23.0.1",
|
|
96
83
|
"vite": "^8.0.16"
|
|
97
84
|
},
|
|
@@ -99,7 +86,7 @@
|
|
|
99
86
|
"svelte"
|
|
100
87
|
],
|
|
101
88
|
"dependencies": {
|
|
102
|
-
"@ark-ui/svelte": "^5.22.
|
|
89
|
+
"@ark-ui/svelte": "^5.22.1",
|
|
103
90
|
"@fontsource-variable/nunito-sans": "^5.2.7",
|
|
104
91
|
"@iconify/svelte": "^5.2.1",
|
|
105
92
|
"@internationalized/date": "^3.12.2",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { RowData } from '@tanstack/table-core';
|
|
2
|
-
import type { DataTableAccessorFnColumn, DataTableAccessorKeyColumn, DataTableColumn, DataTableGroupColumn } from './types';
|
|
3
|
-
type AccessorKeyColumnOptions<T extends RowData> = Omit<DataTableAccessorKeyColumn<T>, 'accessorKey' | 'accessorFn' | 'columns'>;
|
|
4
|
-
type AccessorFnColumnOptions<T extends RowData> = Omit<DataTableAccessorFnColumn<T>, 'accessorFn' | 'accessorKey' | 'columns'>;
|
|
5
|
-
type GroupColumnOptions<T extends RowData> = Omit<DataTableGroupColumn<T>, 'columns' | 'accessorKey' | 'accessorFn' | 'cell' | 'cellComponent' | 'cellProps' | 'cellSnippet' | 'type' | 'formatOptions' | 'formatLocale'>;
|
|
6
|
-
export declare function createDataTableColumnHelper<T extends RowData>(): {
|
|
7
|
-
accessor<K extends Extract<keyof T, string>>(accessorKey: K, options: AccessorKeyColumnOptions<T>): DataTableAccessorKeyColumn<T>;
|
|
8
|
-
accessorFn(accessorFn: (row: T) => unknown, options: AccessorFnColumnOptions<T>): DataTableAccessorFnColumn<T>;
|
|
9
|
-
group(header: string, columns: DataTableColumn<T>[], options?: Omit<GroupColumnOptions<T>, "header">): DataTableGroupColumn<T>;
|
|
10
|
-
columns(columns: DataTableColumn<T>[]): DataTableColumn<T>[];
|
|
11
|
-
};
|
|
12
|
-
export {};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
const TYPE_DEFAULTS = {
|
|
2
|
-
number: { align: 'right', size: 120 },
|
|
3
|
-
currency: { align: 'right', size: 120 },
|
|
4
|
-
percent: { align: 'right', size: 100 },
|
|
5
|
-
date: { align: 'center', size: 110 },
|
|
6
|
-
time: { align: 'center', size: 80 },
|
|
7
|
-
'date-time': { align: 'center', size: 160 },
|
|
8
|
-
boolean: { align: 'center', size: 90 },
|
|
9
|
-
url: { align: 'center', size: 60, enableSorting: false }
|
|
10
|
-
};
|
|
11
|
-
function applyTypeDefaults(options) {
|
|
12
|
-
const defaults = options.type ? TYPE_DEFAULTS[options.type] : undefined;
|
|
13
|
-
if (!defaults)
|
|
14
|
-
return options;
|
|
15
|
-
return { ...defaults, ...options };
|
|
16
|
-
}
|
|
17
|
-
export function createDataTableColumnHelper() {
|
|
18
|
-
return {
|
|
19
|
-
accessor(accessorKey, options) {
|
|
20
|
-
return {
|
|
21
|
-
...applyTypeDefaults(options),
|
|
22
|
-
accessorKey
|
|
23
|
-
};
|
|
24
|
-
},
|
|
25
|
-
accessorFn(accessorFn, options) {
|
|
26
|
-
return {
|
|
27
|
-
...applyTypeDefaults(options),
|
|
28
|
-
accessorFn
|
|
29
|
-
};
|
|
30
|
-
},
|
|
31
|
-
group(header, columns, options = {}) {
|
|
32
|
-
return {
|
|
33
|
-
...options,
|
|
34
|
-
header,
|
|
35
|
-
columns
|
|
36
|
-
};
|
|
37
|
-
},
|
|
38
|
-
columns(columns) {
|
|
39
|
-
return columns;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type RowData, type TableOptions } from '@tanstack/table-core';
|
|
2
|
-
export declare function createSvelteTable<TData extends RowData>(options: TableOptions<TData>): import("@tanstack/table-core").Table<TData>;
|
|
3
|
-
type MaybeThunk<T extends object> = T | (() => T | null | undefined);
|
|
4
|
-
type Intersection<T extends readonly unknown[]> = (T extends [infer H, ...infer R] ? H & Intersection<R> : unknown) & {};
|
|
5
|
-
export declare function mergeObjects<Sources extends readonly MaybeThunk<any>[]>(...sources: Sources): Intersection<{
|
|
6
|
-
[K in keyof Sources]: Sources[K];
|
|
7
|
-
}>;
|
|
8
|
-
export {};
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { createTable } from '@tanstack/table-core';
|
|
2
|
-
export function createSvelteTable(options) {
|
|
3
|
-
const resolvedOptions = mergeObjects({
|
|
4
|
-
state: {},
|
|
5
|
-
onStateChange() { },
|
|
6
|
-
renderFallbackValue: null,
|
|
7
|
-
mergeOptions: (defaultOptions, options) => {
|
|
8
|
-
return mergeObjects(defaultOptions, options);
|
|
9
|
-
}
|
|
10
|
-
}, options);
|
|
11
|
-
const table = createTable(resolvedOptions);
|
|
12
|
-
let state = $state(table.initialState);
|
|
13
|
-
function updateOptions() {
|
|
14
|
-
table.setOptions(() => {
|
|
15
|
-
return mergeObjects(resolvedOptions, options, {
|
|
16
|
-
state: mergeObjects(() => state, options.state || {}),
|
|
17
|
-
onStateChange: (updater) => {
|
|
18
|
-
if (typeof updater === 'function')
|
|
19
|
-
state = updater(state);
|
|
20
|
-
else
|
|
21
|
-
state = mergeObjects(state, updater);
|
|
22
|
-
options.onStateChange?.(updater);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
updateOptions();
|
|
28
|
-
$effect.pre(() => {
|
|
29
|
-
updateOptions();
|
|
30
|
-
});
|
|
31
|
-
Object.defineProperty(table, '_svelteState', {
|
|
32
|
-
get() {
|
|
33
|
-
return state;
|
|
34
|
-
},
|
|
35
|
-
enumerable: false,
|
|
36
|
-
configurable: true
|
|
37
|
-
});
|
|
38
|
-
return table;
|
|
39
|
-
}
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
-
export function mergeObjects(...sources) {
|
|
42
|
-
const resolve = (src) => typeof src === 'function' ? (src() ?? undefined) : src;
|
|
43
|
-
const findSourceWithKey = (key) => {
|
|
44
|
-
for (let i = sources.length - 1; i >= 0; i--) {
|
|
45
|
-
const obj = resolve(sources[i]);
|
|
46
|
-
if (obj && key in obj)
|
|
47
|
-
return obj;
|
|
48
|
-
}
|
|
49
|
-
return undefined;
|
|
50
|
-
};
|
|
51
|
-
return new Proxy(Object.create(null), {
|
|
52
|
-
get(_, key) {
|
|
53
|
-
const src = findSourceWithKey(key);
|
|
54
|
-
return src?.[key];
|
|
55
|
-
},
|
|
56
|
-
has(_, key) {
|
|
57
|
-
return !!findSourceWithKey(key);
|
|
58
|
-
},
|
|
59
|
-
ownKeys() {
|
|
60
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
61
|
-
const all = new Set();
|
|
62
|
-
for (const s of sources) {
|
|
63
|
-
const obj = resolve(s);
|
|
64
|
-
if (obj) {
|
|
65
|
-
for (const k of Reflect.ownKeys(obj)) {
|
|
66
|
-
all.add(k);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return [...all];
|
|
71
|
-
},
|
|
72
|
-
getOwnPropertyDescriptor(_, key) {
|
|
73
|
-
const src = findSourceWithKey(key);
|
|
74
|
-
if (!src)
|
|
75
|
-
return undefined;
|
|
76
|
-
return {
|
|
77
|
-
configurable: true,
|
|
78
|
-
enumerable: true,
|
|
79
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
|
-
value: src[key],
|
|
81
|
-
writable: true
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { type ColumnPinningState, type ColumnResizeMode, type ColumnSizingState, type VisibilityState, type FilterFn, type Row, type RowData, type Table } from '@tanstack/table-core';
|
|
2
|
-
import type { DataTableColumn, DataTableLeafColumn } from './types';
|
|
3
|
-
declare module '@tanstack/table-core' {
|
|
4
|
-
interface FilterFns {
|
|
5
|
-
oneOf: FilterFn<unknown>;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export type DataTableInstance<T extends RowData> = Table<T>;
|
|
9
|
-
export type CreateDataTableOptions<T extends RowData> = {
|
|
10
|
-
data: T[];
|
|
11
|
-
columns: DataTableColumn<T>[];
|
|
12
|
-
columnResizeMode?: ColumnResizeMode;
|
|
13
|
-
initialState?: {
|
|
14
|
-
columnVisibility?: VisibilityState;
|
|
15
|
-
columnSizing?: ColumnSizingState;
|
|
16
|
-
columnPinning?: ColumnPinningState;
|
|
17
|
-
rowSelection?: Record<string, boolean>;
|
|
18
|
-
sorting?: {
|
|
19
|
-
id: string;
|
|
20
|
-
desc: boolean;
|
|
21
|
-
}[];
|
|
22
|
-
columnFilters?: {
|
|
23
|
-
id: string;
|
|
24
|
-
value: unknown;
|
|
25
|
-
}[];
|
|
26
|
-
};
|
|
27
|
-
getRowId?: (row: T, index: number, parent?: Row<T>) => string;
|
|
28
|
-
enableRowSelection?: boolean | ((row: Row<T>) => boolean);
|
|
29
|
-
enableMultiRowSelection?: boolean | ((row: Row<T>) => boolean);
|
|
30
|
-
enableSorting?: boolean;
|
|
31
|
-
debugTable?: boolean;
|
|
32
|
-
onColumnVisibilityChange?: (visibility: VisibilityState) => void;
|
|
33
|
-
};
|
|
34
|
-
export declare function createTable<T extends RowData>(options: CreateDataTableOptions<T>): Table<T>;
|
|
35
|
-
export declare function getColumnId<T extends RowData>(column: DataTableLeafColumn<T>): string;
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { getCoreRowModel, getSortedRowModel, getFilteredRowModel, getFacetedRowModel, getFacetedUniqueValues, getFacetedMinMaxValues } from '@tanstack/table-core';
|
|
2
|
-
import { useLocaleContext } from '@ark-ui/svelte/locale';
|
|
3
|
-
import { createSvelteTable } from './create-svelte-table.svelte';
|
|
4
|
-
import { renderComponent, renderSnippet } from './render-helpers';
|
|
5
|
-
function oneOfFilterFn(row, columnId, filterValue) {
|
|
6
|
-
return filterValue.includes(String(row.getValue(columnId)));
|
|
7
|
-
}
|
|
8
|
-
oneOfFilterFn.autoRemove = (val) => !Array.isArray(val) || val.length === 0;
|
|
9
|
-
export function createTable(options) {
|
|
10
|
-
const localeCtx = useLocaleContext();
|
|
11
|
-
const initialColumnVisibility = {
|
|
12
|
-
...createColumnVisibility(options.columns),
|
|
13
|
-
...options.initialState?.columnVisibility
|
|
14
|
-
};
|
|
15
|
-
// Recompute the resolved column defs only when the source columns change.
|
|
16
|
-
// $derived keeps the reference stable between changes so TanStack's column
|
|
17
|
-
// memoization isn't invalidated on every access. Pass `columns` through a
|
|
18
|
-
// getter (like `data`) to make adding/removing/reordering columns reactive.
|
|
19
|
-
const columnDefs = $derived(createColumns(options.columns, localeCtx));
|
|
20
|
-
const table = createSvelteTable({
|
|
21
|
-
get data() {
|
|
22
|
-
return options.data;
|
|
23
|
-
},
|
|
24
|
-
get columns() {
|
|
25
|
-
return columnDefs;
|
|
26
|
-
},
|
|
27
|
-
getCoreRowModel: getCoreRowModel(),
|
|
28
|
-
getSortedRowModel: getSortedRowModel(),
|
|
29
|
-
getFilteredRowModel: getFilteredRowModel(),
|
|
30
|
-
getFacetedRowModel: getFacetedRowModel(),
|
|
31
|
-
getFacetedUniqueValues: getFacetedUniqueValues(),
|
|
32
|
-
getFacetedMinMaxValues: getFacetedMinMaxValues(),
|
|
33
|
-
columnResizeMode: options.columnResizeMode,
|
|
34
|
-
getRowId: options.getRowId,
|
|
35
|
-
enableRowSelection: options.enableRowSelection ?? false,
|
|
36
|
-
enableMultiRowSelection: options.enableMultiRowSelection,
|
|
37
|
-
enableSorting: options.enableSorting,
|
|
38
|
-
debugTable: options.debugTable,
|
|
39
|
-
filterFns: {
|
|
40
|
-
oneOf: oneOfFilterFn
|
|
41
|
-
},
|
|
42
|
-
onColumnVisibilityChange: (updater) => {
|
|
43
|
-
// Without this, overriding onColumnVisibilityChange bypasses makeStateUpdater,
|
|
44
|
-
// so createSvelteTable's $state never updates and Svelte doesn't re-render.
|
|
45
|
-
table.options.onStateChange?.((old) => {
|
|
46
|
-
const columnVisibility = typeof updater === 'function' ? updater(old.columnVisibility) : updater;
|
|
47
|
-
options.onColumnVisibilityChange?.(columnVisibility);
|
|
48
|
-
return {
|
|
49
|
-
...old,
|
|
50
|
-
columnVisibility
|
|
51
|
-
};
|
|
52
|
-
});
|
|
53
|
-
},
|
|
54
|
-
initialState: {
|
|
55
|
-
columnVisibility: initialColumnVisibility,
|
|
56
|
-
columnSizing: {
|
|
57
|
-
...createColumnSizing(options.columns),
|
|
58
|
-
...options.initialState?.columnSizing
|
|
59
|
-
},
|
|
60
|
-
columnPinning: options.initialState?.columnPinning ?? createColumnPinning(options.columns),
|
|
61
|
-
rowSelection: options.initialState?.rowSelection ?? {},
|
|
62
|
-
sorting: options.initialState?.sorting ?? [],
|
|
63
|
-
columnFilters: options.initialState?.columnFilters ?? []
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
return table;
|
|
67
|
-
}
|
|
68
|
-
function createColumnVisibility(columns) {
|
|
69
|
-
return getLeafColumns(columns).reduce((visibility, column) => {
|
|
70
|
-
visibility[getColumnId(column)] = true;
|
|
71
|
-
return visibility;
|
|
72
|
-
}, {});
|
|
73
|
-
}
|
|
74
|
-
function createColumnSizing(columns) {
|
|
75
|
-
return getLeafColumns(columns).reduce((sizes, column) => {
|
|
76
|
-
if (typeof column.size === 'number') {
|
|
77
|
-
sizes[getColumnId(column)] = column.size;
|
|
78
|
-
}
|
|
79
|
-
return sizes;
|
|
80
|
-
}, {});
|
|
81
|
-
}
|
|
82
|
-
function createColumnPinning(columns) {
|
|
83
|
-
const leafCols = getLeafColumns(columns);
|
|
84
|
-
return {
|
|
85
|
-
left: leafCols.filter((c) => c.pinned === 'left').map(getColumnId),
|
|
86
|
-
right: leafCols.filter((c) => c.pinned === 'right').map(getColumnId)
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
function createColumns(columns, localeCtx) {
|
|
90
|
-
return columns.map((column) => {
|
|
91
|
-
if (isGroupColumn(column)) {
|
|
92
|
-
return {
|
|
93
|
-
id: getGroupColumnId(column),
|
|
94
|
-
header: column.header,
|
|
95
|
-
columns: createColumns(column.columns, localeCtx),
|
|
96
|
-
meta: {
|
|
97
|
-
align: column.align
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
const columnId = getColumnId(column);
|
|
102
|
-
const derivedFilterFn = column.filterFn ?? getFilterFnForType(column.type);
|
|
103
|
-
const columnDef = {
|
|
104
|
-
id: columnId,
|
|
105
|
-
header: column.header,
|
|
106
|
-
size: column.size,
|
|
107
|
-
minSize: column.minSize,
|
|
108
|
-
maxSize: column.maxSize,
|
|
109
|
-
enableResizing: column.enableResizing,
|
|
110
|
-
enableHiding: getColumnEnableHiding(column, columnId),
|
|
111
|
-
enableSorting: column.enableSorting,
|
|
112
|
-
sortDescFirst: column.sortDescFirst,
|
|
113
|
-
enableColumnFilter: column.enableColumnFilter,
|
|
114
|
-
...(derivedFilterFn !== undefined ? { filterFn: derivedFilterFn } : {}),
|
|
115
|
-
meta: {
|
|
116
|
-
align: column.align,
|
|
117
|
-
type: column.type,
|
|
118
|
-
formatOptions: column.formatOptions,
|
|
119
|
-
formatLocale: column.formatLocale,
|
|
120
|
-
grow: column.grow,
|
|
121
|
-
sum: column.sum,
|
|
122
|
-
footer: column.footer
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
if (typeof column.accessorFn === 'function') {
|
|
126
|
-
return {
|
|
127
|
-
...columnDef,
|
|
128
|
-
accessorFn: column.accessorFn,
|
|
129
|
-
cell: (context) => formatCellValue(column, context.getValue(), context.row.original, localeCtx)
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
...columnDef,
|
|
134
|
-
accessorKey: column.accessorKey,
|
|
135
|
-
cell: (context) => formatCellValue(column, context.getValue(), context.row.original, localeCtx)
|
|
136
|
-
};
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
function isGroupColumn(column) {
|
|
140
|
-
return Array.isArray(column.columns);
|
|
141
|
-
}
|
|
142
|
-
function getLeafColumns(columns) {
|
|
143
|
-
return columns.flatMap((column) => isGroupColumn(column) ? getLeafColumns(column.columns) : column);
|
|
144
|
-
}
|
|
145
|
-
function getGroupColumnId(column) {
|
|
146
|
-
return column.id ?? column.header;
|
|
147
|
-
}
|
|
148
|
-
function getColumnEnableHiding(column, columnId) {
|
|
149
|
-
if (column.enableHiding !== undefined)
|
|
150
|
-
return column.enableHiding;
|
|
151
|
-
if (columnId === 'id')
|
|
152
|
-
return false;
|
|
153
|
-
return undefined;
|
|
154
|
-
}
|
|
155
|
-
export function getColumnId(column) {
|
|
156
|
-
if (column.id !== undefined)
|
|
157
|
-
return column.id;
|
|
158
|
-
if ('accessorKey' in column && column.accessorKey !== undefined)
|
|
159
|
-
return column.accessorKey;
|
|
160
|
-
throw new Error('DataTableColumn with accessorFn requires an id.');
|
|
161
|
-
}
|
|
162
|
-
const TYPE_FORMAT_DEFAULTS = {
|
|
163
|
-
currency: { style: 'currency', currency: 'USD' },
|
|
164
|
-
percent: { style: 'percent' },
|
|
165
|
-
number: {}
|
|
166
|
-
};
|
|
167
|
-
const TYPE_DATE_FORMAT_DEFAULTS = {
|
|
168
|
-
date: { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
169
|
-
time: { hour: '2-digit', minute: '2-digit' },
|
|
170
|
-
'date-time': {
|
|
171
|
-
day: '2-digit',
|
|
172
|
-
month: '2-digit',
|
|
173
|
-
year: 'numeric',
|
|
174
|
-
hour: '2-digit',
|
|
175
|
-
minute: '2-digit'
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
function getFilterFnForType(type) {
|
|
179
|
-
switch (type) {
|
|
180
|
-
case 'number':
|
|
181
|
-
case 'currency':
|
|
182
|
-
case 'percent':
|
|
183
|
-
return 'inNumberRange';
|
|
184
|
-
case 'boolean':
|
|
185
|
-
return 'equals';
|
|
186
|
-
case 'select':
|
|
187
|
-
return 'oneOf';
|
|
188
|
-
default:
|
|
189
|
-
return undefined;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
function applyTypeFormat(column, value, localeCtx) {
|
|
193
|
-
if (value === null || value === undefined || value === '')
|
|
194
|
-
return undefined;
|
|
195
|
-
const numDefaults = column.type ? TYPE_FORMAT_DEFAULTS[column.type] : undefined;
|
|
196
|
-
if (numDefaults !== undefined) {
|
|
197
|
-
const locale = column.formatLocale ?? localeCtx().locale;
|
|
198
|
-
return new Intl.NumberFormat(locale, {
|
|
199
|
-
...numDefaults,
|
|
200
|
-
...column.formatOptions
|
|
201
|
-
}).format(Number(value));
|
|
202
|
-
}
|
|
203
|
-
if (column.type === 'date' || column.type === 'time' || column.type === 'date-time') {
|
|
204
|
-
const dateValue = value instanceof Date ? value : new Date(value);
|
|
205
|
-
if (isNaN(dateValue.getTime()))
|
|
206
|
-
return undefined;
|
|
207
|
-
const locale = column.formatLocale ?? localeCtx().locale;
|
|
208
|
-
return new Intl.DateTimeFormat(locale, {
|
|
209
|
-
...TYPE_DATE_FORMAT_DEFAULTS[column.type],
|
|
210
|
-
...column.formatOptions
|
|
211
|
-
}).format(dateValue);
|
|
212
|
-
}
|
|
213
|
-
if (column.type === 'boolean')
|
|
214
|
-
return value ? 'Yes' : 'No';
|
|
215
|
-
return value;
|
|
216
|
-
}
|
|
217
|
-
function formatCellValue(column, value, row, localeCtx) {
|
|
218
|
-
if (column.cellComponent) {
|
|
219
|
-
return renderComponent(column.cellComponent, getCellComponentProps(column, value, row));
|
|
220
|
-
}
|
|
221
|
-
if (column.cellSnippet) {
|
|
222
|
-
return renderSnippet(column.cellSnippet, { value, row });
|
|
223
|
-
}
|
|
224
|
-
const rendered = column.cell
|
|
225
|
-
? column.cell(value, row)
|
|
226
|
-
: applyTypeFormat(column, value, localeCtx);
|
|
227
|
-
if (rendered === null || rendered === undefined || rendered === '') {
|
|
228
|
-
return '-';
|
|
229
|
-
}
|
|
230
|
-
return String(rendered);
|
|
231
|
-
}
|
|
232
|
-
function getCellComponentProps(column, value, row) {
|
|
233
|
-
return column.cellProps ? column.cellProps(value, row) : { value, row };
|
|
234
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
<script lang="ts" generics="T extends RowData">
|
|
2
|
-
import type { Column, Row, RowData } from '@tanstack/table-core';
|
|
3
|
-
import { useLocaleContext } from '@ark-ui/svelte/locale';
|
|
4
|
-
import { cn } from 'tailwind-variants';
|
|
5
|
-
import type { DataTableInstance } from './data-table-utils';
|
|
6
|
-
import {
|
|
7
|
-
alignClass,
|
|
8
|
-
formatColumnFooter,
|
|
9
|
-
getColumnMeta,
|
|
10
|
-
getPinningStyle,
|
|
11
|
-
justifyClass,
|
|
12
|
-
joinStyles,
|
|
13
|
-
virtualColumnSizeStyle,
|
|
14
|
-
virtualGrowColumnSizeStyle,
|
|
15
|
-
virtualSelectionColumnSizeStyle
|
|
16
|
-
} from './data-table-utils';
|
|
17
|
-
|
|
18
|
-
type Props = {
|
|
19
|
-
table: DataTableInstance<T>;
|
|
20
|
-
visibleLeafColumns: Column<T, unknown>[];
|
|
21
|
-
rows: Row<T>[];
|
|
22
|
-
isRowSelectionEnabled: boolean;
|
|
23
|
-
hasGrowColumn: boolean;
|
|
24
|
-
isVirtual?: boolean;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
let {
|
|
28
|
-
table,
|
|
29
|
-
visibleLeafColumns,
|
|
30
|
-
rows,
|
|
31
|
-
isRowSelectionEnabled,
|
|
32
|
-
hasGrowColumn,
|
|
33
|
-
isVirtual = false
|
|
34
|
-
}: Props = $props();
|
|
35
|
-
|
|
36
|
-
const localeCtx = useLocaleContext();
|
|
37
|
-
const locale = $derived(localeCtx().locale);
|
|
38
|
-
|
|
39
|
-
function footCellStyle(column: Column<T, unknown>) {
|
|
40
|
-
const meta = getColumnMeta(column.columnDef);
|
|
41
|
-
if (!isVirtual) return getPinningStyle(column, table, true, isRowSelectionEnabled);
|
|
42
|
-
return joinStyles(
|
|
43
|
-
meta?.grow ? virtualGrowColumnSizeStyle() : virtualColumnSizeStyle(column.getSize()),
|
|
44
|
-
getPinningStyle(column, table, true, isRowSelectionEnabled)
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function selectionCellStyle() {
|
|
49
|
-
return isVirtual
|
|
50
|
-
? joinStyles(
|
|
51
|
-
virtualSelectionColumnSizeStyle(),
|
|
52
|
-
'min-width: 40px',
|
|
53
|
-
'max-width: 40px',
|
|
54
|
-
'position: sticky',
|
|
55
|
-
'left: 0',
|
|
56
|
-
'z-index: 15'
|
|
57
|
-
)
|
|
58
|
-
: 'width: 40px; min-width: 40px; max-width: 40px; position: sticky; left: 0; z-index: 15';
|
|
59
|
-
}
|
|
60
|
-
</script>
|
|
61
|
-
|
|
62
|
-
<tfoot
|
|
63
|
-
class="sticky bottom-0 z-20 bg-surface-2 text-ink-dim"
|
|
64
|
-
style={isVirtual ? 'display: grid; position: sticky; bottom: 0; z-index: 20' : undefined}
|
|
65
|
-
>
|
|
66
|
-
<tr class="h-9" style={isVirtual ? 'display: flex; width: 100%' : undefined}>
|
|
67
|
-
{#if isRowSelectionEnabled}
|
|
68
|
-
<td
|
|
69
|
-
class={cn(
|
|
70
|
-
'h-9 border-t border-surface-3 bg-surface-2 px-3 py-0',
|
|
71
|
-
isVirtual && 'flex items-center'
|
|
72
|
-
)}
|
|
73
|
-
style={selectionCellStyle()}
|
|
74
|
-
></td>
|
|
75
|
-
{/if}
|
|
76
|
-
{#each visibleLeafColumns as column (column.id)}
|
|
77
|
-
{@const meta = getColumnMeta(column.columnDef)}
|
|
78
|
-
{@const values = rows.map((row) => row.getValue(column.id))}
|
|
79
|
-
{@const footerText = formatColumnFooter(meta ?? {}, values, locale)}
|
|
80
|
-
<td
|
|
81
|
-
class={cn(
|
|
82
|
-
'h-9 truncate border-t border-surface-3 bg-surface-2 px-3 py-0 align-middle text-sm font-medium',
|
|
83
|
-
alignClass(meta?.align),
|
|
84
|
-
isVirtual && 'flex items-center',
|
|
85
|
-
isVirtual && justifyClass(meta?.align)
|
|
86
|
-
)}
|
|
87
|
-
style={footCellStyle(column)}
|
|
88
|
-
>
|
|
89
|
-
{footerText ?? ''}
|
|
90
|
-
</td>
|
|
91
|
-
{/each}
|
|
92
|
-
{#if !isVirtual && !hasGrowColumn}
|
|
93
|
-
<td aria-hidden="true" class="h-9 border-t border-surface-3 bg-surface-2 p-0"></td>
|
|
94
|
-
{/if}
|
|
95
|
-
</tr>
|
|
96
|
-
</tfoot>
|