compote-ui 0.56.1 → 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.
Files changed (42) hide show
  1. package/dist/components/data-table-v9/create-table.svelte.js +15 -14
  2. package/dist/index.d.ts +0 -2
  3. package/dist/index.js +0 -2
  4. package/package.json +6 -19
  5. package/dist/components/data-table-v8/column-helper.d.ts +0 -12
  6. package/dist/components/data-table-v8/column-helper.js +0 -42
  7. package/dist/components/data-table-v8/create-svelte-table.svelte.d.ts +0 -8
  8. package/dist/components/data-table-v8/create-svelte-table.svelte.js +0 -85
  9. package/dist/components/data-table-v8/create-table.svelte.d.ts +0 -35
  10. package/dist/components/data-table-v8/create-table.svelte.js +0 -234
  11. package/dist/components/data-table-v8/data-table-foot.svelte +0 -96
  12. package/dist/components/data-table-v8/data-table-foot.svelte.d.ts +0 -33
  13. package/dist/components/data-table-v8/data-table-head.svelte +0 -196
  14. package/dist/components/data-table-v8/data-table-head.svelte.d.ts +0 -35
  15. package/dist/components/data-table-v8/data-table-title.svelte +0 -16
  16. package/dist/components/data-table-v8/data-table-title.svelte.d.ts +0 -10
  17. package/dist/components/data-table-v8/data-table-utils.d.ts +0 -32
  18. package/dist/components/data-table-v8/data-table-utils.js +0 -160
  19. package/dist/components/data-table-v8/data-table.svelte +0 -273
  20. package/dist/components/data-table-v8/data-table.svelte.d.ts +0 -41
  21. package/dist/components/data-table-v8/flex-render.svelte +0 -35
  22. package/dist/components/data-table-v8/flex-render.svelte.d.ts +0 -28
  23. package/dist/components/data-table-v8/index.d.ts +0 -12
  24. package/dist/components/data-table-v8/index.js +0 -10
  25. package/dist/components/data-table-v8/render-helpers.d.ts +0 -13
  26. package/dist/components/data-table-v8/render-helpers.js +0 -23
  27. package/dist/components/data-table-v8/toolbar/data-table-column-filter.svelte +0 -373
  28. package/dist/components/data-table-v8/toolbar/data-table-column-filter.svelte.d.ts +0 -29
  29. package/dist/components/data-table-v8/toolbar/data-table-column-visibility.svelte +0 -73
  30. package/dist/components/data-table-v8/toolbar/data-table-column-visibility.svelte.d.ts +0 -29
  31. package/dist/components/data-table-v8/toolbar/data-table-search.svelte +0 -57
  32. package/dist/components/data-table-v8/toolbar/data-table-search.svelte.d.ts +0 -31
  33. package/dist/components/data-table-v8/toolbar/data-table-toolbar.svelte +0 -39
  34. package/dist/components/data-table-v8/toolbar/data-table-toolbar.svelte.d.ts +0 -12
  35. package/dist/components/data-table-v8/types.d.ts +0 -73
  36. package/dist/components/data-table-v8/types.js +0 -1
  37. package/dist/components/data-table-v8/virtual/data-table-virtual-rows.svelte +0 -176
  38. package/dist/components/data-table-v8/virtual/data-table-virtual-rows.svelte.d.ts +0 -40
  39. package/dist/components/data-table-v8/virtual/data-table-virtualized.svelte +0 -146
  40. package/dist/components/data-table-v8/virtual/data-table-virtualized.svelte.d.ts +0 -41
  41. package/dist/components/data-table-v8/virtual/index.d.ts +0 -3
  42. 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,22 +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
- // v9 setters are atom-aware, so we observe the reactive state instead of
77
- // overriding `onColumnVisibilityChange` (which would suppress internal updates).
78
- // The callback runs untracked: it must only depend on the visibility atom,
79
- // otherwise consumer-side reads (e.g. a persisted-state proxy the callback
80
- // writes into) become dependencies of this effect and re-trigger it forever.
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.
81
84
  if (options.onColumnVisibilityChange) {
82
- let first = true;
83
- $effect(() => {
84
- const visibility = table.atoms.columnVisibility.get();
85
- if (first) {
86
- first = false;
85
+ const initialVisibility = table.atoms.columnVisibility.get();
86
+ const subscription = table.atoms.columnVisibility.subscribe((visibility) => {
87
+ if (visibility === initialVisibility)
87
88
  return;
88
- }
89
- untrack(() => options.onColumnVisibilityChange?.(visibility));
89
+ options.onColumnVisibilityChange?.(visibility);
90
90
  });
91
+ onDestroy(() => subscription.unsubscribe());
91
92
  }
92
93
  return table;
93
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.56.1",
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.63.0",
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.3",
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.2",
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.60.1",
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.0",
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>