@svgrid/grid 2.6.20 → 2.6.22
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/CHANGELOG.md +62 -0
- package/README.md +22 -0
- package/dist/GridMenus.svelte +17 -12
- package/dist/SvGrid.controller.svelte.d.ts +14 -8
- package/dist/SvGrid.controller.svelte.js +214 -74
- package/dist/SvGrid.css +1 -1
- package/dist/SvGrid.svelte +112 -57
- package/dist/SvGrid.types.d.ts +191 -1
- package/dist/ai.d.ts +28 -0
- package/dist/ai.js +6 -0
- package/dist/cdn/{GridMenus-B0F9iBrG.js → GridMenus-BuoBPqxx.js} +137 -132
- package/dist/cdn/GridMenus-n4llxoOI.js +494 -0
- package/dist/cdn/column-resize-DsfNXMom.js +102 -0
- package/dist/cdn/row-resize-BRcimkUT.js +95 -0
- package/dist/cdn/{src-Cd0tearp.js → src-C9Hihx1W.js} +3497 -3487
- package/dist/cdn/{src-B1TdiyS8.js → src-D1lXwq1l.js} +8258 -8248
- package/dist/cdn/svgrid.js +10 -8
- package/dist/cdn/svgrid.svelte-external.js +10 -8
- package/dist/cdn/validate-_CDJzgIo.js +75 -0
- package/dist/cell-formatting.d.ts +2 -0
- package/dist/cell-formatting.js +2 -0
- package/dist/chart-export.d.ts +1 -0
- package/dist/chart.d.ts +31 -5
- package/dist/chart.js +9 -3
- package/dist/column-groups.js +1 -1
- package/dist/column-resize.d.ts +46 -0
- package/dist/column-resize.js +205 -0
- package/dist/columns.d.ts +0 -3
- package/dist/columns.js +0 -57
- package/dist/core.d.ts +216 -4
- package/dist/core.js +532 -119
- package/dist/createTree.svelte.d.ts +3 -0
- package/dist/createTree.svelte.js +1 -0
- package/dist/datetime/date-core.d.ts +2 -0
- package/dist/datetime/date-restrict.d.ts +1 -0
- package/dist/datetime/timezone.d.ts +1 -0
- package/dist/dock-manager-model.d.ts +3 -0
- package/dist/dock-manager-model.js +1 -0
- package/dist/dock-model.d.ts +6 -0
- package/dist/dock-model.js +3 -0
- package/dist/editor-contract.d.ts +1 -0
- package/dist/filtering/excel-filters.js +28 -0
- package/dist/group-display.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +6 -0
- package/dist/list-option.d.ts +1 -0
- package/dist/menus.js +1 -1
- package/dist/positioning.d.ts +2 -0
- package/dist/row-resize.d.ts +11 -0
- package/dist/row-resize.js +7 -1
- package/dist/scheduler-ical.d.ts +1 -0
- package/dist/scheduler-model.d.ts +1 -0
- package/dist/selection.js +9 -0
- package/dist/spreadsheet.d.ts +1 -1
- package/dist/spreadsheet.js +1 -1
- package/dist/summaries.js +22 -0
- package/dist/svgrid-wrapper.types.d.ts +5 -0
- package/dist/toast-store.svelte.d.ts +4 -0
- package/dist/validate.d.ts +50 -0
- package/dist/validate.js +187 -0
- package/package.json +4 -1
- package/src/GridMenus.svelte +17 -12
- package/src/SvGrid.controller.svelte.ts +223 -76
- package/src/SvGrid.css +1 -1
- package/src/SvGrid.svelte +112 -57
- package/src/SvGrid.types.ts +191 -1
- package/src/ai.ts +28 -0
- package/src/cell-formatting.ts +2 -0
- package/src/chart-export.ts +1 -0
- package/src/chart.ts +31 -5
- package/src/column-groups.ts +1 -1
- package/src/column-resize.test.ts +381 -0
- package/src/column-resize.ts +227 -0
- package/src/columns.test.ts +0 -103
- package/src/columns.ts +0 -58
- package/src/core.aggregate.test.ts +134 -0
- package/src/core.filter.test.ts +156 -0
- package/src/core.grouping.test.ts +146 -0
- package/src/core.row-shape.test.ts +119 -0
- package/src/core.rowmodel-cache.test.ts +121 -0
- package/src/core.sort.test.ts +293 -0
- package/src/core.ts +723 -119
- package/src/createTree.svelte.ts +3 -0
- package/src/datetime/date-core.ts +2 -0
- package/src/datetime/date-restrict.ts +1 -0
- package/src/datetime/timezone.ts +1 -0
- package/src/dock-manager-model.ts +3 -0
- package/src/dock-model.ts +6 -0
- package/src/editor-contract.ts +1 -0
- package/src/filtering/excel-filters.ts +30 -0
- package/src/filtering/normalize-fast-path.test.ts +104 -0
- package/src/group-display.ts +1 -1
- package/src/index.ts +12 -1
- package/src/list-option.ts +1 -0
- package/src/menus.ts +1 -1
- package/src/positioning.ts +2 -0
- package/src/resize-props.test.ts +361 -0
- package/src/row-resize.test.ts +31 -0
- package/src/row-resize.ts +21 -3
- package/src/scheduler-ical.ts +1 -0
- package/src/scheduler-model.ts +1 -0
- package/src/selection.ts +9 -0
- package/src/spreadsheet.ts +1 -1
- package/src/summaries.ts +21 -0
- package/src/svgrid-wrapper.types.ts +5 -0
- package/src/svgrid.summaries.test.ts +217 -0
- package/src/toast-store.svelte.ts +4 -0
- package/src/validate.test.ts +207 -0
- package/src/validate.ts +269 -0
- package/dist/cdn/GridMenus-IHK_l7m6.js +0 -489
package/dist/SvGrid.css
CHANGED
|
@@ -1573,7 +1573,7 @@ select.sv-grid-fr-editor {
|
|
|
1573
1573
|
position: relative;
|
|
1574
1574
|
}
|
|
1575
1575
|
/* Declarative cell validation (column `validate` hook). Invalid cells get a
|
|
1576
|
-
* soft red wash and a red inset ring -
|
|
1576
|
+
* soft red wash and a red inset ring - the conventional spreadsheet invalid-cell look. The
|
|
1577
1577
|
* value keeps rendering as-is; the message (if any) shows as the tooltip. */
|
|
1578
1578
|
.sv-grid-cell-invalid {
|
|
1579
1579
|
background-color: var(--sg-invalid-bg, rgba(239, 68, 68, 0.14)) !important;
|
package/dist/SvGrid.svelte
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
} from "./index";
|
|
16
16
|
import "./sv-grid-scrollbar";
|
|
17
17
|
import "./SvGrid.css";
|
|
18
|
+
import type { RowResizeOptions } from "./row-resize";
|
|
19
|
+
import type { ColumnResizeOptions } from "./column-resize";
|
|
18
20
|
import {
|
|
19
21
|
RenderSnippetConfig,
|
|
20
22
|
RenderComponentConfig,
|
|
@@ -167,7 +169,9 @@
|
|
|
167
169
|
const hideTooltip = $derived(ctrl.hideTooltip);
|
|
168
170
|
const findHits = $derived(ctrl.findHits);
|
|
169
171
|
const headerHeight = $derived(ctrl.headerHeight);
|
|
170
|
-
|
|
172
|
+
// Column resizing has always been unconditional; `columnResize={false}` is
|
|
173
|
+
// the opt-out, so the default has to stay on when the prop is absent.
|
|
174
|
+
const columnResizeEnabled = $derived(opt.columnResize === true);
|
|
171
175
|
const selectionColumnWidth = $derived(ctrl.selectionColumnWidth);
|
|
172
176
|
const rowNumberColumnWidth = $derived(ctrl.rowNumberColumnWidth);
|
|
173
177
|
const showRowNumbersEffective = $derived(ctrl.showRowNumbersEffective);
|
|
@@ -184,6 +188,7 @@
|
|
|
184
188
|
ctrl.showInlineColumnFilterEffective,
|
|
185
189
|
);
|
|
186
190
|
const showRowSelectionEffective = $derived(ctrl.showRowSelectionEffective);
|
|
191
|
+
const rowSummariesEnabled = $derived(ctrl.rowSummariesEnabled);
|
|
187
192
|
const grid = $derived(ctrl.grid);
|
|
188
193
|
const allColumns = $derived(ctrl.allColumns);
|
|
189
194
|
const headerGroups = $derived(ctrl.headerGroups);
|
|
@@ -263,6 +268,23 @@
|
|
|
263
268
|
// Row-grouping display modes: group state lives in synthetic columns instead
|
|
264
269
|
// of a full-width banner row.
|
|
265
270
|
const groupColumnMode = $derived(ctrl.groupColumnMode);
|
|
271
|
+
/**
|
|
272
|
+
* True when a cell's content needs none of the wrapper snippets.
|
|
273
|
+
*
|
|
274
|
+
* A cell body normally renders through `cellBodyWithFormat` ->
|
|
275
|
+
* `cellBodyFormatted` -> `cellBody`, and with no grouping, no tree data and
|
|
276
|
+
* no conditional formats the first two are pure pass-throughs: three snippet
|
|
277
|
+
* renders and two `{#if}` blocks per cell to reach content that one render
|
|
278
|
+
* produces. Measured by ablation, that chain is 4.2 ms of a 17.4 ms mount at
|
|
279
|
+
* 28 rows x 9 columns - about a quarter of the whole mount, and the largest
|
|
280
|
+
* single per-cell cost.
|
|
281
|
+
*
|
|
282
|
+
* Computed once per render rather than per cell, so the fast path costs one
|
|
283
|
+
* boolean read at each of the ~250 cells instead of two snippet frames.
|
|
284
|
+
*/
|
|
285
|
+
const plainCellBody = $derived(
|
|
286
|
+
!groupColumnMode && !treeData && !hasConditionalFormats,
|
|
287
|
+
);
|
|
266
288
|
const autoGroupCell = $derived(ctrl.autoGroupCell);
|
|
267
289
|
const isAutoGroupColumn = (id: string): boolean =>
|
|
268
290
|
id === "__autoGroup" || id.startsWith("__group_");
|
|
@@ -279,7 +301,60 @@
|
|
|
279
301
|
// The fixed row height, matching what the virtualized path takes from the virtualizer.
|
|
280
302
|
// The non-virtualized (`virtualization={false}`) body must apply this too, else its rows
|
|
281
303
|
// fall back to content height and look shorter than a virtualized grid's.
|
|
304
|
+
/**
|
|
305
|
+
* `rowResize` and `columnResize` are both opt-in and both default to OFF, so
|
|
306
|
+
* neither module is imported statically - a grid that leaves them alone must
|
|
307
|
+
* not carry their bytes. This wraps an action so its module is fetched on
|
|
308
|
+
* first enable and never otherwise. The handles appear a microtask after the
|
|
309
|
+
* first paint, which is invisible for a drag affordance.
|
|
310
|
+
*
|
|
311
|
+
* One helper for both: two hand-rolled copies of this bookkeeping would cost
|
|
312
|
+
* more base bundle than the deferral saves.
|
|
313
|
+
*/
|
|
314
|
+
type LazyHandle<O> = { update(o: O): void; destroy(): void };
|
|
315
|
+
function lazyAction<O extends { disabled?: boolean }>(
|
|
316
|
+
load: () => Promise<(node: HTMLElement, opts: O) => LazyHandle<O>>,
|
|
317
|
+
) {
|
|
318
|
+
return (node: HTMLElement, opts: O): LazyHandle<O> => {
|
|
319
|
+
let handle: LazyHandle<O> | null = null;
|
|
320
|
+
let current = opts;
|
|
321
|
+
let destroyed = false;
|
|
322
|
+
const ensure = () => {
|
|
323
|
+
if (handle || destroyed || current.disabled) return;
|
|
324
|
+
void load().then((make) => {
|
|
325
|
+
// The prop can be switched back off, or the grid unmounted, while
|
|
326
|
+
// the chunk is still in flight.
|
|
327
|
+
if (destroyed || current.disabled || handle) return;
|
|
328
|
+
handle = make(node, current);
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
ensure();
|
|
332
|
+
return {
|
|
333
|
+
update(next: O) {
|
|
334
|
+
current = next;
|
|
335
|
+
if (handle) handle.update(next);
|
|
336
|
+
else ensure();
|
|
337
|
+
},
|
|
338
|
+
destroy() {
|
|
339
|
+
destroyed = true;
|
|
340
|
+
handle?.destroy();
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const lazyRowResize = lazyAction<RowResizeOptions>(() =>
|
|
347
|
+
import("./row-resize").then((m) => m.rowResize),
|
|
348
|
+
);
|
|
349
|
+
const lazyColumnResize = lazyAction<ColumnResizeOptions>(() =>
|
|
350
|
+
import("./column-resize").then((m) => m.columnResize),
|
|
351
|
+
);
|
|
352
|
+
|
|
282
353
|
const rowSizePx = (i: number): number => {
|
|
354
|
+
// A height the user dragged wins over the declared one, so the row stays
|
|
355
|
+
// where they put it across re-renders and virtualization recycling.
|
|
356
|
+
const dragged = ctrl.rowResizeHeightPx(i);
|
|
357
|
+
if (dragged != null) return dragged;
|
|
283
358
|
const rh = opt.rowHeight;
|
|
284
359
|
return typeof rh === "function" ? rh(i) : (rh ?? 30);
|
|
285
360
|
};
|
|
@@ -357,26 +432,10 @@
|
|
|
357
432
|
return "sv-grid-cell-flash";
|
|
358
433
|
}
|
|
359
434
|
|
|
360
|
-
// Keyboard-accessible column resize (#79): focus a resize handle and use the
|
|
361
|
-
// arrow keys (Shift = fine 1px step). Complements the pointer-drag resize.
|
|
362
|
-
function resizeColumnByKeyboard(e: KeyboardEvent, columnId: string) {
|
|
363
|
-
let delta = 0;
|
|
364
|
-
const step = e.shiftKey ? 1 : 10;
|
|
365
|
-
if (e.key === "ArrowLeft") delta = -step;
|
|
366
|
-
else if (e.key === "ArrowRight") delta = step;
|
|
367
|
-
else return;
|
|
368
|
-
e.preventDefault();
|
|
369
|
-
const current = ctrl.getColumnWidth(columnId);
|
|
370
|
-
ctrl.columnWidths = {
|
|
371
|
-
...ctrl.columnWidths,
|
|
372
|
-
[columnId]: Math.max(40, current + delta),
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
|
|
376
435
|
// ---- Full-row editing -------------------------------------------------
|
|
377
436
|
const fullRowEdit = $derived(ctrl.fullRowEdit);
|
|
378
437
|
// Commit the whole row when the user clicks away from its editors (Excel /
|
|
379
|
-
//
|
|
438
|
+
// spreadsheet feel). Clicking within any full-row editor keeps editing.
|
|
380
439
|
// Stays here rather than in SvGridCellEditor: that component is instantiated
|
|
381
440
|
// once PER editable cell during a full-row edit, so a document listener there
|
|
382
441
|
// would be attached N times and commit N times.
|
|
@@ -428,7 +487,6 @@
|
|
|
428
487
|
const setActiveCell = $derived(ctrl.setActiveCell);
|
|
429
488
|
const scrollActiveCellIntoView = $derived(ctrl.scrollActiveCellIntoView);
|
|
430
489
|
const getColumnWidth = $derived(ctrl.getColumnWidth);
|
|
431
|
-
const startColumnResize = $derived(ctrl.startColumnResize);
|
|
432
490
|
const getCellRangeEdges = $derived(ctrl.getCellRangeEdges);
|
|
433
491
|
const fillHandleCell = $derived(ctrl.fillHandleCell);
|
|
434
492
|
const isInFillPreview = $derived(ctrl.isInFillPreview);
|
|
@@ -1293,6 +1351,26 @@
|
|
|
1293
1351
|
class="sv-grid-root"
|
|
1294
1352
|
class:sv-grid-root-fill={opt.containerHeight === "100%"}
|
|
1295
1353
|
style={chartDockReserveStyle}
|
|
1354
|
+
use:lazyRowResize={{
|
|
1355
|
+
disabled: !ctrl.rowResizeOn,
|
|
1356
|
+
// No gutter column on most grids, so fall back to the first body cell -
|
|
1357
|
+
// otherwise `rowResize` would be a prop that silently does nothing.
|
|
1358
|
+
anchor: "row",
|
|
1359
|
+
onResize: (index, height) => ctrl.setRowResizeHeight(index, height),
|
|
1360
|
+
}}
|
|
1361
|
+
use:lazyColumnResize={{
|
|
1362
|
+
disabled: !columnResizeEnabled,
|
|
1363
|
+
getWidth: (columnId) => ctrl.getColumnWidth(columnId),
|
|
1364
|
+
onResize: (columnId, width) => {
|
|
1365
|
+
ctrl.columnWidths = { ...ctrl.columnWidths, [columnId]: width };
|
|
1366
|
+
},
|
|
1367
|
+
label: (columnId) => {
|
|
1368
|
+
const col = ctrl.findColumnById(columnId);
|
|
1369
|
+
return col ? toolPanelHeaderLabel(col) : columnId;
|
|
1370
|
+
},
|
|
1371
|
+
canResize: (columnId) => ctrl.columnResizable(columnId),
|
|
1372
|
+
onAutosize: (columnId) => ctrl.autosizeColumn(columnId),
|
|
1373
|
+
}}
|
|
1296
1374
|
>
|
|
1297
1375
|
{#if showGlobalFilterEffective}
|
|
1298
1376
|
<label class="sv-grid-global-filter">
|
|
@@ -1746,32 +1824,6 @@
|
|
|
1746
1824
|
}}
|
|
1747
1825
|
/>
|
|
1748
1826
|
{/if}
|
|
1749
|
-
<div
|
|
1750
|
-
class="sv-grid-resize-handle"
|
|
1751
|
-
class:is-resizing={resizingColumnId ===
|
|
1752
|
-
header.column.id}
|
|
1753
|
-
role="separator"
|
|
1754
|
-
aria-orientation="vertical"
|
|
1755
|
-
aria-label={`Resize ${toolPanelHeaderLabel(header.column)}`}
|
|
1756
|
-
tabindex="0"
|
|
1757
|
-
{...(() => {
|
|
1758
|
-
// A focusable separator is a widget, so ARIA requires
|
|
1759
|
-
// aria-valuenow. The value it exposes is the column
|
|
1760
|
-
// width the arrow keys change; 40 is the floor
|
|
1761
|
-
// enforced in resizeColumnByKeyboard.
|
|
1762
|
-
const w = Math.round(ctrl.getColumnWidth(header.column.id));
|
|
1763
|
-
return {
|
|
1764
|
-
"aria-valuenow": w,
|
|
1765
|
-
"aria-valuemin": 40,
|
|
1766
|
-
"aria-valuetext": `${w} pixels`,
|
|
1767
|
-
};
|
|
1768
|
-
})()}
|
|
1769
|
-
onpointerdown={(event) =>
|
|
1770
|
-
startColumnResize(event, header.column.id)}
|
|
1771
|
-
onkeydown={(event) =>
|
|
1772
|
-
resizeColumnByKeyboard(event, header.column.id)}
|
|
1773
|
-
ondblclick={(event) => event.stopPropagation()}
|
|
1774
|
-
></div>
|
|
1775
1827
|
{/if}
|
|
1776
1828
|
</th>
|
|
1777
1829
|
{/if}
|
|
@@ -2176,12 +2228,11 @@
|
|
|
2176
2228
|
rendered.column.columnDef.cellFlash,
|
|
2177
2229
|
),
|
|
2178
2230
|
}}
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
})}
|
|
2231
|
+
role="gridcell"
|
|
2232
|
+
id={getGridCellDomId(ctrl.gridDomId, rowIndex, colIndex)}
|
|
2233
|
+
aria-colindex={colIndex + 1}
|
|
2234
|
+
aria-rowindex={rowIndex + 1}
|
|
2235
|
+
aria-selected={isRowSelected(row.id)}
|
|
2185
2236
|
>
|
|
2186
2237
|
{#if inRowEdit || isEditing}
|
|
2187
2238
|
<!-- The editing cell stays empty until the lazy
|
|
@@ -2193,11 +2244,15 @@
|
|
|
2193
2244
|
<CellEditor {ctrl} column={rendered.column} {row} fullRow={inRowEdit} />
|
|
2194
2245
|
{/if}
|
|
2195
2246
|
{:else}
|
|
2196
|
-
{
|
|
2197
|
-
row,
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2247
|
+
{#if plainCellBody}
|
|
2248
|
+
{@render cellBody(row, rendered.column, cellValue)}
|
|
2249
|
+
{:else}
|
|
2250
|
+
{@render cellBodyWithFormat(
|
|
2251
|
+
row,
|
|
2252
|
+
rendered.column,
|
|
2253
|
+
cellValue,
|
|
2254
|
+
)}
|
|
2255
|
+
{/if}
|
|
2201
2256
|
{/if}
|
|
2202
2257
|
{#if !isEditing && fillHandleCell && fillHandleCell.rowIndex === rowIndex && fillHandleCell.colIndex === colIndex}
|
|
2203
2258
|
<!-- Excel-style fill handle: drag down/right to
|
|
@@ -2519,7 +2574,7 @@
|
|
|
2519
2574
|
{/each}
|
|
2520
2575
|
</tbody>
|
|
2521
2576
|
{/if}
|
|
2522
|
-
{#if
|
|
2577
|
+
{#if rowSummariesEnabled}
|
|
2523
2578
|
<!-- svelte-ignore a11y_no_redundant_roles -->
|
|
2524
2579
|
<tfoot class="sv-grid-foot" role="rowgroup">
|
|
2525
2580
|
<tr
|
package/dist/SvGrid.types.d.ts
CHANGED
|
@@ -993,7 +993,21 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
993
993
|
* work; the shortcut wins only when it is explicitly set.
|
|
994
994
|
*/
|
|
995
995
|
sortable?: boolean;
|
|
996
|
+
/**
|
|
997
|
+
* Click a header to filter that column. Injects `columnFilteringFeature`,
|
|
998
|
+
* so you do not import it yourself. Which filter surface appears is a
|
|
999
|
+
* separate question - see `filterMode` (default `'menu'`).
|
|
1000
|
+
*
|
|
1001
|
+
* <SvGrid {data} {columns} filterable />
|
|
1002
|
+
*/
|
|
996
1003
|
filterable?: boolean;
|
|
1004
|
+
/**
|
|
1005
|
+
* Inline cell editing. Alias of `enableInlineEditing`, and wins over it when
|
|
1006
|
+
* both are set. A column also needs an `editorType` to be editable; without
|
|
1007
|
+
* one it falls back to a text editor.
|
|
1008
|
+
*
|
|
1009
|
+
* <SvGrid {data} {columns} editable />
|
|
1010
|
+
*/
|
|
997
1011
|
editable?: boolean;
|
|
998
1012
|
/**
|
|
999
1013
|
* Cell selection - click a cell to select it, drag or shift-click to extend
|
|
@@ -1045,6 +1059,16 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1045
1059
|
/** Indent per depth level, in px. Default `12`. */
|
|
1046
1060
|
indentPx?: number;
|
|
1047
1061
|
};
|
|
1062
|
+
/**
|
|
1063
|
+
* Show the grouping controls: "Group by this column" in the column menu, and
|
|
1064
|
+
* the group panel when `showGroupPanel` is on. Alias of
|
|
1065
|
+
* `showGroupingControls`, and also injects `columnGroupingFeature`.
|
|
1066
|
+
*
|
|
1067
|
+
* This turns on the UI for grouping. To group without asking the user, set
|
|
1068
|
+
* `groupBy` instead.
|
|
1069
|
+
*
|
|
1070
|
+
* <SvGrid {data} {columns} groupable />
|
|
1071
|
+
*/
|
|
1048
1072
|
groupable?: boolean;
|
|
1049
1073
|
/**
|
|
1050
1074
|
* Group the rows by these column ids, outermost first - `['region',
|
|
@@ -1122,7 +1146,19 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1122
1146
|
autoGroupColumnHeader?: string;
|
|
1123
1147
|
/** Width (px) of each auto-group column. Default `220`. */
|
|
1124
1148
|
autoGroupColumnWidth?: number;
|
|
1149
|
+
/**
|
|
1150
|
+
* Show the pagination footer. Alias of `showPagination`, and wins over it
|
|
1151
|
+
* when both are set. Page size starts at `pageSize` (default 10).
|
|
1152
|
+
*
|
|
1153
|
+
* <SvGrid {data} {columns} pageable pageSize={25} />
|
|
1154
|
+
*/
|
|
1125
1155
|
pageable?: boolean;
|
|
1156
|
+
/**
|
|
1157
|
+
* Show the loading state instead of the rows. By default this replaces the
|
|
1158
|
+
* grid body with "Loading..."; set `loadingOverlay` to keep the current rows
|
|
1159
|
+
* visible under a dimmed overlay instead, which is what you usually want for
|
|
1160
|
+
* a server-paged grid.
|
|
1161
|
+
*/
|
|
1126
1162
|
loading?: boolean;
|
|
1127
1163
|
/**
|
|
1128
1164
|
* Render `loading` as a non-blocking overlay instead of replacing the
|
|
@@ -1134,7 +1170,16 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1134
1170
|
loadingOverlay?: boolean;
|
|
1135
1171
|
/** Skeleton placeholder rows to show on first load. Defaults to 8. */
|
|
1136
1172
|
loadingSkeletonRows?: number;
|
|
1173
|
+
/**
|
|
1174
|
+
* Render an error message in place of the rows. `null` or omitted means no
|
|
1175
|
+
* error. Takes precedence over `loading` and over the empty state.
|
|
1176
|
+
*/
|
|
1137
1177
|
error?: string | null;
|
|
1178
|
+
/**
|
|
1179
|
+
* Text shown when there are no rows to display - either the data is empty or
|
|
1180
|
+
* a filter matched nothing. Defaults to the localized `noRows` string, so
|
|
1181
|
+
* prefer `localization.text.noRows` when you are translating the whole grid.
|
|
1182
|
+
*/
|
|
1138
1183
|
emptyMessage?: string;
|
|
1139
1184
|
/**
|
|
1140
1185
|
* The single place to localize the grid. One object with two fields:
|
|
@@ -1154,7 +1199,21 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1154
1199
|
* Omitting it (or any field) is a no-op. See {@link GridMessages}.
|
|
1155
1200
|
*/
|
|
1156
1201
|
localization?: GridLocalization;
|
|
1202
|
+
/**
|
|
1203
|
+
* Show the single search box that filters across every column. Explicitly
|
|
1204
|
+
* setting this wins over `filterMode`; leaving it unset means it appears only
|
|
1205
|
+
* when `filterMode` is `'global'`.
|
|
1206
|
+
*/
|
|
1157
1207
|
showGlobalFilter?: boolean;
|
|
1208
|
+
/**
|
|
1209
|
+
* Show the filter section inside each column's menu. Explicitly setting this
|
|
1210
|
+
* wins over `filterMode`; unset, it follows `filterMode` (default `'menu'`,
|
|
1211
|
+
* so this is normally on).
|
|
1212
|
+
*
|
|
1213
|
+
* Setting it `true` also adds the inline "floating filter" input under each
|
|
1214
|
+
* header - that surface requires the explicit opt-in, since it otherwise
|
|
1215
|
+
* duplicates the menu's own filter popover.
|
|
1216
|
+
*/
|
|
1158
1217
|
showColumnFilters?: boolean;
|
|
1159
1218
|
/**
|
|
1160
1219
|
* Quick way to pick a single filtering UI. When set it controls which of
|
|
@@ -1163,8 +1222,23 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1163
1222
|
* Defaults to `'menu'` (only the column menu's filter section is shown).
|
|
1164
1223
|
*/
|
|
1165
1224
|
filterMode?: "row" | "menu" | "global" | "none";
|
|
1225
|
+
/**
|
|
1226
|
+
* Show the grouping affordances (the column menu's "Group by this column",
|
|
1227
|
+
* and the group panel). The `groupable` shortcut sets this and registers the
|
|
1228
|
+
* grouping feature in one go; prefer that unless you have already registered
|
|
1229
|
+
* `columnGroupingFeature` yourself.
|
|
1230
|
+
*/
|
|
1166
1231
|
showGroupingControls?: boolean;
|
|
1232
|
+
/**
|
|
1233
|
+
* Show the row-selection checkbox column, including the select-all checkbox
|
|
1234
|
+
* in the header. Unset, it follows `selectionMode` (default `'both'`, so
|
|
1235
|
+
* row selection is on).
|
|
1236
|
+
*/
|
|
1167
1237
|
showRowSelection?: boolean;
|
|
1238
|
+
/**
|
|
1239
|
+
* Show the pagination footer. Off by default. `pageable` is the shortcut
|
|
1240
|
+
* alias and wins when both are set.
|
|
1241
|
+
*/
|
|
1168
1242
|
showPagination?: boolean;
|
|
1169
1243
|
/** Initial page size when pagination is enabled. Defaults to 10. */
|
|
1170
1244
|
pageSize?: number;
|
|
@@ -1197,6 +1271,14 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1197
1271
|
pageIndex: number;
|
|
1198
1272
|
pageSize: number;
|
|
1199
1273
|
}) => void;
|
|
1274
|
+
/**
|
|
1275
|
+
* Render only the rows in view instead of all of them. **On by default** -
|
|
1276
|
+
* this is what keeps a 100,000-row grid responsive.
|
|
1277
|
+
*
|
|
1278
|
+
* Turn it off when a row's height cannot be known up front and must not be
|
|
1279
|
+
* clipped, such as a variable-height master-detail panel. Expect the DOM to
|
|
1280
|
+
* hold every row when you do.
|
|
1281
|
+
*/
|
|
1200
1282
|
virtualization?: boolean;
|
|
1201
1283
|
/** Row height in pixels. Pass a function `(rowIndex) => px` for
|
|
1202
1284
|
* per-row variable heights (e.g. an interactive row-resize feature).
|
|
@@ -1214,6 +1296,28 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1214
1296
|
* supplying per-row heights).
|
|
1215
1297
|
*/
|
|
1216
1298
|
autoRowHeight?: boolean;
|
|
1299
|
+
/**
|
|
1300
|
+
* Let the user drag a row's bottom edge to change its height. **Off by
|
|
1301
|
+
* default**, because a resizable row needs somewhere to grab and most grids
|
|
1302
|
+
* do not want a drag target on every row.
|
|
1303
|
+
*
|
|
1304
|
+
* The grid remembers the heights itself, so this works as a bare boolean -
|
|
1305
|
+
* no `rowHeight` function required. Drag, or focus the grip and use Up/Down
|
|
1306
|
+
* (Shift for 1px steps).
|
|
1307
|
+
*
|
|
1308
|
+
* Turning this on also turns on the **row header column** ({@link
|
|
1309
|
+
* showRowNumbers}), because that is where the grip lives and where a
|
|
1310
|
+
* spreadsheet puts it - a drag target on the edge of a data cell works but
|
|
1311
|
+
* reads as an accident. An explicit `showRowNumbers={false}` still wins; the
|
|
1312
|
+
* grip then falls back to the row's first cell, and a column of your own
|
|
1313
|
+
* carrying `cellClass: 'sv-row-gutter'` is used ahead of either.
|
|
1314
|
+
*
|
|
1315
|
+
* Ignored under `autoRowHeight`, where the content decides the height and a
|
|
1316
|
+
* manual one would immediately be overwritten. For full control of the
|
|
1317
|
+
* heights - persisting them, sharing them between grids - pass a
|
|
1318
|
+
* function-valued {@link rowHeight} and use the `rowResize` action directly.
|
|
1319
|
+
*/
|
|
1320
|
+
rowResize?: boolean;
|
|
1217
1321
|
/**
|
|
1218
1322
|
* Height (px) of a single column-header level row. With multi-level
|
|
1219
1323
|
* (grouped) headers the total header height is `levels * headerHeight`,
|
|
@@ -1221,6 +1325,11 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1221
1325
|
* to their content (the default). Does not affect the filter row.
|
|
1222
1326
|
*/
|
|
1223
1327
|
headerHeight?: number;
|
|
1328
|
+
/**
|
|
1329
|
+
* Extra rows rendered above and below the viewport, so fast scrolling does
|
|
1330
|
+
* not reach empty space before the next batch renders. Defaults to 8.
|
|
1331
|
+
* Raise it for very tall rows, lower it to trim DOM work.
|
|
1332
|
+
*/
|
|
1224
1333
|
overscan?: number;
|
|
1225
1334
|
/**
|
|
1226
1335
|
* Height of the grid's scrollable shell. A number is treated as pixels;
|
|
@@ -1228,8 +1337,24 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1228
1337
|
* make the grid fill its parent. Defaults to 520 px.
|
|
1229
1338
|
*/
|
|
1230
1339
|
containerHeight?: number | string;
|
|
1340
|
+
/**
|
|
1341
|
+
* Render only the columns in view, the horizontal counterpart of
|
|
1342
|
+
* `virtualization`. **On by default**, which is what makes a 100-column grid
|
|
1343
|
+
* scroll smoothly.
|
|
1344
|
+
*
|
|
1345
|
+
* It recycles column DOM nodes, so it cannot coexist with sticky pinned
|
|
1346
|
+
* columns - turn it off if you need pinning to survive horizontal scrolling.
|
|
1347
|
+
*/
|
|
1231
1348
|
columnVirtualization?: boolean;
|
|
1349
|
+
/**
|
|
1350
|
+
* Extra columns rendered either side of the viewport when
|
|
1351
|
+
* `columnVirtualization` is on. Defaults to 3.
|
|
1352
|
+
*/
|
|
1232
1353
|
columnOverscan?: number;
|
|
1354
|
+
/**
|
|
1355
|
+
* Fallback width in pixels for columns whose `ColumnDef` sets no `width`.
|
|
1356
|
+
* Defaults to 140.
|
|
1357
|
+
*/
|
|
1233
1358
|
columnWidth?: number;
|
|
1234
1359
|
/**
|
|
1235
1360
|
* Columns pinned to the left/right edge on mount. Each entry is a
|
|
@@ -1251,6 +1376,24 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1251
1376
|
* win once they happen.
|
|
1252
1377
|
*/
|
|
1253
1378
|
fitColumns?: boolean;
|
|
1379
|
+
/**
|
|
1380
|
+
* Let the user drag a column's edge to change its width. **Off by default**,
|
|
1381
|
+
* so `width` means the width you asked for until you say otherwise.
|
|
1382
|
+
*
|
|
1383
|
+
* Turn it on for grids the reader is meant to arrange - a spreadsheet, a
|
|
1384
|
+
* dense report, anything with columns whose content varies in length. Leave
|
|
1385
|
+
* it off for layouts you control, and for columns that must keep their size:
|
|
1386
|
+
* a row-number gutter, a checkbox column, an icon column.
|
|
1387
|
+
*
|
|
1388
|
+
* It is grid-wide rather than per-column: there is no `resizable: false` on a
|
|
1389
|
+
* single column definition. `api.autosizeColumn()`, `fitColumns` and
|
|
1390
|
+
* programmatic width changes work either way - this only governs the drag
|
|
1391
|
+
* handle.
|
|
1392
|
+
*
|
|
1393
|
+
* The handles come from the `columnResize` action, loaded on demand: a grid
|
|
1394
|
+
* that leaves this off never fetches that code.
|
|
1395
|
+
*/
|
|
1396
|
+
columnResize?: boolean;
|
|
1254
1397
|
/**
|
|
1255
1398
|
* Make the grid usable on narrow screens. When the grid's own width drops
|
|
1256
1399
|
* below the breakpoint (default `640`px), pinned columns are un-pinned so the
|
|
@@ -1262,8 +1405,24 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1262
1405
|
responsive?: boolean | {
|
|
1263
1406
|
breakpoint?: number;
|
|
1264
1407
|
};
|
|
1408
|
+
/**
|
|
1409
|
+
* @deprecated Has no effect - nothing in the grid reads this prop. It is kept
|
|
1410
|
+
* only so existing code keeps compiling. The column menu's filter section is
|
|
1411
|
+
* controlled by `showColumnFilters`, or by `filterMode="menu"` (the default).
|
|
1412
|
+
*/
|
|
1265
1413
|
showFilterMenu?: boolean;
|
|
1414
|
+
/**
|
|
1415
|
+
* Show the always-visible filter row under the header. Explicitly setting
|
|
1416
|
+
* this wins over `filterMode`; unset, it appears only when `filterMode` is
|
|
1417
|
+
* `'row'`.
|
|
1418
|
+
*/
|
|
1266
1419
|
showFilterRow?: boolean;
|
|
1420
|
+
/**
|
|
1421
|
+
* Cell selection - click to select, drag or shift-click to extend to a range,
|
|
1422
|
+
* which is what clipboard copy and the range fill handle operate on. Unset,
|
|
1423
|
+
* it follows `selectionMode` (default `'both'`, so this is on). `selectable`
|
|
1424
|
+
* is the shortcut alias and wins over it.
|
|
1425
|
+
*/
|
|
1267
1426
|
enableCellSelection?: boolean;
|
|
1268
1427
|
/**
|
|
1269
1428
|
* Highlight the row under the pointer. Default **false** - the hover tint can
|
|
@@ -1289,6 +1448,14 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1289
1448
|
rowIndex: number;
|
|
1290
1449
|
columnId: string;
|
|
1291
1450
|
}) => unknown;
|
|
1451
|
+
/**
|
|
1452
|
+
* Inline cell editing: F2 or double-click opens an editor in the active cell,
|
|
1453
|
+
* Enter commits, Esc cancels. Off by default.
|
|
1454
|
+
*
|
|
1455
|
+
* A column still needs an `editorType` to pick its editor (text, number,
|
|
1456
|
+
* date, checkbox, list, ...); without one it gets a plain text editor.
|
|
1457
|
+
* `editable` is the shortcut alias and wins over this.
|
|
1458
|
+
*/
|
|
1292
1459
|
enableInlineEditing?: boolean;
|
|
1293
1460
|
/**
|
|
1294
1461
|
* Full-row editing. When `true`, starting an edit puts the WHOLE row into
|
|
@@ -1298,7 +1465,22 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1298
1465
|
* text / number / date / datetime / checkbox / list-select editor types.
|
|
1299
1466
|
*/
|
|
1300
1467
|
fullRowEditing?: boolean;
|
|
1468
|
+
/**
|
|
1469
|
+
* Append a sticky footer row aggregating every filtered row: the sum of a
|
|
1470
|
+
* numeric column, `Count: N` otherwise. Choose a different aggregate per
|
|
1471
|
+
* column with that column's own `summary` option, or set it to `false` there
|
|
1472
|
+
* to leave the cell blank.
|
|
1473
|
+
*
|
|
1474
|
+
* Off by default. `summary` is the shortcut alias and wins when both are set.
|
|
1475
|
+
*
|
|
1476
|
+
* <SvGrid {data} {columns} summary />
|
|
1477
|
+
*/
|
|
1301
1478
|
enableRowSummaries?: boolean;
|
|
1479
|
+
/**
|
|
1480
|
+
* Shortcut alias for {@link enableRowSummaries}. Wins over it when both are
|
|
1481
|
+
* set, the same precedence `selectable` has over `enableCellSelection`.
|
|
1482
|
+
*/
|
|
1483
|
+
summary?: boolean;
|
|
1302
1484
|
/**
|
|
1303
1485
|
* Excel-style status bar under the grid showing live aggregates of the
|
|
1304
1486
|
* selected cell range (count, numeric count, sum, average, min, max).
|
|
@@ -1321,7 +1503,7 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1321
1503
|
charting?: boolean | ChartingConfig<TData>;
|
|
1322
1504
|
/**
|
|
1323
1505
|
* Render the header column menu (⋮) as a tabbed popover - **General**,
|
|
1324
|
-
* **Filter**, and **Columns** tabs (the
|
|
1506
|
+
* **Filter**, and **Columns** tabs (the tabbed layout). Defaults to `false`,
|
|
1325
1507
|
* which keeps the flat menu (actions list + "Choose columns" submenu).
|
|
1326
1508
|
*/
|
|
1327
1509
|
columnMenuTabs?: boolean;
|
|
@@ -1514,6 +1696,14 @@ export type Props<TFeatures extends TableFeatures = TableFeatures, TData extends
|
|
|
1514
1696
|
* filter.
|
|
1515
1697
|
*/
|
|
1516
1698
|
conditionalStatScope?: "filtered" | "visible" | "all";
|
|
1699
|
+
/**
|
|
1700
|
+
* Fires after an inline edit commits, with the cell's old and new value and
|
|
1701
|
+
* the row it belongs to. This is where you persist the change.
|
|
1702
|
+
*
|
|
1703
|
+
* The grid has already applied the edit to its own state by the time this
|
|
1704
|
+
* runs, so it is a notification, not a veto - reject a value with the
|
|
1705
|
+
* column's `valueParser` or a validation rule instead.
|
|
1706
|
+
*/
|
|
1517
1707
|
onCellValueChange?: (event: {
|
|
1518
1708
|
rowIndex: number;
|
|
1519
1709
|
columnId: string;
|