@happyvertical/smrt-ui 0.42.4 → 0.42.6
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/README.md +157 -3
- package/dist/components/data/DataTable.svelte +1097 -111
- package/dist/components/data/DataTable.svelte.d.ts +1 -1
- package/dist/components/data/DataTable.svelte.d.ts.map +1 -1
- package/dist/components/data/DataTableController.d.ts +45 -5
- package/dist/components/data/DataTableController.d.ts.map +1 -1
- package/dist/components/data/DataTableController.js +153 -11
- package/dist/components/data/DataTableLayout.d.ts +37 -0
- package/dist/components/data/DataTableLayout.d.ts.map +1 -0
- package/dist/components/data/DataTableLayout.js +135 -0
- package/dist/components/data/DataTablePerformance.d.ts +31 -0
- package/dist/components/data/DataTablePerformance.d.ts.map +1 -0
- package/dist/components/data/DataTablePerformance.js +46 -0
- package/dist/components/data/DataTableVirtualization.d.ts +71 -0
- package/dist/components/data/DataTableVirtualization.d.ts.map +1 -0
- package/dist/components/data/DataTableVirtualization.js +100 -0
- package/dist/components/data/__benchmarks__/DataTable.bench.d.ts +2 -0
- package/dist/components/data/__benchmarks__/DataTable.bench.d.ts.map +1 -0
- package/dist/components/data/__benchmarks__/DataTable.bench.js +53 -0
- package/dist/components/data/__fixtures__/DataTableConformanceFixture.d.ts +27 -0
- package/dist/components/data/__fixtures__/DataTableConformanceFixture.d.ts.map +1 -0
- package/dist/components/data/__fixtures__/DataTableConformanceFixture.js +141 -0
- package/dist/components/data/__fixtures__/DataTablePerformanceFixture.d.ts +10 -0
- package/dist/components/data/__fixtures__/DataTablePerformanceFixture.d.ts.map +1 -0
- package/dist/components/data/__fixtures__/DataTablePerformanceFixture.js +23 -0
- package/dist/components/data/__tests__/DataTable.test.js +393 -8
- package/dist/components/data/__tests__/DataTableConformance.test.js +212 -0
- package/dist/components/data/__tests__/DataTableController.test.js +124 -2
- package/dist/components/data/__tests__/DataTableLayout.test.js +195 -0
- package/dist/components/data/__tests__/DataTablePerformance.test.js +21 -0
- package/dist/components/data/__tests__/DataTableVirtualization.test.js +80 -0
- package/dist/components/data/__tests__/DataTableVirtualizationComponent.test.js +255 -0
- package/dist/components/data/__tests__/data-surface.test.js +675 -0
- package/dist/components/data/data-surface.d.ts +246 -0
- package/dist/components/data/data-surface.d.ts.map +1 -0
- package/dist/components/data/data-surface.js +1102 -0
- package/dist/components/data/index.d.ts +3 -0
- package/dist/components/data/index.d.ts.map +1 -1
- package/dist/components/data/index.js +3 -0
- package/dist/components/data/types.d.ts +83 -1
- package/dist/components/data/types.d.ts.map +1 -1
- package/dist/i18n/strings.d.ts +25 -0
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +27 -2
- package/dist/svelte/playground/DataTablePreview.svelte +374 -5
- package/dist/svelte/playground/DataTablePreview.svelte.d.ts.map +1 -1
- package/dist/svelte/playground.js +2 -2
- package/package.json +3 -2
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - Responsive with sticky header option
|
|
10
10
|
* - Material 3 styling with theme token support
|
|
11
11
|
*/
|
|
12
|
-
import type
|
|
12
|
+
import { type Snippet } from 'svelte';
|
|
13
13
|
import type { DataTableColumn, DataTableProps } from './types.js';
|
|
14
14
|
interface ExtendedProps<T> extends DataTableProps<T> {
|
|
15
15
|
/** Global cell renderer - takes precedence over column.cell */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTable.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"DataTable.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTable.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,KAAK,OAAO,EAAQ,MAAM,QAAQ,CAAC;AA4B5C,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAGf,MAAM,YAAY,CAAC;AAIpB,UAAU,aAAa,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IAClD,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,CACZ;QAAC;YAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;YAAC,GAAG,EAAE,CAAC,CAAC;YAAC,KAAK,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE;KAAC,CACxE,CAAC;CACH;AAAC,iBAAS,QAAQ,CAAC,CAAC;WAsxCQ,aAAa,CAAC,CAAC,CAAC;;;;;EAAgH;AAC7J,cAAM,iBAAiB,CAAC,CAAC;IACrB,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,QAAQ;IACR,OAAO;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5X,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3H,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AACD,QAAA,MAAM,SAAS,EAAE,qBAAmC,CAAC;AACnC,KAAK,SAAS,CAAC,CAAC,IAAI,YAAY,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,eAAe,SAAS,CAAC"}
|
|
@@ -51,6 +51,16 @@ export interface DataTableColumnVisibility {
|
|
|
51
51
|
columnId: string;
|
|
52
52
|
visible: boolean;
|
|
53
53
|
}
|
|
54
|
+
/** A persisted width in CSS pixels. Static column widths remain presentation defaults. */
|
|
55
|
+
export interface DataTableColumnWidth {
|
|
56
|
+
columnId: string;
|
|
57
|
+
width: number;
|
|
58
|
+
}
|
|
59
|
+
/** A persisted edge pin. Column order is retained within each pin partition. */
|
|
60
|
+
export interface DataTableColumnPinning {
|
|
61
|
+
columnId: string;
|
|
62
|
+
position: 'start' | 'end';
|
|
63
|
+
}
|
|
54
64
|
/**
|
|
55
65
|
* The JSON-safe, persistable portion of a table view. Selection and expansion
|
|
56
66
|
* are serialized as canonical arrays rather than Sets.
|
|
@@ -63,6 +73,8 @@ export interface DataTableViewState {
|
|
|
63
73
|
pageSize: number | null;
|
|
64
74
|
columnOrder: string[];
|
|
65
75
|
columnVisibility: DataTableColumnVisibility[];
|
|
76
|
+
columnWidths: DataTableColumnWidth[];
|
|
77
|
+
columnPinning: DataTableColumnPinning[];
|
|
66
78
|
selection: DataTableSelection;
|
|
67
79
|
/**
|
|
68
80
|
* Legacy shorthand for row-ID selections. It is always derived from
|
|
@@ -72,15 +84,19 @@ export interface DataTableViewState {
|
|
|
72
84
|
expandedRowIds: DataTableRowId[];
|
|
73
85
|
}
|
|
74
86
|
/**
|
|
75
|
-
* Accepts
|
|
76
|
-
* normalized version-
|
|
87
|
+
* Accepts version-1 and version-2 controlled state while the controller emits
|
|
88
|
+
* normalized version-3 state with explicit selection and column layout.
|
|
77
89
|
*/
|
|
78
|
-
export type DataTableViewStateInput = Omit<DataTableViewState, 'selection'> & {
|
|
90
|
+
export type DataTableViewStateInput = Omit<DataTableViewState, 'selection' | 'columnWidths' | 'columnPinning'> & {
|
|
79
91
|
selection?: DataTableSelection;
|
|
92
|
+
/** Optional while restoring version-1 or version-2 state. */
|
|
93
|
+
columnWidths?: DataTableColumnWidth[];
|
|
94
|
+
/** Optional while restoring version-1 or version-2 state. */
|
|
95
|
+
columnPinning?: DataTableColumnPinning[];
|
|
80
96
|
};
|
|
81
97
|
/** The stable envelope intended for URL and saved-view adapters. */
|
|
82
98
|
export interface DataTableSnapshot {
|
|
83
|
-
version:
|
|
99
|
+
version: 3;
|
|
84
100
|
modes: DataTableModes;
|
|
85
101
|
state: DataTableViewState;
|
|
86
102
|
}
|
|
@@ -110,6 +126,20 @@ export type DataTableCommand = {
|
|
|
110
126
|
} | {
|
|
111
127
|
type: 'setColumnVisibility';
|
|
112
128
|
columns: DataTableColumnVisibility[];
|
|
129
|
+
} | {
|
|
130
|
+
type: 'setColumnWidths';
|
|
131
|
+
columns: DataTableColumnWidth[];
|
|
132
|
+
} | {
|
|
133
|
+
type: 'setColumnWidth';
|
|
134
|
+
columnId: string;
|
|
135
|
+
width: number | null;
|
|
136
|
+
} | {
|
|
137
|
+
type: 'setColumnPinning';
|
|
138
|
+
columns: DataTableColumnPinning[];
|
|
139
|
+
} | {
|
|
140
|
+
type: 'setColumnPin';
|
|
141
|
+
columnId: string;
|
|
142
|
+
position: DataTableColumnPinning['position'] | null;
|
|
113
143
|
} | {
|
|
114
144
|
type: 'setSelection';
|
|
115
145
|
selection: DataTableSelection;
|
|
@@ -148,6 +178,8 @@ export interface DataTableControllerOptions {
|
|
|
148
178
|
modes?: Partial<DataTableModes>;
|
|
149
179
|
/** Optional known columns let the controller ignore stale saved-view fields. */
|
|
150
180
|
columnIds?: readonly string[];
|
|
181
|
+
/** Static schema constraints that saved or controlled state may not override. */
|
|
182
|
+
hiddenColumnIds?: readonly string[];
|
|
151
183
|
onStateChange?: (state: DataTableViewState, command: DataTableCommand) => void;
|
|
152
184
|
}
|
|
153
185
|
export type DataTableStateListener = (transition: DataTableTransition) => void;
|
|
@@ -168,6 +200,13 @@ export declare class DataTableController {
|
|
|
168
200
|
private state;
|
|
169
201
|
private modes;
|
|
170
202
|
private columnIds?;
|
|
203
|
+
private hiddenColumnIds?;
|
|
204
|
+
/**
|
|
205
|
+
* Static schema visibility is a rendering constraint, not a saved-view
|
|
206
|
+
* preference. Keep the latter while a column is constrained so removing the
|
|
207
|
+
* constraint restores the caller's prior intent.
|
|
208
|
+
*/
|
|
209
|
+
private readonly visibilityBeforeStaticHide;
|
|
171
210
|
private controlled;
|
|
172
211
|
private readonly listeners;
|
|
173
212
|
private readonly onStateChange?;
|
|
@@ -186,7 +225,8 @@ export declare class DataTableController {
|
|
|
186
225
|
/** Configures transformation ownership; this remains outside persisted state. */
|
|
187
226
|
setModes(modes: Partial<DataTableModes>): DataTableTransition;
|
|
188
227
|
/** Reconciles stale saved-view column IDs with the renderer's current columns. */
|
|
189
|
-
setColumnIds(columnIds: readonly string[]): DataTableTransition;
|
|
228
|
+
setColumnIds(columnIds: readonly string[], hiddenColumnIds?: readonly string[]): DataTableTransition;
|
|
229
|
+
private rememberStaticVisibility;
|
|
190
230
|
/** Clamp against a reliable total. A missing total intentionally does not guess. */
|
|
191
231
|
clampPage(totalRows: number | null | undefined): DataTableTransition;
|
|
192
232
|
private emit;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTableController.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTableController.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7C,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,EAAE,CAAA;CAAE,GAC3C;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,cAAc,EAAE,CAAA;CAAE,GAC/C,CAAC;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC;AAE/E,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AACtE,MAAM,MAAM,kBAAkB,GAC1B,sBAAsB,GACtB,kBAAkB,EAAE,GACpB;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;CAAE,CAAC;AAE1C,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExD,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,sBAAsB,CAAC;IAClC,OAAO,EAAE,sBAAsB,CAAC;IAChC,UAAU,EAAE,sBAAsB,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,uBAAuB,GAC/B,QAAQ,GACR,WAAW,GACX,UAAU,GACV,aAAa,GACb,YAAY,GACZ,UAAU,GACV,IAAI,GACJ,OAAO,GACP,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,KAAK,GACL,QAAQ,GACR,WAAW,CAAC;AAEhB,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED,2EAA2E;AAC3E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,yBAAyB,EAAE,CAAC;IAC9C,SAAS,EAAE,kBAAkB,CAAC;IAC9B;;;OAGG;IACH,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC,cAAc,EAAE,cAAc,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"DataTableController.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTableController.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,8 @@ const DEFAULT_STATE = {
|
|
|
17
17
|
pageSize: null,
|
|
18
18
|
columnOrder: [],
|
|
19
19
|
columnVisibility: [],
|
|
20
|
+
columnWidths: [],
|
|
21
|
+
columnPinning: [],
|
|
20
22
|
selection: { scope: 'explicit', rowIds: [] },
|
|
21
23
|
selectedRowIds: [],
|
|
22
24
|
expandedRowIds: [],
|
|
@@ -271,6 +273,34 @@ function normalizeVisibility(values) {
|
|
|
271
273
|
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
272
274
|
.map(([columnId, visible]) => ({ columnId, visible }));
|
|
273
275
|
}
|
|
276
|
+
function normalizeWidths(values) {
|
|
277
|
+
const entries = new Map();
|
|
278
|
+
for (const entry of values) {
|
|
279
|
+
const columnId = assertColumnId(entry?.columnId, 'width column id');
|
|
280
|
+
if (typeof entry?.width !== 'number' ||
|
|
281
|
+
!Number.isFinite(entry.width) ||
|
|
282
|
+
entry.width <= 0) {
|
|
283
|
+
throw new TypeError('DataTable column widths must be positive finite numbers');
|
|
284
|
+
}
|
|
285
|
+
entries.set(columnId, entry.width);
|
|
286
|
+
}
|
|
287
|
+
return [...entries.entries()]
|
|
288
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
289
|
+
.map(([columnId, width]) => ({ columnId, width }));
|
|
290
|
+
}
|
|
291
|
+
function normalizePinning(values) {
|
|
292
|
+
const entries = new Map();
|
|
293
|
+
for (const entry of values) {
|
|
294
|
+
const columnId = assertColumnId(entry?.columnId, 'pin column id');
|
|
295
|
+
if (entry?.position !== 'start' && entry?.position !== 'end') {
|
|
296
|
+
throw new TypeError('DataTable column pins must be start or end');
|
|
297
|
+
}
|
|
298
|
+
entries.set(columnId, entry.position);
|
|
299
|
+
}
|
|
300
|
+
return [...entries.entries()]
|
|
301
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
302
|
+
.map(([columnId, position]) => ({ columnId, position }));
|
|
303
|
+
}
|
|
274
304
|
function normalizeModes(modes) {
|
|
275
305
|
const result = { ...DEFAULT_MODES, ...modes };
|
|
276
306
|
for (const mode of Object.values(result)) {
|
|
@@ -280,12 +310,13 @@ function normalizeModes(modes) {
|
|
|
280
310
|
}
|
|
281
311
|
return result;
|
|
282
312
|
}
|
|
283
|
-
function normalizeState(state, columnIds) {
|
|
313
|
+
function normalizeState(state, columnIds, hiddenColumnIds) {
|
|
284
314
|
const input = state ?? {};
|
|
285
315
|
const selection = normalizeSelection(input.selection, input.selectedRowIds ?? DEFAULT_STATE.selectedRowIds);
|
|
286
316
|
const knownColumns = columnIds ? normalizeUniqueColumnIds(columnIds) : null;
|
|
287
317
|
const allowed = knownColumns ? new Set(knownColumns) : null;
|
|
288
318
|
const keepKnown = (columnId) => !allowed || allowed.has(columnId);
|
|
319
|
+
const hidden = new Set((hiddenColumnIds ? normalizeUniqueColumnIds(hiddenColumnIds) : []).filter(keepKnown));
|
|
289
320
|
const visibility = normalizeVisibility(input.columnVisibility ?? DEFAULT_STATE.columnVisibility).filter((entry) => keepKnown(entry.columnId));
|
|
290
321
|
const knownVisibility = new Map(visibility.map((entry) => [entry.columnId, entry.visible]));
|
|
291
322
|
if (knownColumns) {
|
|
@@ -294,6 +325,8 @@ function normalizeState(state, columnIds) {
|
|
|
294
325
|
knownVisibility.set(columnId, true);
|
|
295
326
|
}
|
|
296
327
|
}
|
|
328
|
+
for (const columnId of hidden)
|
|
329
|
+
knownVisibility.set(columnId, false);
|
|
297
330
|
const columnOrder = normalizeUniqueColumnIds(input.columnOrder ?? DEFAULT_STATE.columnOrder).filter(keepKnown);
|
|
298
331
|
if (knownColumns) {
|
|
299
332
|
for (const columnId of knownColumns) {
|
|
@@ -301,6 +334,8 @@ function normalizeState(state, columnIds) {
|
|
|
301
334
|
columnOrder.push(columnId);
|
|
302
335
|
}
|
|
303
336
|
}
|
|
337
|
+
const columnWidths = normalizeWidths(input.columnWidths ?? DEFAULT_STATE.columnWidths).filter((entry) => keepKnown(entry.columnId));
|
|
338
|
+
const columnPinning = normalizePinning(input.columnPinning ?? DEFAULT_STATE.columnPinning).filter((entry) => keepKnown(entry.columnId));
|
|
304
339
|
return {
|
|
305
340
|
search: typeof input.search === 'string' ? input.search : DEFAULT_STATE.search,
|
|
306
341
|
filters: normalizeFilters(input.filters ?? DEFAULT_STATE.filters).filter((filter) => keepKnown(filter.columnId)),
|
|
@@ -312,6 +347,8 @@ function normalizeState(state, columnIds) {
|
|
|
312
347
|
columnId,
|
|
313
348
|
visible,
|
|
314
349
|
}))),
|
|
350
|
+
columnWidths,
|
|
351
|
+
columnPinning,
|
|
315
352
|
selection,
|
|
316
353
|
selectedRowIds: selectedRowIdsFor(selection),
|
|
317
354
|
expandedRowIds: normalizeRowIds(input.expandedRowIds ?? DEFAULT_STATE.expandedRowIds),
|
|
@@ -413,6 +450,57 @@ export function transitionDataTableState(state, command) {
|
|
|
413
450
|
columnVisibility: normalizeVisibility(command.columns),
|
|
414
451
|
};
|
|
415
452
|
break;
|
|
453
|
+
case 'setColumnWidths':
|
|
454
|
+
next = {
|
|
455
|
+
...current,
|
|
456
|
+
columnWidths: normalizeWidths(command.columns),
|
|
457
|
+
};
|
|
458
|
+
break;
|
|
459
|
+
case 'setColumnWidth': {
|
|
460
|
+
const columnId = assertColumnId(command.columnId, 'width column id');
|
|
461
|
+
const widths = new Map(current.columnWidths.map((entry) => [entry.columnId, entry.width]));
|
|
462
|
+
if (command.width === null) {
|
|
463
|
+
widths.delete(columnId);
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
const normalized = normalizeWidths([
|
|
467
|
+
{ columnId, width: command.width },
|
|
468
|
+
]);
|
|
469
|
+
widths.set(columnId, normalized[0].width);
|
|
470
|
+
}
|
|
471
|
+
next = {
|
|
472
|
+
...current,
|
|
473
|
+
columnWidths: normalizeWidths([...widths.entries()].map(([id, width]) => ({ columnId: id, width }))),
|
|
474
|
+
};
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
477
|
+
case 'setColumnPinning':
|
|
478
|
+
next = {
|
|
479
|
+
...current,
|
|
480
|
+
columnPinning: normalizePinning(command.columns),
|
|
481
|
+
};
|
|
482
|
+
break;
|
|
483
|
+
case 'setColumnPin': {
|
|
484
|
+
const columnId = assertColumnId(command.columnId, 'pin column id');
|
|
485
|
+
const pins = new Map(current.columnPinning.map((entry) => [entry.columnId, entry.position]));
|
|
486
|
+
if (command.position === null) {
|
|
487
|
+
pins.delete(columnId);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
const normalized = normalizePinning([
|
|
491
|
+
{ columnId, position: command.position },
|
|
492
|
+
]);
|
|
493
|
+
pins.set(columnId, normalized[0].position);
|
|
494
|
+
}
|
|
495
|
+
next = {
|
|
496
|
+
...current,
|
|
497
|
+
columnPinning: normalizePinning([...pins.entries()].map(([id, position]) => ({
|
|
498
|
+
columnId: id,
|
|
499
|
+
position,
|
|
500
|
+
}))),
|
|
501
|
+
};
|
|
502
|
+
break;
|
|
503
|
+
}
|
|
416
504
|
case 'setSelection':
|
|
417
505
|
next = withSelection(current, command.selection);
|
|
418
506
|
break;
|
|
@@ -478,10 +566,10 @@ export function hydrateDataTableSnapshot(value) {
|
|
|
478
566
|
throw new TypeError('DataTable snapshot must be a plain object');
|
|
479
567
|
}
|
|
480
568
|
const input = value;
|
|
481
|
-
if (input.version !== 1 && input.version !== 2)
|
|
569
|
+
if (input.version !== 1 && input.version !== 2 && input.version !== 3)
|
|
482
570
|
throw new TypeError('Unsupported DataTable snapshot version');
|
|
483
571
|
return {
|
|
484
|
-
version:
|
|
572
|
+
version: 3,
|
|
485
573
|
modes: normalizeModes(input.modes),
|
|
486
574
|
state: normalizeState(input.state),
|
|
487
575
|
};
|
|
@@ -491,6 +579,13 @@ export class DataTableController {
|
|
|
491
579
|
state;
|
|
492
580
|
modes;
|
|
493
581
|
columnIds;
|
|
582
|
+
hiddenColumnIds;
|
|
583
|
+
/**
|
|
584
|
+
* Static schema visibility is a rendering constraint, not a saved-view
|
|
585
|
+
* preference. Keep the latter while a column is constrained so removing the
|
|
586
|
+
* constraint restores the caller's prior intent.
|
|
587
|
+
*/
|
|
588
|
+
visibilityBeforeStaticHide = new Map();
|
|
494
589
|
controlled;
|
|
495
590
|
listeners = new Set();
|
|
496
591
|
onStateChange;
|
|
@@ -499,8 +594,12 @@ export class DataTableController {
|
|
|
499
594
|
this.columnIds = options.columnIds
|
|
500
595
|
? normalizeUniqueColumnIds(options.columnIds)
|
|
501
596
|
: undefined;
|
|
597
|
+
this.hiddenColumnIds = options.hiddenColumnIds
|
|
598
|
+
? normalizeUniqueColumnIds(options.hiddenColumnIds)
|
|
599
|
+
: undefined;
|
|
600
|
+
this.rememberStaticVisibility(options.state ?? options.initialState ?? {}, this.hiddenColumnIds ?? []);
|
|
502
601
|
this.controlled = options.state !== undefined;
|
|
503
|
-
this.state = normalizeState(options.state ?? options.initialState, this.columnIds);
|
|
602
|
+
this.state = normalizeState(options.state ?? options.initialState, this.columnIds, this.hiddenColumnIds);
|
|
504
603
|
this.modes = normalizeModes(options.modes);
|
|
505
604
|
this.onStateChange = options.onStateChange;
|
|
506
605
|
}
|
|
@@ -511,7 +610,7 @@ export class DataTableController {
|
|
|
511
610
|
return { ...this.modes };
|
|
512
611
|
}
|
|
513
612
|
snapshot() {
|
|
514
|
-
return { version:
|
|
613
|
+
return { version: 3, modes: this.getModes(), state: this.getState() };
|
|
515
614
|
}
|
|
516
615
|
subscribe(listener) {
|
|
517
616
|
this.listeners.add(listener);
|
|
@@ -520,9 +619,9 @@ export class DataTableController {
|
|
|
520
619
|
/** Dispatches a serializable command. Controlled controllers emit a proposal only. */
|
|
521
620
|
dispatch(command) {
|
|
522
621
|
const previous = this.snapshot();
|
|
523
|
-
const candidate = normalizeState(transitionDataTableState(this.state, command), this.columnIds);
|
|
622
|
+
const candidate = normalizeState(transitionDataTableState(this.state, command), this.columnIds, this.hiddenColumnIds);
|
|
524
623
|
const next = {
|
|
525
|
-
version:
|
|
624
|
+
version: 3,
|
|
526
625
|
modes: this.getModes(),
|
|
527
626
|
state: candidate,
|
|
528
627
|
};
|
|
@@ -552,9 +651,12 @@ export class DataTableController {
|
|
|
552
651
|
/** Supplies state from a controlled host or an external persistence adapter. */
|
|
553
652
|
replaceState(state) {
|
|
554
653
|
const previous = this.snapshot();
|
|
555
|
-
|
|
654
|
+
if (this.controlled) {
|
|
655
|
+
this.rememberStaticVisibility(state, this.hiddenColumnIds ?? [], true);
|
|
656
|
+
}
|
|
657
|
+
const nextState = normalizeState(state, this.columnIds, this.hiddenColumnIds);
|
|
556
658
|
const next = {
|
|
557
|
-
version:
|
|
659
|
+
version: 3,
|
|
558
660
|
modes: this.getModes(),
|
|
559
661
|
state: nextState,
|
|
560
662
|
};
|
|
@@ -589,10 +691,34 @@ export class DataTableController {
|
|
|
589
691
|
return transition;
|
|
590
692
|
}
|
|
591
693
|
/** Reconciles stale saved-view column IDs with the renderer's current columns. */
|
|
592
|
-
setColumnIds(columnIds) {
|
|
694
|
+
setColumnIds(columnIds, hiddenColumnIds = []) {
|
|
593
695
|
const previous = this.snapshot();
|
|
696
|
+
const previousHidden = new Set(this.hiddenColumnIds ?? []);
|
|
594
697
|
this.columnIds = normalizeUniqueColumnIds(columnIds);
|
|
595
|
-
this.
|
|
698
|
+
this.hiddenColumnIds = normalizeUniqueColumnIds(hiddenColumnIds);
|
|
699
|
+
this.rememberStaticVisibility(this.state, this.hiddenColumnIds.filter((columnId) => !previousHidden.has(columnId)));
|
|
700
|
+
const restoredVisibility = new Map(this.state.columnVisibility.map((entry) => [
|
|
701
|
+
entry.columnId,
|
|
702
|
+
entry.visible,
|
|
703
|
+
]));
|
|
704
|
+
for (const columnId of previousHidden) {
|
|
705
|
+
if (this.hiddenColumnIds.includes(columnId))
|
|
706
|
+
continue;
|
|
707
|
+
const visible = this.visibilityBeforeStaticHide.get(columnId);
|
|
708
|
+
if (visible !== undefined)
|
|
709
|
+
restoredVisibility.set(columnId, visible);
|
|
710
|
+
this.visibilityBeforeStaticHide.delete(columnId);
|
|
711
|
+
}
|
|
712
|
+
const knownColumns = new Set(this.columnIds);
|
|
713
|
+
for (const columnId of this.visibilityBeforeStaticHide.keys()) {
|
|
714
|
+
if (!knownColumns.has(columnId)) {
|
|
715
|
+
this.visibilityBeforeStaticHide.delete(columnId);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
this.state = normalizeState({
|
|
719
|
+
...this.state,
|
|
720
|
+
columnVisibility: [...restoredVisibility.entries()].map(([columnId, visible]) => ({ columnId, visible })),
|
|
721
|
+
}, this.columnIds, this.hiddenColumnIds);
|
|
596
722
|
const next = this.snapshot();
|
|
597
723
|
const changed = snapshotSignature(previous) !== snapshotSignature(next);
|
|
598
724
|
const transition = { command: null, previous, next, changed };
|
|
@@ -600,6 +726,22 @@ export class DataTableController {
|
|
|
600
726
|
this.emit(transition);
|
|
601
727
|
return transition;
|
|
602
728
|
}
|
|
729
|
+
rememberStaticVisibility(state, hiddenColumnIds, overwrite = false) {
|
|
730
|
+
const visibility = new Map(normalizeVisibility(state.columnVisibility ?? []).map((entry) => [
|
|
731
|
+
entry.columnId,
|
|
732
|
+
entry.visible,
|
|
733
|
+
]));
|
|
734
|
+
for (const columnId of hiddenColumnIds) {
|
|
735
|
+
const visible = visibility.get(columnId);
|
|
736
|
+
if (visible !== undefined &&
|
|
737
|
+
(overwrite || !this.visibilityBeforeStaticHide.has(columnId))) {
|
|
738
|
+
this.visibilityBeforeStaticHide.set(columnId, visible);
|
|
739
|
+
}
|
|
740
|
+
else if (!this.visibilityBeforeStaticHide.has(columnId)) {
|
|
741
|
+
this.visibilityBeforeStaticHide.set(columnId, true);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
603
745
|
/** Clamp against a reliable total. A missing total intentionally does not guess. */
|
|
604
746
|
clampPage(totalRows) {
|
|
605
747
|
if (totalRows === null || totalRows === undefined) {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DataTableColumnPinning, DataTableViewState } from './DataTableController.js';
|
|
2
|
+
import type { DataTableColumn } from './types.js';
|
|
3
|
+
export interface DataTableResolvedColumn<T> {
|
|
4
|
+
column: DataTableColumn<T>;
|
|
5
|
+
pin?: DataTableColumnPinning['position'];
|
|
6
|
+
/** A persisted pixel width supersedes the column's presentational default. */
|
|
7
|
+
width?: number;
|
|
8
|
+
/** CSS-safe width used for a sticky offset when one is available. */
|
|
9
|
+
offsetWidth: string;
|
|
10
|
+
stickyOffset?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DataTableHeaderGroupCell {
|
|
13
|
+
kind: 'group';
|
|
14
|
+
key: string;
|
|
15
|
+
label: string;
|
|
16
|
+
colspan: number;
|
|
17
|
+
rowspan: number;
|
|
18
|
+
pin?: DataTableColumnPinning['position'];
|
|
19
|
+
stickyOffset?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface DataTableHeaderLeafCell<T> {
|
|
22
|
+
kind: 'leaf';
|
|
23
|
+
column: DataTableResolvedColumn<T>;
|
|
24
|
+
rowspan: number;
|
|
25
|
+
}
|
|
26
|
+
export type DataTableHeaderCell<T> = DataTableHeaderGroupCell | DataTableHeaderLeafCell<T>;
|
|
27
|
+
export interface DataTableLayout<T> {
|
|
28
|
+
columns: DataTableResolvedColumn<T>[];
|
|
29
|
+
headerRows: DataTableHeaderCell<T>[][];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve a DOM-safe table layout from canonical controller state. Pinning is
|
|
33
|
+
* a partition of the configured order so the visual and assistive orders stay
|
|
34
|
+
* aligned. Header groups are then rebuilt from the final visible leaf order.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveDataTableLayout<T>(columns: readonly DataTableColumn<T>[], state: Pick<DataTableViewState, 'columnOrder' | 'columnVisibility' | 'columnWidths' | 'columnPinning'>, measuredWidths?: Readonly<Record<string, number>>): DataTableLayout<T>;
|
|
37
|
+
//# sourceMappingURL=DataTableLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTableLayout.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTableLayout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAA8B,MAAM,YAAY,CAAC;AAE9E,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACxC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAC3B,GAAG,CAAC,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC;IACzC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,sBAAsB,CAAC,UAAU,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAC7B,wBAAwB,GACxB,uBAAuB,CAAC,CAAC,CAAC,CAAC;AAE/B,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,OAAO,EAAE,uBAAuB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;CACxC;AA4GD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,OAAO,EAAE,SAAS,eAAe,CAAC,CAAC,CAAC,EAAE,EACtC,KAAK,EAAE,IAAI,CACT,kBAAkB,EAClB,aAAa,GAAG,kBAAkB,GAAG,cAAc,GAAG,eAAe,CACtE,EACD,cAAc,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GACpD,eAAe,CAAC,CAAC,CAAC,CA2DpB"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
function compareOrder(left, right, order) {
|
|
2
|
+
const leftOrder = order.get(left.id) ?? Number.MAX_SAFE_INTEGER;
|
|
3
|
+
const rightOrder = order.get(right.id) ?? Number.MAX_SAFE_INTEGER;
|
|
4
|
+
return leftOrder === rightOrder ? 0 : leftOrder - rightOrder;
|
|
5
|
+
}
|
|
6
|
+
function headerPath(column) {
|
|
7
|
+
const path = column.headerPath ?? [];
|
|
8
|
+
for (const segment of path) {
|
|
9
|
+
if (!segment ||
|
|
10
|
+
typeof segment.id !== 'string' ||
|
|
11
|
+
segment.id.length === 0 ||
|
|
12
|
+
typeof segment.label !== 'string' ||
|
|
13
|
+
segment.label.length === 0) {
|
|
14
|
+
throw new TypeError(`DataTable headerPath entries for ${column.id} require non-empty id and label`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return path;
|
|
18
|
+
}
|
|
19
|
+
function offsetWidth(column, width, measuredWidth) {
|
|
20
|
+
if (measuredWidth !== undefined && measuredWidth > 0) {
|
|
21
|
+
return `${measuredWidth}px`;
|
|
22
|
+
}
|
|
23
|
+
if (width !== undefined)
|
|
24
|
+
return `${width}px`;
|
|
25
|
+
return column.width ?? column.minWidth ?? '0px';
|
|
26
|
+
}
|
|
27
|
+
function resolveHeaderRows(columns) {
|
|
28
|
+
const paths = columns.map(({ column }) => headerPath(column));
|
|
29
|
+
const groupDepth = Math.max(0, ...paths.map((path) => path.length));
|
|
30
|
+
if (groupDepth === 0) {
|
|
31
|
+
return [columns.map((column) => ({ kind: 'leaf', column, rowspan: 1 }))];
|
|
32
|
+
}
|
|
33
|
+
const rows = Array.from({ length: groupDepth + 1 }, () => []);
|
|
34
|
+
for (let level = 0; level <= groupDepth; level += 1) {
|
|
35
|
+
let index = 0;
|
|
36
|
+
while (index < columns.length) {
|
|
37
|
+
const path = paths[index];
|
|
38
|
+
if (path.length < level) {
|
|
39
|
+
index += 1;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (path.length === level) {
|
|
43
|
+
rows[level].push({
|
|
44
|
+
kind: 'leaf',
|
|
45
|
+
column: columns[index],
|
|
46
|
+
rowspan: groupDepth - level + 1,
|
|
47
|
+
});
|
|
48
|
+
index += 1;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const segment = path[level];
|
|
52
|
+
let end = index + 1;
|
|
53
|
+
while (end < columns.length &&
|
|
54
|
+
paths[end][level]?.id === segment.id &&
|
|
55
|
+
paths[end][level]?.label === segment.label) {
|
|
56
|
+
end += 1;
|
|
57
|
+
}
|
|
58
|
+
rows[level].push({
|
|
59
|
+
kind: 'group',
|
|
60
|
+
key: `${level}:${index}:${segment.id}`,
|
|
61
|
+
label: segment.label,
|
|
62
|
+
colspan: end - index,
|
|
63
|
+
rowspan: 1,
|
|
64
|
+
...resolveGroupPin(columns.slice(index, end)),
|
|
65
|
+
});
|
|
66
|
+
index = end;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return rows;
|
|
70
|
+
}
|
|
71
|
+
function resolveGroupPin(columns) {
|
|
72
|
+
const pin = columns[0]?.pin;
|
|
73
|
+
if (!pin || !columns.every((column) => column.pin === pin))
|
|
74
|
+
return {};
|
|
75
|
+
const edge = pin === 'start' ? columns[0] : columns.at(-1);
|
|
76
|
+
return { pin, stickyOffset: edge?.stickyOffset };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Resolve a DOM-safe table layout from canonical controller state. Pinning is
|
|
80
|
+
* a partition of the configured order so the visual and assistive orders stay
|
|
81
|
+
* aligned. Header groups are then rebuilt from the final visible leaf order.
|
|
82
|
+
*/
|
|
83
|
+
export function resolveDataTableLayout(columns, state, measuredWidths = {}) {
|
|
84
|
+
const order = new Map(state.columnOrder.map((id, index) => [id, index]));
|
|
85
|
+
const visibility = new Map(state.columnVisibility.map((entry) => [entry.columnId, entry.visible]));
|
|
86
|
+
const widths = new Map(state.columnWidths.map((entry) => [entry.columnId, entry.width]));
|
|
87
|
+
const pinning = new Map(state.columnPinning.map((entry) => [entry.columnId, entry.position]));
|
|
88
|
+
const ordered = columns
|
|
89
|
+
.filter((column) => !column.hidden && visibility.get(column.id) !== false)
|
|
90
|
+
.slice()
|
|
91
|
+
.sort((left, right) => compareOrder(left, right, order));
|
|
92
|
+
const partitions = {
|
|
93
|
+
start: ordered.filter((column) => pinning.get(column.id) === 'start'),
|
|
94
|
+
center: ordered.filter((column) => !pinning.has(column.id)),
|
|
95
|
+
end: ordered.filter((column) => pinning.get(column.id) === 'end'),
|
|
96
|
+
};
|
|
97
|
+
const resolved = [];
|
|
98
|
+
let startOffset = '0px';
|
|
99
|
+
for (const column of partitions.start) {
|
|
100
|
+
const width = widths.get(column.id);
|
|
101
|
+
const offset = offsetWidth(column, width, measuredWidths[column.id]);
|
|
102
|
+
resolved.push({
|
|
103
|
+
column,
|
|
104
|
+
pin: 'start',
|
|
105
|
+
width,
|
|
106
|
+
offsetWidth: offset,
|
|
107
|
+
stickyOffset: startOffset,
|
|
108
|
+
});
|
|
109
|
+
startOffset = `calc(${startOffset} + ${offset})`;
|
|
110
|
+
}
|
|
111
|
+
for (const column of partitions.center) {
|
|
112
|
+
const width = widths.get(column.id);
|
|
113
|
+
resolved.push({
|
|
114
|
+
column,
|
|
115
|
+
width,
|
|
116
|
+
offsetWidth: offsetWidth(column, width, measuredWidths[column.id]),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
let endOffset = '0px';
|
|
120
|
+
const endColumns = [];
|
|
121
|
+
for (const column of partitions.end.slice().reverse()) {
|
|
122
|
+
const width = widths.get(column.id);
|
|
123
|
+
const offset = offsetWidth(column, width, measuredWidths[column.id]);
|
|
124
|
+
endColumns.unshift({
|
|
125
|
+
column,
|
|
126
|
+
pin: 'end',
|
|
127
|
+
width,
|
|
128
|
+
offsetWidth: offset,
|
|
129
|
+
stickyOffset: endOffset,
|
|
130
|
+
});
|
|
131
|
+
endOffset = `calc(${endOffset} + ${offset})`;
|
|
132
|
+
}
|
|
133
|
+
resolved.push(...endColumns);
|
|
134
|
+
return { columns: resolved, headerRows: resolveHeaderRows(resolved) };
|
|
135
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Published, testable scale guidance for the DataTable pipeline.
|
|
3
|
+
*
|
|
4
|
+
* These are interaction thresholds, not hard data limits. Use the benchmark
|
|
5
|
+
* fixture before raising them for a new renderer, browser target, or cell shape.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DATA_TABLE_SCALE_THRESHOLDS: {
|
|
8
|
+
readonly localRender: {
|
|
9
|
+
readonly maxRows: 250;
|
|
10
|
+
readonly maxCells: 5000;
|
|
11
|
+
readonly recommendation: "Use normal semantic rendering for ordinary, bounded result sets.";
|
|
12
|
+
};
|
|
13
|
+
readonly clientTransforms: {
|
|
14
|
+
readonly maxRows: 1000;
|
|
15
|
+
readonly maxCells: 20000;
|
|
16
|
+
readonly recommendation: "Use manual filtering, sorting, or paging once a client transform exceeds this budget.";
|
|
17
|
+
};
|
|
18
|
+
readonly manualPaging: {
|
|
19
|
+
readonly recommendedPageSize: 100;
|
|
20
|
+
readonly maxRenderedRows: 250;
|
|
21
|
+
readonly recommendation: "Keep remote pages bounded and pass totalRows only for a known server total.";
|
|
22
|
+
};
|
|
23
|
+
readonly virtualization: {
|
|
24
|
+
readonly minRows: 250;
|
|
25
|
+
readonly recommendation: "Use fixed-height virtualization for continuous browsing above the local render budget; preserve stable rowKey values and retain remote paging for unbounded data.";
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export type DataTableScaleStrategy = 'local' | 'manual-paging' | 'virtualization';
|
|
29
|
+
/** Returns the recommended rendering strategy for a known row and column count. */
|
|
30
|
+
export declare function recommendDataTableScaleStrategy(rowCount: number, columnCount: number): DataTableScaleStrategy;
|
|
31
|
+
//# sourceMappingURL=DataTablePerformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTablePerformance.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTablePerformance.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;CAwB9B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAC9B,OAAO,GACP,eAAe,GACf,gBAAgB,CAAC;AAErB,mFAAmF;AACnF,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,sBAAsB,CAwBxB"}
|