compote-ui 0.55.3 → 0.56.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-v8/create-table.svelte.js +8 -1
- package/dist/components/data-table-v9/column-helper.d.ts +12 -0
- package/dist/components/data-table-v9/column-helper.js +42 -0
- package/dist/components/data-table-v9/create-table.svelte.d.ts +42 -0
- package/dist/components/data-table-v9/create-table.svelte.js +248 -0
- package/dist/components/data-table-v9/data-table-cell-content.svelte +66 -0
- package/dist/components/data-table-v9/data-table-cell-content.svelte.d.ts +28 -0
- package/dist/components/data-table-v9/data-table-foot.svelte +111 -0
- package/dist/components/data-table-v9/data-table-foot.svelte.d.ts +32 -0
- package/dist/components/{data-table/data-table-head.svelte.md → data-table-v9/data-table-head.svelte} +47 -39
- package/dist/components/data-table-v9/data-table-head.svelte.d.ts +32 -0
- package/dist/components/data-table-v9/data-table-title.svelte.d.ts +10 -0
- package/dist/components/data-table-v9/data-table-utils.d.ts +53 -0
- package/dist/components/data-table-v9/data-table-utils.js +181 -0
- package/dist/components/data-table-v9/data-table.svelte +151 -0
- package/dist/components/data-table-v9/data-table.svelte.d.ts +41 -0
- package/dist/components/data-table-v9/features.d.ts +12 -0
- package/dist/components/data-table-v9/features.js +14 -0
- package/dist/components/data-table-v9/index.d.ts +11 -0
- package/dist/components/data-table-v9/index.js +9 -0
- package/dist/components/data-table-v9/table-view-state.svelte.d.ts +74 -0
- package/dist/components/data-table-v9/table-view-state.svelte.js +182 -0
- package/dist/components/data-table-v9/toolbar/data-table-column-filter.svelte +380 -0
- package/dist/components/data-table-v9/toolbar/data-table-column-filter.svelte.d.ts +29 -0
- package/dist/components/data-table-v9/toolbar/data-table-column-visibility.svelte +73 -0
- package/dist/components/data-table-v9/toolbar/data-table-column-visibility.svelte.d.ts +29 -0
- package/dist/components/data-table-v9/toolbar/data-table-search.svelte +58 -0
- package/dist/components/data-table-v9/toolbar/data-table-search.svelte.d.ts +32 -0
- package/dist/components/{data-table/data-table-toolbar.svelte.md → data-table-v9/toolbar/data-table-toolbar.svelte} +14 -15
- package/dist/components/data-table-v9/toolbar/data-table-toolbar.svelte.d.ts +12 -0
- package/dist/components/data-table-v9/types.d.ts +74 -0
- package/dist/components/data-table-v9/types.js +1 -0
- package/dist/components/data-table-v9/virtual/data-table-virtual-rows.svelte +131 -0
- package/dist/components/data-table-v9/virtual/data-table-virtual-rows.svelte.d.ts +40 -0
- package/dist/components/data-table-v9/virtual/data-table-virtualized.svelte +79 -0
- package/dist/components/data-table-v9/virtual/data-table-virtualized.svelte.d.ts +41 -0
- package/dist/components/data-table-v9/virtual/index.d.ts +3 -0
- package/dist/components/data-table-v9/virtual/index.js +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/package.json +12 -2
- package/dist/components/data-table/column-helper.ts.md +0 -96
- package/dist/components/data-table/create-table.ts.md +0 -386
- package/dist/components/data-table/data-table-column-filter.svelte.md +0 -249
- package/dist/components/data-table/data-table-column-visibility.svelte.md +0 -74
- package/dist/components/data-table/data-table-new.svelte.md +0 -245
- package/dist/components/data-table/data-table-utils.ts.md +0 -179
- package/dist/components/data-table/data-table-virtual-rows.svelte.md +0 -171
- package/dist/components/data-table/data-table-virtualized.svelte.md +0 -108
- package/dist/components/data-table/data-table.svelte.md +0 -214
- package/dist/components/data-table/index.ts.md +0 -22
- package/dist/components/data-table/types.ts.md +0 -101
- package/dist/components/data-table/virtual/index.ts.md +0 -26
- /package/dist/components/{data-table/data-table-title.svelte.md → data-table-v9/data-table-title.svelte} +0 -0
|
@@ -12,11 +12,18 @@ export function createTable(options) {
|
|
|
12
12
|
...createColumnVisibility(options.columns),
|
|
13
13
|
...options.initialState?.columnVisibility
|
|
14
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));
|
|
15
20
|
const table = createSvelteTable({
|
|
16
21
|
get data() {
|
|
17
22
|
return options.data;
|
|
18
23
|
},
|
|
19
|
-
columns
|
|
24
|
+
get columns() {
|
|
25
|
+
return columnDefs;
|
|
26
|
+
},
|
|
20
27
|
getCoreRowModel: getCoreRowModel(),
|
|
21
28
|
getSortedRowModel: getSortedRowModel(),
|
|
22
29
|
getFilteredRowModel: getFilteredRowModel(),
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RowData } from '@tanstack/svelte-table';
|
|
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 {};
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type ColumnPinningState, type ColumnResizeMode, type ColumnSizingState, type ColumnVisibilityState, type Row, type RowData, type RowSelectionState } from '@tanstack/svelte-table';
|
|
2
|
+
import { type DataTableFeatures } from './features';
|
|
3
|
+
import { type DataTableInstance } from './data-table-utils';
|
|
4
|
+
import type { DataTableColumn, DataTableLeafColumn } from './types';
|
|
5
|
+
export type { DataTableInstance };
|
|
6
|
+
export type CreateDataTableOptions<T extends RowData> = {
|
|
7
|
+
data: T[];
|
|
8
|
+
columns: DataTableColumn<T>[];
|
|
9
|
+
columnResizeMode?: ColumnResizeMode;
|
|
10
|
+
initialState?: {
|
|
11
|
+
columnVisibility?: ColumnVisibilityState;
|
|
12
|
+
columnSizing?: ColumnSizingState;
|
|
13
|
+
columnPinning?: ColumnPinningState;
|
|
14
|
+
rowSelection?: RowSelectionState;
|
|
15
|
+
sorting?: {
|
|
16
|
+
id: string;
|
|
17
|
+
desc: boolean;
|
|
18
|
+
}[];
|
|
19
|
+
columnFilters?: {
|
|
20
|
+
id: string;
|
|
21
|
+
value: unknown;
|
|
22
|
+
}[];
|
|
23
|
+
};
|
|
24
|
+
getRowId?: (row: T, index: number, parent?: Row<DataTableFeatures, T>) => string;
|
|
25
|
+
enableRowSelection?: boolean | ((row: Row<DataTableFeatures, T>) => boolean);
|
|
26
|
+
enableMultiRowSelection?: boolean | ((row: Row<DataTableFeatures, T>) => boolean);
|
|
27
|
+
enableSorting?: boolean;
|
|
28
|
+
debugTable?: boolean;
|
|
29
|
+
onColumnVisibilityChange?: (visibility: ColumnVisibilityState) => void;
|
|
30
|
+
};
|
|
31
|
+
export declare function createTable<T extends RowData>(options: CreateDataTableOptions<T>): import("@tanstack/svelte-table").SvelteTable<{
|
|
32
|
+
rowSortingFeature: import("@tanstack/svelte-table").TableFeature;
|
|
33
|
+
rowSelectionFeature: import("@tanstack/svelte-table").TableFeature;
|
|
34
|
+
columnFilteringFeature: import("@tanstack/svelte-table").TableFeature;
|
|
35
|
+
columnFacetingFeature: import("@tanstack/svelte-table").TableFeature;
|
|
36
|
+
globalFilteringFeature: import("@tanstack/svelte-table").TableFeature;
|
|
37
|
+
columnVisibilityFeature: import("@tanstack/svelte-table").TableFeature;
|
|
38
|
+
columnPinningFeature: import("@tanstack/svelte-table").TableFeature;
|
|
39
|
+
columnSizingFeature: import("@tanstack/svelte-table").TableFeature;
|
|
40
|
+
columnResizingFeature: import("@tanstack/svelte-table").TableFeature;
|
|
41
|
+
}, T, import("@tanstack/svelte-table").TableState_ColumnFiltering & import("@tanstack/svelte-table").TableState_ColumnPinning & import("@tanstack/svelte-table").TableState_ColumnResizing & import("@tanstack/svelte-table").TableState_ColumnSizing & import("@tanstack/svelte-table").TableState_ColumnVisibility & import("@tanstack/svelte-table").TableState_GlobalFiltering & import("@tanstack/svelte-table").TableState_RowSelection & import("@tanstack/svelte-table").TableState_RowSorting>;
|
|
42
|
+
export declare function getColumnId<T extends RowData>(column: DataTableLeafColumn<T>): string;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { createTable as createSvelteTable, createSortedRowModel, createFilteredRowModel, createFacetedRowModel, createFacetedUniqueValues, createFacetedMinMaxValues, sortFns, filterFns } from '@tanstack/svelte-table';
|
|
2
|
+
import { useLocaleContext } from '@ark-ui/svelte/locale';
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
|
+
import { renderComponent, renderSnippet } from '@tanstack/svelte-table';
|
|
5
|
+
import { dataTableFeatures } from './features';
|
|
6
|
+
import { TYPE_NUMBER_FORMAT_DEFAULTS } from './data-table-utils';
|
|
7
|
+
const oneOfFilterFn = (row, columnId, filterValue) => {
|
|
8
|
+
return filterValue.includes(String(row.getValue(columnId)));
|
|
9
|
+
};
|
|
10
|
+
oneOfFilterFn.autoRemove = (val) => !Array.isArray(val) || val.length === 0;
|
|
11
|
+
export function createTable(options) {
|
|
12
|
+
const localeCtx = useLocaleContext();
|
|
13
|
+
const initialColumnVisibility = {
|
|
14
|
+
...createColumnVisibility(options.columns),
|
|
15
|
+
...options.initialState?.columnVisibility
|
|
16
|
+
};
|
|
17
|
+
// Recompute the resolved column defs only when the source columns change.
|
|
18
|
+
// $derived keeps the reference stable between changes so TanStack's column
|
|
19
|
+
// memoization isn't invalidated on every access. Pass `columns` through a
|
|
20
|
+
// getter (like `data`) to make adding/removing/reordering columns reactive.
|
|
21
|
+
const columnDefs = $derived(createColumns(options.columns, localeCtx));
|
|
22
|
+
const table = createSvelteTable({
|
|
23
|
+
features: dataTableFeatures,
|
|
24
|
+
rowModels: {
|
|
25
|
+
sortedRowModel: createSortedRowModel(sortFns),
|
|
26
|
+
filteredRowModel: createFilteredRowModel(filterFns),
|
|
27
|
+
facetedRowModel: createFacetedRowModel(),
|
|
28
|
+
facetedUniqueValues: createFacetedUniqueValues(),
|
|
29
|
+
facetedMinMaxValues: createFacetedMinMaxValues()
|
|
30
|
+
},
|
|
31
|
+
get data() {
|
|
32
|
+
return options.data;
|
|
33
|
+
},
|
|
34
|
+
get columns() {
|
|
35
|
+
return columnDefs;
|
|
36
|
+
},
|
|
37
|
+
columnResizeMode: options.columnResizeMode,
|
|
38
|
+
getRowId: options.getRowId,
|
|
39
|
+
enableRowSelection: options.enableRowSelection ?? false,
|
|
40
|
+
enableMultiRowSelection: options.enableMultiRowSelection,
|
|
41
|
+
enableSorting: options.enableSorting,
|
|
42
|
+
debugTable: options.debugTable,
|
|
43
|
+
initialState: {
|
|
44
|
+
columnVisibility: initialColumnVisibility,
|
|
45
|
+
columnSizing: {
|
|
46
|
+
...createColumnSizing(options.columns),
|
|
47
|
+
...options.initialState?.columnSizing
|
|
48
|
+
},
|
|
49
|
+
columnPinning: options.initialState?.columnPinning ?? createColumnPinning(options.columns),
|
|
50
|
+
rowSelection: options.initialState?.rowSelection ?? {},
|
|
51
|
+
sorting: options.initialState?.sorting ?? [],
|
|
52
|
+
columnFilters: options.initialState?.columnFilters ?? []
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
// The svelte adapter's internal $effect.pre only tracks `data` and `state` — not
|
|
56
|
+
// `columns` — so reactive add/remove/reorder of columns never reaches the table.
|
|
57
|
+
// Track the derived column defs here and push them through setOptions ourselves.
|
|
58
|
+
// Re-supply the `data` getter so spreading `prev` doesn't freeze data reactivity.
|
|
59
|
+
// CAUTION: upstream guidance says a second setOptions sync can race the adapter's
|
|
60
|
+
// own $effect.pre (which getter-merges the original options on data/state change).
|
|
61
|
+
// Both syncs write consistent values here, but revisit if the beta adapter ever
|
|
62
|
+
// starts tracking `columns` itself.
|
|
63
|
+
$effect.pre(() => {
|
|
64
|
+
const columns = columnDefs;
|
|
65
|
+
untrack(() => {
|
|
66
|
+
table.setOptions((prev) => ({
|
|
67
|
+
...prev,
|
|
68
|
+
get data() {
|
|
69
|
+
return options.data;
|
|
70
|
+
},
|
|
71
|
+
columns
|
|
72
|
+
}));
|
|
73
|
+
});
|
|
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
|
+
if (options.onColumnVisibilityChange) {
|
|
79
|
+
let first = true;
|
|
80
|
+
$effect(() => {
|
|
81
|
+
const visibility = table.atoms.columnVisibility.get();
|
|
82
|
+
if (first) {
|
|
83
|
+
first = false;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
options.onColumnVisibilityChange?.(visibility);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return table;
|
|
90
|
+
}
|
|
91
|
+
function createColumnVisibility(columns) {
|
|
92
|
+
return getLeafColumns(columns).reduce((visibility, column) => {
|
|
93
|
+
visibility[getColumnId(column)] = true;
|
|
94
|
+
return visibility;
|
|
95
|
+
}, {});
|
|
96
|
+
}
|
|
97
|
+
function createColumnSizing(columns) {
|
|
98
|
+
return getLeafColumns(columns).reduce((sizes, column) => {
|
|
99
|
+
if (typeof column.size === 'number') {
|
|
100
|
+
sizes[getColumnId(column)] = column.size;
|
|
101
|
+
}
|
|
102
|
+
return sizes;
|
|
103
|
+
}, {});
|
|
104
|
+
}
|
|
105
|
+
function createColumnPinning(columns) {
|
|
106
|
+
const leafCols = getLeafColumns(columns);
|
|
107
|
+
return {
|
|
108
|
+
left: leafCols.filter((c) => c.pinned === 'left').map(getColumnId),
|
|
109
|
+
right: leafCols.filter((c) => c.pinned === 'right').map(getColumnId)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function createColumns(columns, localeCtx) {
|
|
113
|
+
return columns.map((column) => {
|
|
114
|
+
if (isGroupColumn(column)) {
|
|
115
|
+
return {
|
|
116
|
+
id: getGroupColumnId(column),
|
|
117
|
+
header: column.header,
|
|
118
|
+
columns: createColumns(column.columns, localeCtx),
|
|
119
|
+
meta: {
|
|
120
|
+
align: column.align
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const columnId = getColumnId(column);
|
|
125
|
+
const derivedFilterFn = column.filterFn ?? getFilterFnForType(column.type);
|
|
126
|
+
const columnDef = {
|
|
127
|
+
id: columnId,
|
|
128
|
+
header: column.header,
|
|
129
|
+
size: column.size,
|
|
130
|
+
minSize: column.minSize,
|
|
131
|
+
maxSize: column.maxSize,
|
|
132
|
+
enableResizing: column.enableResizing,
|
|
133
|
+
enableHiding: column.enableHiding,
|
|
134
|
+
enableSorting: column.enableSorting,
|
|
135
|
+
sortDescFirst: column.sortDescFirst,
|
|
136
|
+
enableColumnFilter: column.enableColumnFilter,
|
|
137
|
+
...(derivedFilterFn !== undefined ? { filterFn: derivedFilterFn } : {}),
|
|
138
|
+
meta: {
|
|
139
|
+
align: column.align,
|
|
140
|
+
type: column.type,
|
|
141
|
+
formatOptions: column.formatOptions,
|
|
142
|
+
formatLocale: column.formatLocale,
|
|
143
|
+
grow: column.grow,
|
|
144
|
+
sum: column.sum,
|
|
145
|
+
footer: column.footer
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
if (typeof column.accessorFn === 'function') {
|
|
149
|
+
return {
|
|
150
|
+
...columnDef,
|
|
151
|
+
accessorFn: column.accessorFn,
|
|
152
|
+
cell: (context) => formatCellValue(column, context.getValue(), context.row.original, localeCtx)
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
...columnDef,
|
|
157
|
+
accessorKey: column.accessorKey,
|
|
158
|
+
cell: (context) => formatCellValue(column, context.getValue(), context.row.original, localeCtx)
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function isGroupColumn(column) {
|
|
163
|
+
return Array.isArray(column.columns);
|
|
164
|
+
}
|
|
165
|
+
function getLeafColumns(columns) {
|
|
166
|
+
return columns.flatMap((column) => isGroupColumn(column) ? getLeafColumns(column.columns) : column);
|
|
167
|
+
}
|
|
168
|
+
function getGroupColumnId(column) {
|
|
169
|
+
return column.id ?? column.header;
|
|
170
|
+
}
|
|
171
|
+
export function getColumnId(column) {
|
|
172
|
+
if (column.id !== undefined)
|
|
173
|
+
return column.id;
|
|
174
|
+
if ('accessorKey' in column && column.accessorKey !== undefined)
|
|
175
|
+
return column.accessorKey;
|
|
176
|
+
throw new Error('DataTableColumn with accessorFn requires an id.');
|
|
177
|
+
}
|
|
178
|
+
const TYPE_DATE_FORMAT_DEFAULTS = {
|
|
179
|
+
date: { day: '2-digit', month: '2-digit', year: 'numeric' },
|
|
180
|
+
time: { hour: '2-digit', minute: '2-digit' },
|
|
181
|
+
'date-time': {
|
|
182
|
+
day: '2-digit',
|
|
183
|
+
month: '2-digit',
|
|
184
|
+
year: 'numeric',
|
|
185
|
+
hour: '2-digit',
|
|
186
|
+
minute: '2-digit'
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
function getFilterFnForType(type) {
|
|
190
|
+
switch (type) {
|
|
191
|
+
case 'number':
|
|
192
|
+
case 'currency':
|
|
193
|
+
case 'percent':
|
|
194
|
+
return 'inNumberRange';
|
|
195
|
+
case 'boolean':
|
|
196
|
+
return 'equals';
|
|
197
|
+
case 'select':
|
|
198
|
+
return oneOfFilterFn;
|
|
199
|
+
default:
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function applyTypeFormat(column, value, localeCtx) {
|
|
204
|
+
if (value === null || value === undefined || value === '')
|
|
205
|
+
return undefined;
|
|
206
|
+
const numDefaults = column.type ? TYPE_NUMBER_FORMAT_DEFAULTS[column.type] : undefined;
|
|
207
|
+
if (numDefaults !== undefined) {
|
|
208
|
+
const numericValue = Number(value);
|
|
209
|
+
if (isNaN(numericValue))
|
|
210
|
+
return undefined;
|
|
211
|
+
const locale = column.formatLocale ?? localeCtx().locale;
|
|
212
|
+
return new Intl.NumberFormat(locale, {
|
|
213
|
+
...numDefaults,
|
|
214
|
+
...column.formatOptions
|
|
215
|
+
}).format(numericValue);
|
|
216
|
+
}
|
|
217
|
+
if (column.type === 'date' || column.type === 'time' || column.type === 'date-time') {
|
|
218
|
+
const dateValue = value instanceof Date ? value : new Date(value);
|
|
219
|
+
if (isNaN(dateValue.getTime()))
|
|
220
|
+
return undefined;
|
|
221
|
+
const locale = column.formatLocale ?? localeCtx().locale;
|
|
222
|
+
return new Intl.DateTimeFormat(locale, {
|
|
223
|
+
...TYPE_DATE_FORMAT_DEFAULTS[column.type],
|
|
224
|
+
...column.formatOptions
|
|
225
|
+
}).format(dateValue);
|
|
226
|
+
}
|
|
227
|
+
if (column.type === 'boolean')
|
|
228
|
+
return value ? 'Yes' : 'No';
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
231
|
+
function formatCellValue(column, value, row, localeCtx) {
|
|
232
|
+
if (column.cellComponent) {
|
|
233
|
+
return renderComponent(column.cellComponent, getCellComponentProps(column, value, row));
|
|
234
|
+
}
|
|
235
|
+
if (column.cellSnippet) {
|
|
236
|
+
return renderSnippet(column.cellSnippet, { value, row });
|
|
237
|
+
}
|
|
238
|
+
const rendered = column.cell
|
|
239
|
+
? column.cell(value, row)
|
|
240
|
+
: applyTypeFormat(column, value, localeCtx);
|
|
241
|
+
if (rendered === null || rendered === undefined || rendered === '') {
|
|
242
|
+
return '-';
|
|
243
|
+
}
|
|
244
|
+
return String(rendered);
|
|
245
|
+
}
|
|
246
|
+
function getCellComponentProps(column, value, row) {
|
|
247
|
+
return column.cellProps ? column.cellProps(value, row) : { value, row };
|
|
248
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends RowData">
|
|
2
|
+
import type { Cell, RowData } from '@tanstack/svelte-table';
|
|
3
|
+
import { FlexRender } from '@tanstack/svelte-table';
|
|
4
|
+
import { cn } from 'tailwind-variants';
|
|
5
|
+
import { PhArrowSquareOut, PhCheck, PhX } from '../../icons';
|
|
6
|
+
import type { DataTableFeatures } from './features';
|
|
7
|
+
import {
|
|
8
|
+
getBooleanCellValue,
|
|
9
|
+
getColumnMeta,
|
|
10
|
+
getUrlCellValue,
|
|
11
|
+
justifyClass,
|
|
12
|
+
openUrlCell
|
|
13
|
+
} from './data-table-utils';
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
cell: Cell<DataTableFeatures, T, unknown>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let { cell }: Props = $props();
|
|
20
|
+
|
|
21
|
+
const meta = $derived(getColumnMeta(cell.column.columnDef));
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
{#if meta?.type === 'boolean'}
|
|
25
|
+
{@const value = getBooleanCellValue(cell.getValue())}
|
|
26
|
+
{#if value === true}
|
|
27
|
+
<span
|
|
28
|
+
class="inline-flex size-5 items-center justify-center text-success"
|
|
29
|
+
role="img"
|
|
30
|
+
aria-label="Yes"
|
|
31
|
+
>
|
|
32
|
+
<PhCheck class="size-4" />
|
|
33
|
+
</span>
|
|
34
|
+
{:else if value === false}
|
|
35
|
+
<span
|
|
36
|
+
class="inline-flex size-5 items-center justify-center text-danger"
|
|
37
|
+
role="img"
|
|
38
|
+
aria-label="No"
|
|
39
|
+
>
|
|
40
|
+
<PhX class="size-4" />
|
|
41
|
+
</span>
|
|
42
|
+
{:else}
|
|
43
|
+
-
|
|
44
|
+
{/if}
|
|
45
|
+
{:else if meta?.type === 'url'}
|
|
46
|
+
{@const value = getUrlCellValue(cell.getValue())}
|
|
47
|
+
{#if value}
|
|
48
|
+
<button
|
|
49
|
+
type="button"
|
|
50
|
+
class={cn(
|
|
51
|
+
'inline-flex max-w-full appearance-none items-center gap-1.5 rounded-sm border-0 bg-transparent p-0 align-middle leading-5 font-medium text-ink underline decoration-border decoration-dotted underline-offset-4 outline-none hover:text-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring',
|
|
52
|
+
justifyClass(meta.align)
|
|
53
|
+
)}
|
|
54
|
+
onclick={(event) => {
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
openUrlCell(value);
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
<PhArrowSquareOut class="size-3.5 shrink-0" />
|
|
60
|
+
</button>
|
|
61
|
+
{:else}
|
|
62
|
+
-
|
|
63
|
+
{/if}
|
|
64
|
+
{:else}
|
|
65
|
+
<FlexRender {cell} />
|
|
66
|
+
{/if}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Cell, RowData } from '@tanstack/svelte-table';
|
|
2
|
+
import type { DataTableFeatures } from './features';
|
|
3
|
+
declare function $$render<T extends RowData>(): {
|
|
4
|
+
props: {
|
|
5
|
+
cell: Cell<DataTableFeatures, T, unknown>;
|
|
6
|
+
};
|
|
7
|
+
exports: {};
|
|
8
|
+
bindings: "";
|
|
9
|
+
slots: {};
|
|
10
|
+
events: {};
|
|
11
|
+
};
|
|
12
|
+
declare class __sveltets_Render<T extends RowData> {
|
|
13
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
14
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
15
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
16
|
+
bindings(): "";
|
|
17
|
+
exports(): {};
|
|
18
|
+
}
|
|
19
|
+
interface $$IsomorphicComponent {
|
|
20
|
+
new <T extends RowData>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
21
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
22
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
23
|
+
<T extends RowData>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
24
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
25
|
+
}
|
|
26
|
+
declare const DataTableCellContent: $$IsomorphicComponent;
|
|
27
|
+
type DataTableCellContent<T extends RowData> = InstanceType<typeof DataTableCellContent<T>>;
|
|
28
|
+
export default DataTableCellContent;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends RowData">
|
|
2
|
+
import type { Column, RowData } from '@tanstack/svelte-table';
|
|
3
|
+
import { useLocaleContext } from '@ark-ui/svelte/locale';
|
|
4
|
+
import { cn } from 'tailwind-variants';
|
|
5
|
+
import type { DataTableInstance } from './data-table-utils';
|
|
6
|
+
import type { DataTableViewState } from './table-view-state.svelte';
|
|
7
|
+
import type { DataTableFeatures } from './features';
|
|
8
|
+
import {
|
|
9
|
+
alignClass,
|
|
10
|
+
formatColumnFooter,
|
|
11
|
+
getColumnMeta,
|
|
12
|
+
getPinningStyle,
|
|
13
|
+
justifyClass,
|
|
14
|
+
joinStyles,
|
|
15
|
+
virtualColumnSizeStyle,
|
|
16
|
+
virtualGrowColumnSizeStyle,
|
|
17
|
+
virtualSelectionColumnSizeStyle
|
|
18
|
+
} from './data-table-utils';
|
|
19
|
+
|
|
20
|
+
type Props = {
|
|
21
|
+
table: DataTableInstance<T>;
|
|
22
|
+
view: DataTableViewState<T>;
|
|
23
|
+
hasGrowColumn: boolean;
|
|
24
|
+
isVirtual?: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
let { table, view, hasGrowColumn, isVirtual = false }: Props = $props();
|
|
28
|
+
|
|
29
|
+
const localeCtx = useLocaleContext();
|
|
30
|
+
const locale = $derived(localeCtx().locale);
|
|
31
|
+
|
|
32
|
+
// One pass over the rows collects values for every footer column, instead of
|
|
33
|
+
// re-reading all rows per column on each render.
|
|
34
|
+
const footerTexts = $derived.by(() => {
|
|
35
|
+
const footerColumns = view.visibleLeafColumns.filter((column) => {
|
|
36
|
+
const meta = getColumnMeta(column.columnDef);
|
|
37
|
+
return !!(meta?.sum || meta?.footer);
|
|
38
|
+
});
|
|
39
|
+
const valuesByColumn: Record<string, unknown[]> = {};
|
|
40
|
+
for (const column of footerColumns) {
|
|
41
|
+
valuesByColumn[column.id] = [];
|
|
42
|
+
}
|
|
43
|
+
for (const row of view.rowModel.rows) {
|
|
44
|
+
for (const columnId in valuesByColumn) {
|
|
45
|
+
valuesByColumn[columnId].push(row.getValue(columnId));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const texts: Record<string, string | undefined> = {};
|
|
49
|
+
for (const column of footerColumns) {
|
|
50
|
+
const meta = getColumnMeta(column.columnDef);
|
|
51
|
+
texts[column.id] = formatColumnFooter(meta ?? {}, valuesByColumn[column.id], locale);
|
|
52
|
+
}
|
|
53
|
+
return texts;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
function footCellStyle(column: Column<DataTableFeatures, T, unknown>) {
|
|
57
|
+
const meta = getColumnMeta(column.columnDef);
|
|
58
|
+
if (!isVirtual) return getPinningStyle(column, table, view, true, view.isRowSelectionEnabled);
|
|
59
|
+
return joinStyles(
|
|
60
|
+
meta?.grow ? virtualGrowColumnSizeStyle() : virtualColumnSizeStyle(column.getSize()),
|
|
61
|
+
getPinningStyle(column, table, view, true, view.isRowSelectionEnabled)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function selectionCellStyle() {
|
|
66
|
+
return isVirtual
|
|
67
|
+
? joinStyles(
|
|
68
|
+
virtualSelectionColumnSizeStyle(),
|
|
69
|
+
'min-width: 40px',
|
|
70
|
+
'max-width: 40px',
|
|
71
|
+
'position: sticky',
|
|
72
|
+
'left: 0',
|
|
73
|
+
'z-index: 15'
|
|
74
|
+
)
|
|
75
|
+
: 'width: 40px; min-width: 40px; max-width: 40px; position: sticky; left: 0; z-index: 15';
|
|
76
|
+
}
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<tfoot
|
|
80
|
+
class="sticky bottom-0 z-20 bg-surface-2 text-ink-dim"
|
|
81
|
+
style={isVirtual ? 'display: grid; position: sticky; bottom: 0; z-index: 20' : undefined}
|
|
82
|
+
>
|
|
83
|
+
<tr class="h-9" style={isVirtual ? 'display: flex; width: 100%' : undefined}>
|
|
84
|
+
{#if view.isRowSelectionEnabled}
|
|
85
|
+
<td
|
|
86
|
+
class={cn(
|
|
87
|
+
'h-9 border-t border-surface-3 bg-surface-2 px-3 py-0',
|
|
88
|
+
isVirtual && 'flex items-center'
|
|
89
|
+
)}
|
|
90
|
+
style={selectionCellStyle()}
|
|
91
|
+
></td>
|
|
92
|
+
{/if}
|
|
93
|
+
{#each view.visibleLeafColumns as column (column.id)}
|
|
94
|
+
{@const meta = getColumnMeta(column.columnDef)}
|
|
95
|
+
<td
|
|
96
|
+
class={cn(
|
|
97
|
+
'h-9 truncate border-t border-surface-3 bg-surface-2 px-3 py-0 align-middle text-sm font-medium',
|
|
98
|
+
alignClass(meta?.align),
|
|
99
|
+
isVirtual && 'flex items-center',
|
|
100
|
+
isVirtual && justifyClass(meta?.align)
|
|
101
|
+
)}
|
|
102
|
+
style={footCellStyle(column)}
|
|
103
|
+
>
|
|
104
|
+
{footerTexts[column.id] ?? ''}
|
|
105
|
+
</td>
|
|
106
|
+
{/each}
|
|
107
|
+
{#if !isVirtual && !hasGrowColumn}
|
|
108
|
+
<td aria-hidden="true" class="h-9 border-t border-surface-3 bg-surface-2 p-0"></td>
|
|
109
|
+
{/if}
|
|
110
|
+
</tr>
|
|
111
|
+
</tfoot>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RowData } from '@tanstack/svelte-table';
|
|
2
|
+
import type { DataTableInstance } from './data-table-utils';
|
|
3
|
+
import type { DataTableViewState } from './table-view-state.svelte';
|
|
4
|
+
declare function $$render<T extends RowData>(): {
|
|
5
|
+
props: {
|
|
6
|
+
table: DataTableInstance<T>;
|
|
7
|
+
view: DataTableViewState<T>;
|
|
8
|
+
hasGrowColumn: boolean;
|
|
9
|
+
isVirtual?: boolean;
|
|
10
|
+
};
|
|
11
|
+
exports: {};
|
|
12
|
+
bindings: "";
|
|
13
|
+
slots: {};
|
|
14
|
+
events: {};
|
|
15
|
+
};
|
|
16
|
+
declare class __sveltets_Render<T extends RowData> {
|
|
17
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
18
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
19
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
20
|
+
bindings(): "";
|
|
21
|
+
exports(): {};
|
|
22
|
+
}
|
|
23
|
+
interface $$IsomorphicComponent {
|
|
24
|
+
new <T extends RowData>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
25
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
26
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
27
|
+
<T extends RowData>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
28
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
29
|
+
}
|
|
30
|
+
declare const DataTableFoot: $$IsomorphicComponent;
|
|
31
|
+
type DataTableFoot<T extends RowData> = InstanceType<typeof DataTableFoot<T>>;
|
|
32
|
+
export default DataTableFoot;
|