@svgrid/grid 2.6.21 → 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 +13 -8
- package/dist/SvGrid.controller.svelte.js +150 -72
- package/dist/SvGrid.css +1 -1
- package/dist/SvGrid.svelte +110 -56
- package/dist/SvGrid.types.d.ts +41 -1
- package/dist/cdn/{GridMenus-BfTAKn84.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-BYq-qyrp.js → src-C9Hihx1W.js} +3456 -3459
- package/dist/cdn/{src-DBel9wRZ.js → src-D1lXwq1l.js} +8283 -8286
- package/dist/cdn/svgrid.js +10 -8
- package/dist/cdn/svgrid.svelte-external.js +10 -8
- 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 +19 -4
- package/dist/core.js +460 -119
- 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/menus.js +1 -1
- package/dist/row-resize.d.ts +11 -0
- package/dist/row-resize.js +7 -1
- package/dist/selection.js +9 -0
- package/dist/spreadsheet.d.ts +1 -1
- package/dist/spreadsheet.js +1 -1
- package/package.json +1 -1
- package/src/GridMenus.svelte +17 -12
- package/src/SvGrid.controller.svelte.ts +155 -74
- package/src/SvGrid.css +1 -1
- package/src/SvGrid.svelte +110 -56
- package/src/SvGrid.types.ts +41 -1
- 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 +516 -119
- 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/menus.ts +1 -1
- 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/selection.ts +9 -0
- package/src/spreadsheet.ts +1 -1
- package/dist/cdn/GridMenus-C3bJd7w8.js +0 -489
|
@@ -8,11 +8,39 @@ const DIACRITIC_RE = /[̀-ͯ]/g;
|
|
|
8
8
|
export function normalizeForFilter(s, locale) {
|
|
9
9
|
if (!s)
|
|
10
10
|
return '';
|
|
11
|
+
// Fast path for pure-ASCII input, which is the overwhelming majority of what
|
|
12
|
+
// a grid filters. Both of the expensive steps are provably no-ops there:
|
|
13
|
+
// ASCII is already NFD-normalised, and the combining-marks block this strips
|
|
14
|
+
// (U+0300..U+036F) contains no ASCII. So lowercasing alone is the same
|
|
15
|
+
// answer, and `normalize-fast-path.test.ts` checks that exhaustively over
|
|
16
|
+
// every ASCII code point rather than taking the argument on trust.
|
|
17
|
+
//
|
|
18
|
+
// Worth the branch: this runs once per cell per filter - 100,000 times for a
|
|
19
|
+
// one-column filter over a 100k grid - and a CPU profile of a browser filter
|
|
20
|
+
// put more time in this function than in any other.
|
|
21
|
+
//
|
|
22
|
+
// Note the locale still routes through toLocaleLowerCase even on the fast
|
|
23
|
+
// path: 'I'.toLocaleLowerCase('tr') is 'ı', so ASCII does NOT imply the
|
|
24
|
+
// locale can be ignored.
|
|
25
|
+
if (isAsciiOnly(s)) {
|
|
26
|
+
return locale ? s.toLocaleLowerCase(locale) : s.toLowerCase();
|
|
27
|
+
}
|
|
11
28
|
const stripped = s.normalize('NFD').replace(DIACRITIC_RE, '');
|
|
12
29
|
return locale
|
|
13
30
|
? stripped.toLocaleLowerCase(locale)
|
|
14
31
|
: stripped.toLowerCase();
|
|
15
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* True when every code unit is ASCII. A plain char-code scan, which is far
|
|
35
|
+
* cheaper than the `normalize()` + regex pass it lets us skip.
|
|
36
|
+
*/
|
|
37
|
+
function isAsciiOnly(s) {
|
|
38
|
+
for (let i = 0; i < s.length; i++) {
|
|
39
|
+
if (s.charCodeAt(i) > 127)
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
16
44
|
/**
|
|
17
45
|
* Delimiter used to serialise the `in` / `notIn` value list into the single
|
|
18
46
|
* `value` string that the filter model carries.
|
package/dist/group-display.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* Both are generic over the row / column shape (via small accessor callbacks) so
|
|
14
14
|
* they are trivially unit-testable and carry no dependency on the grid runtime.
|
|
15
15
|
*/
|
|
16
|
-
/**
|
|
16
|
+
/** Grouping display variants. */
|
|
17
17
|
export type GroupDisplayType = 'groupRows' | 'singleColumn' | 'multipleColumns';
|
|
18
18
|
export type GroupFooterOptions<R> = {
|
|
19
19
|
/** Depth of a row (group rows and their descendants). */
|
package/dist/index.d.ts
CHANGED
|
@@ -194,6 +194,7 @@ export { chartToSvgString, downloadChartSvg, chartToPngBlob, downloadChartPng, c
|
|
|
194
194
|
export { buildSparkline, toSparklineValues, type SparklineConfig, type SparklineType, type SparklineGeometry, } from './sparkline.js';
|
|
195
195
|
export { spreadsheetLayout, spansToMerges, type SpanColumn, type SpreadsheetActionOptions, type MergeSpec, type CellBorderSpec, type BorderSpec, } from './spreadsheet.js';
|
|
196
196
|
export { rowResize, type RowResizeOptions } from './row-resize.js';
|
|
197
|
+
export { columnResize, type ColumnResizeOptions } from './column-resize.js';
|
|
197
198
|
export { rowDropZone, type RowDragEndEvent, type RowDropZoneOptions } from './row-drag.js';
|
|
198
199
|
export { resolveColumnTypes, inferCellDataType, type CellDataType } from './column-types.js';
|
|
199
200
|
export { computeColumnGroupMeta, hiddenLeavesForCollapse, type ColumnGroupMeta, type ColumnGroupShow, } from './column-groups.js';
|
|
@@ -212,7 +213,7 @@ export { createVirtualizer } from './virtualization/virtualizer.js';
|
|
|
212
213
|
export { createSvelteVirtualizer } from './virtualization/svelte-virtualizer.svelte.js';
|
|
213
214
|
export { createColumnVirtualizer } from './virtualization/column-virtualizer.js';
|
|
214
215
|
export type { VirtualItem, VirtualizerOptions, VirtualizerState } from './virtualization/types.js';
|
|
215
|
-
export type { SvGridApi, SvGridFilterOperator, SvGridWrapperProps } from './svgrid-wrapper.types.js';
|
|
216
|
+
export type { SvGridApi, SvGridFilterOperator, SvGridViewState, SvGridWrapperProps, } from './svgrid-wrapper.types.js';
|
|
216
217
|
export { parseEditorValue, normalizeEditorOptions, type CellEditorType, type CellEditorOption, } from './editors/cell-editors.js';
|
|
217
218
|
export { applyExcelFilter, compileExcelFilter, normalizeForFilter, splitInTokens, joinInTokens, trailingInToken, type CompiledExcelFilter, type ExcelFilter, type ExcelFilterOperator, type ExcelFilterOptions, } from './filtering/excel-filters.js';
|
|
218
219
|
export { ALL_FILTER_OPERATORS, SET_OPERATOR_IDS, VALUELESS_OPERATOR_IDS, RANGE_OPERATOR_IDS, isSetOperator, isValuelessOperator, isRangeOperator, type FilterValueType, } from './filtering/filter-operator-catalogue.js';
|
package/dist/index.js
CHANGED
|
@@ -230,7 +230,13 @@ export { buildChart, formatChartValue, rowsToChartSpec, niceScale, niceLogScale,
|
|
|
230
230
|
export { chartToSvgString, downloadChartSvg, chartToPngBlob, downloadChartPng, chartSpecToCsv, downloadChartCsv, } from './chart-export.js';
|
|
231
231
|
export { buildSparkline, toSparklineValues, } from './sparkline.js';
|
|
232
232
|
export { spreadsheetLayout, spansToMerges, } from './spreadsheet.js';
|
|
233
|
+
// The two resize actions, exported as a matched pair. `<SvGrid>` drives both
|
|
234
|
+
// through the `rowResize` / `columnResize` props - both default OFF, both are
|
|
235
|
+
// turned on by setting them true, and the grid `import()`s the module itself so
|
|
236
|
+
// a grid that leaves them off carries neither. Import them directly only for a
|
|
237
|
+
// headless table, which renders its own rows and headers.
|
|
233
238
|
export { rowResize } from './row-resize.js';
|
|
239
|
+
export { columnResize } from './column-resize.js';
|
|
234
240
|
export { rowDropZone } from './row-drag.js';
|
|
235
241
|
export { resolveColumnTypes, inferCellDataType } from './column-types.js';
|
|
236
242
|
export { computeColumnGroupMeta, hiddenLeavesForCollapse, } from './column-groups.js';
|
package/dist/menus.js
CHANGED
|
@@ -118,7 +118,7 @@ export function createMenus(ctx) {
|
|
|
118
118
|
function openChooseColumns(event) {
|
|
119
119
|
event.stopPropagation();
|
|
120
120
|
// Submenu behavior: keep the parent operations menu open and float the
|
|
121
|
-
// Choose Columns panel out to the right of it
|
|
121
|
+
// Choose Columns panel out to the right of it, submenu-style. Falls
|
|
122
122
|
// back to below the item if the popover would clip the viewport.
|
|
123
123
|
const trigger = event.currentTarget;
|
|
124
124
|
const menuEl = trigger.closest(".sv-grid-menu");
|
package/dist/row-resize.d.ts
CHANGED
|
@@ -36,6 +36,17 @@ export type RowResizeOptions = {
|
|
|
36
36
|
max?: number;
|
|
37
37
|
/** When true, the action removes its strips and ignores events. */
|
|
38
38
|
disabled?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Where the drag strip is anchored.
|
|
41
|
+
* - `'gutter'` (default) - only rows that have a row-header gutter cell get
|
|
42
|
+
* a strip: the built-in row-number column (`showRowNumbers`) or a column
|
|
43
|
+
* tagged `cellClass: 'sv-row-gutter'`. Rows without one are skipped, so on
|
|
44
|
+
* a plain grid the action does nothing.
|
|
45
|
+
* - `'row'` - use the gutter when there is one, otherwise fall back to the
|
|
46
|
+
* row's first body cell. This is what `<SvGrid rowResize>` passes, so the
|
|
47
|
+
* prop works without also asking for a gutter column.
|
|
48
|
+
*/
|
|
49
|
+
anchor?: 'gutter' | 'row';
|
|
39
50
|
};
|
|
40
51
|
export declare function rowResize(node: HTMLElement, opts: RowResizeOptions): {
|
|
41
52
|
update(next: RowResizeOptions): void;
|
package/dist/row-resize.js
CHANGED
|
@@ -141,7 +141,13 @@ export function rowResize(node, opts) {
|
|
|
141
141
|
// A row-header gutter cell: either a user column tagged
|
|
142
142
|
// `sv-row-gutter`, or the grid's built-in row-number gutter
|
|
143
143
|
// (`showRowNumbers`), whose cell is `.sv-grid-row-number-cell`.
|
|
144
|
-
const gutter = tr.querySelector('.sv-grid-cell.sv-row-gutter, .sv-grid-cell.sv-grid-row-number-cell')
|
|
144
|
+
const gutter = tr.querySelector('.sv-grid-cell.sv-row-gutter, .sv-grid-cell.sv-grid-row-number-cell') ??
|
|
145
|
+
// `anchor: 'row'` - no gutter on this grid, so hang the strip off the
|
|
146
|
+
// first body cell instead. Without this a grid with no row-number
|
|
147
|
+
// column would silently not resize.
|
|
148
|
+
(current.anchor === 'row'
|
|
149
|
+
? tr.querySelector('.sv-grid-cell')
|
|
150
|
+
: null);
|
|
145
151
|
if (!gutter)
|
|
146
152
|
continue;
|
|
147
153
|
if (gutter.querySelector(`:scope > .${STRIP_CLASS}`))
|
package/dist/selection.js
CHANGED
|
@@ -225,6 +225,15 @@ export function createSelection(ctx) {
|
|
|
225
225
|
* outline wins on overlap). Returns null when the cell is in no range.
|
|
226
226
|
*/
|
|
227
227
|
function getCellRangeEdges(rowIndex, colIndex) {
|
|
228
|
+
// Bail before `getSelectionRects()`, which allocates an array and resolves
|
|
229
|
+
// every range. This runs once per rendered CELL on every render - about 250
|
|
230
|
+
// times per frame on a default grid - and with nothing selected it did all
|
|
231
|
+
// that work to return null every time. An anchored active range or a
|
|
232
|
+
// committed one is the only way any rect can exist.
|
|
233
|
+
const active = ctx.selectionRange;
|
|
234
|
+
const committed = ctx.selectionRanges;
|
|
235
|
+
if (!committed?.length && !(active?.anchor && active?.focus))
|
|
236
|
+
return null;
|
|
228
237
|
for (const rect of getSelectionRects()) {
|
|
229
238
|
if (rowIndex < rect.minRow ||
|
|
230
239
|
rowIndex > rect.maxRow ||
|
package/dist/spreadsheet.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export type SpanColumn<TData = Record<string, unknown>> = {
|
|
|
63
63
|
/**
|
|
64
64
|
* Turn declarative per-column `colSpan` / `rowSpan` callbacks into a
|
|
65
65
|
* `MergeSpec[]` you can hand to `spreadsheetLayout` - so value-driven,
|
|
66
|
-
*
|
|
66
|
+
* Declarative spanning runs on the SAME real colspan/rowspan merge engine
|
|
67
67
|
* instead of a second code path. Recompute after sort/filter (indexes are
|
|
68
68
|
* display-row indexes). A common pattern is "merge runs of equal values":
|
|
69
69
|
*
|
package/dist/spreadsheet.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
/**
|
|
23
23
|
* Turn declarative per-column `colSpan` / `rowSpan` callbacks into a
|
|
24
24
|
* `MergeSpec[]` you can hand to `spreadsheetLayout` - so value-driven,
|
|
25
|
-
*
|
|
25
|
+
* Declarative spanning runs on the SAME real colspan/rowspan merge engine
|
|
26
26
|
* instead of a second code path. Recompute after sort/filter (indexes are
|
|
27
27
|
* display-row indexes). A common pattern is "merge runs of equal values":
|
|
28
28
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svgrid/grid",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.22",
|
|
4
4
|
"description": "Svelte 5-native data grid and data table. Headless-first engine with virtual scrolling for 100k+ rows, Excel-style filtering, inline editing, grouping, tree data, pivot, and server-side data. Drop-in <SvGrid> component. TypeScript, SSR-ready.",
|
|
5
5
|
"author": "jQWidgets <boikom@jqwidgets.com>",
|
|
6
6
|
"license": "MIT",
|
package/src/GridMenus.svelte
CHANGED
|
@@ -450,18 +450,23 @@
|
|
|
450
450
|
</button>
|
|
451
451
|
{/if}
|
|
452
452
|
<div class="sv-grid-menu-sep"></div>
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
453
|
+
<!-- `resizable: false` means the width is part of the layout, so the
|
|
454
|
+
menu must not offer to change it either - otherwise removing the
|
|
455
|
+
drag handle just moves the same action one click away. -->
|
|
456
|
+
{#if ctrl.columnResizable(menuColumnId)}
|
|
457
|
+
<button
|
|
458
|
+
type="button"
|
|
459
|
+
class="sv-grid-menu-item"
|
|
460
|
+
role="menuitem"
|
|
461
|
+
onclick={() => {
|
|
462
|
+
autosizeColumn(menuColumnId);
|
|
463
|
+
closeMenus();
|
|
464
|
+
}}
|
|
465
|
+
>
|
|
466
|
+
<span class="sv-grid-header-icon">{@render icon("autosize")}</span> Autosize
|
|
467
|
+
this column
|
|
468
|
+
</button>
|
|
469
|
+
{/if}
|
|
465
470
|
<button
|
|
466
471
|
type="button"
|
|
467
472
|
class="sv-grid-menu-item"
|