@svgrid/grid 2.2.27 → 2.2.29
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 +199 -199
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +179 -179
- package/dist/GridMenus.svelte +782 -734
- package/dist/SvAutoComplete.svelte +165 -165
- package/dist/SvCalendar.svelte +503 -503
- package/dist/SvCarousel.svelte +141 -141
- package/dist/SvCheckBox.svelte +101 -101
- package/dist/SvColorInput.svelte +181 -181
- package/dist/SvComboBox.svelte +275 -275
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +160 -160
- package/dist/SvDrawer.svelte +254 -250
- package/dist/SvDropDownList.svelte +374 -374
- package/dist/SvDurationInput.svelte +126 -126
- package/dist/SvField.svelte +293 -293
- package/dist/SvForm.svelte +437 -437
- package/dist/SvGrid.controller.svelte.d.ts +14 -1
- package/dist/SvGrid.controller.svelte.js +112 -28
- package/dist/SvGrid.css +2704 -2723
- package/dist/SvGrid.svelte +3361 -3333
- package/dist/SvGrid.types.d.ts +20 -5
- package/dist/SvGridChart.svelte +1724 -1724
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridChartView.svelte +70 -70
- package/dist/SvGridDropdown.svelte +696 -696
- package/dist/SvGridSelect.svelte +259 -259
- package/dist/SvGroupCell.svelte +109 -109
- package/dist/SvListBox.svelte +326 -287
- package/dist/SvListBox.svelte.d.ts +10 -1
- package/dist/SvMaskedInput.svelte +122 -122
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +146 -146
- package/dist/SvMultiSelect.svelte +281 -281
- package/dist/SvNumberInput.svelte +168 -168
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPasswordInput.svelte +151 -151
- package/dist/SvPhoneInput.svelte +133 -131
- package/dist/SvPopover.svelte +197 -197
- package/dist/SvRadioGroup.svelte +107 -107
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvSlider.svelte +200 -200
- package/dist/SvSwitchButton.svelte +107 -107
- package/dist/SvTagsInput.svelte +112 -112
- package/dist/SvTextInput.svelte +147 -147
- package/dist/SvTimePicker.svelte +245 -245
- package/dist/SvToaster.svelte +159 -159
- package/dist/SvToggleButton.svelte +85 -85
- package/dist/SvTooltip.svelte +161 -161
- package/dist/SvTour.svelte +204 -204
- package/dist/SvTree.svelte +437 -437
- package/dist/SvTreeSelect.svelte +233 -233
- package/dist/cdn/GridMenus-Da_p7SKS.js +486 -0
- package/dist/cdn/GridMenus-Ds3OpzZT.js +490 -0
- package/dist/cdn/{SvDateTimePicker-B1sDc9Pz.js → SvDateTimePicker-B8GopjhC.js} +2 -2
- package/dist/cdn/{SvDateTimePicker-Bh0FTs1E.js → SvDateTimePicker-DB0aIEk8.js} +2 -2
- package/dist/cdn/{SvGridChart-Bgk4hDs8.js → SvGridChart-BcLCYvw9.js} +1 -1
- package/dist/cdn/{SvGridChart-BKQsO5fZ.js → SvGridChart-BhnFdLd0.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-DkCc2Z7b.js → SvGridChartPanel-Cmx9DHAS.js} +1 -1
- package/dist/cdn/{SvGridChartPanel-DSkHIQDd.js → SvGridChartPanel-DvjwxLvK.js} +1 -1
- package/dist/cdn/{SvGridChartView-BrbVaELm.js → SvGridChartView-B40DTJSX.js} +1 -1
- package/dist/cdn/{SvGridChartView-i9rWvSKg.js → SvGridChartView-PwqI4s02.js} +1 -1
- package/dist/cdn/{SvGridDropdown-D08sVmAy.js → SvGridDropdown-DjALc_4f.js} +1 -1
- package/dist/cdn/{SvGridDropdown-CGxxopQ4.js → SvGridDropdown-hpnHvOGt.js} +1 -1
- package/dist/cdn/{src-cgs1wcUS.js → src-BLJfdyL0.js} +4034 -3889
- package/dist/cdn/{src-Cw8d9U8j.js → src-DYDCiC0D.js} +7053 -6908
- package/dist/cdn/svgrid.js +9 -9
- package/dist/cdn/svgrid.svelte-external.js +9 -9
- package/dist/chart-export.js +8 -8
- package/dist/column-groups.js +8 -10
- package/dist/column-id.d.ts +9 -0
- package/dist/column-id.js +25 -0
- package/dist/core.js +2 -1
- package/dist/createListbox.svelte.d.ts +15 -2
- package/dist/createListbox.svelte.js +27 -6
- package/dist/editing.d.ts +1 -0
- package/dist/editing.js +45 -10
- package/dist/filtering/excel-filters.d.ts +30 -10
- package/dist/filtering/excel-filters.js +96 -15
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/menus.d.ts +2 -0
- package/dist/menus.js +25 -0
- package/dist/row-resize.js +40 -0
- package/dist/selection.js +1 -1
- package/package.json +10 -10
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +179 -179
- package/src/GridMenus.svelte +782 -734
- package/src/SvAutoComplete.svelte +165 -165
- package/src/SvCalendar.svelte +503 -503
- package/src/SvCalendar.test.ts +226 -226
- package/src/SvCarousel.svelte +141 -141
- package/src/SvCheckBox.svelte +101 -101
- package/src/SvColorInput.svelte +181 -181
- package/src/SvComboBox.svelte +275 -275
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +160 -160
- package/src/SvDrawer.svelte +254 -250
- package/src/SvDrawer.test.ts +18 -1
- package/src/SvDropDownList.svelte +374 -374
- package/src/SvDurationInput.svelte +126 -126
- package/src/SvField.svelte +293 -293
- package/src/SvForm.svelte +437 -437
- package/src/SvForm.test.ts +411 -411
- package/src/SvGrid.controller.svelte.ts +3335 -3239
- package/src/SvGrid.css +2704 -2723
- package/src/SvGrid.svelte +3361 -3333
- package/src/SvGrid.types.ts +1628 -1613
- package/src/SvGridChart.svelte +1724 -1724
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridChartView.svelte +70 -70
- package/src/SvGridDropdown.svelte +696 -696
- package/src/SvGridSelect.svelte +259 -259
- package/src/SvGroupCell.svelte +109 -109
- package/src/SvListBox.svelte +326 -287
- package/src/SvMaskedInput.svelte +122 -122
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -97
- package/src/SvMenuList.svelte +146 -146
- package/src/SvMultiSelect.svelte +281 -281
- package/src/SvNavPane.test.ts +15 -4
- package/src/SvNumberInput.svelte +168 -168
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPasswordInput.svelte +151 -151
- package/src/SvPhoneInput.svelte +133 -131
- package/src/SvPopover.svelte +197 -197
- package/src/SvRadioGroup.svelte +107 -107
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvSlider.svelte +200 -200
- package/src/SvSwitchButton.svelte +107 -107
- package/src/SvTagsInput.svelte +112 -112
- package/src/SvTextInput.svelte +147 -147
- package/src/SvTimePicker.svelte +245 -245
- package/src/SvToaster.svelte +159 -159
- package/src/SvToaster.test.ts +95 -95
- package/src/SvToggleButton.svelte +85 -85
- package/src/SvTooltip.svelte +161 -161
- package/src/SvTour.svelte +204 -204
- package/src/SvTree.svelte +437 -437
- package/src/SvTreeSelect.svelte +233 -233
- package/src/a11y/dismissable.test.ts +119 -119
- package/src/a11y/dismissable.ts +114 -114
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/ai.test.ts +502 -502
- package/src/ai.ts +1391 -1391
- package/src/build-api.coverage.test.ts +633 -633
- package/src/build-api.ts +895 -895
- package/src/builtin-editors.grid.test.ts +85 -85
- package/src/cell-formatting.ts +169 -169
- package/src/cell-render.ts +469 -469
- package/src/chart-export.ts +201 -201
- package/src/chart-view.svelte.ts +36 -36
- package/src/chart.ts +2296 -2296
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/column-groups.test.ts +48 -0
- package/src/column-groups.ts +8 -10
- package/src/column-id.ts +30 -0
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1112 -1111
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCombobox.svelte.ts +191 -191
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +168 -168
- package/src/createForm.svelte.ts +386 -386
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createListbox.svelte.ts +39 -7
- package/src/createMenu.svelte.ts +225 -225
- package/src/createPopoverSelect.svelte.ts +213 -213
- package/src/createSlider.svelte.ts +191 -191
- package/src/createTooltip.svelte.ts +144 -144
- package/src/createTree.svelte.ts +319 -319
- package/src/editing.test.ts +949 -859
- package/src/editing.ts +709 -675
- package/src/editor-contract.ts +157 -157
- package/src/export-data-api.test.ts +126 -126
- package/src/export-format.test.ts +107 -107
- package/src/export-format.ts +598 -598
- package/src/filter-operators.ts +157 -157
- package/src/filtering/excel-filters.test.ts +44 -1
- package/src/filtering/excel-filters.ts +91 -14
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +127 -127
- package/src/index.ts +715 -713
- package/src/js-scroller.svelte.ts +173 -173
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -49
- package/src/list-nav.ts +29 -29
- package/src/list-option.test.ts +56 -56
- package/src/list-option.ts +172 -172
- package/src/menus.test.ts +736 -700
- package/src/menus.ts +679 -652
- package/src/merge-objects.ts +48 -48
- package/src/overlays.test.ts +90 -90
- package/src/render-component.ts +28 -28
- package/src/row-resize.test.ts +100 -0
- package/src/row-resize.ts +36 -0
- package/src/scheduler-model.test.ts +562 -562
- package/src/scheduler-model.ts +872 -872
- package/src/selection.test.ts +754 -754
- package/src/selection.ts +600 -600
- package/src/server-data-source.test.ts +289 -289
- package/src/server-data-source.ts +413 -413
- package/src/sparkline.test.ts +68 -68
- package/src/sparkline.ts +169 -169
- package/src/spreadsheet.test.ts +489 -489
- package/src/spreadsheet.ts +312 -312
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/svgrid-wrapper.types.ts +524 -524
- package/src/svgrid.api-extensions.test.ts +8 -3
- package/src/svgrid.behavior.test.ts +706 -706
- package/src/svgrid.cell-dom-ids.test.ts +96 -0
- package/src/svgrid.charting.test.ts +534 -534
- package/src/svgrid.conditional-stat-scope.test.ts +111 -0
- package/src/svgrid.features.test.ts +157 -157
- package/src/svgrid.filter-menu-listbox.svelte.test.ts +308 -0
- package/src/svgrid.filter-menu-scroll.test.ts +3 -1
- package/src/svgrid.group-header-ids.test.ts +121 -0
- package/src/svgrid.new-features.wrapper.test.ts +251 -251
- package/src/svgrid.wrapper.test.ts +40 -40
- package/src/test-setup.ts +62 -62
- package/src/themes/index.ts +215 -215
- package/src/toast-store.svelte.ts +246 -246
- package/src/toast-store.test.ts +147 -147
- package/src/ui-buttons.test.ts +144 -144
- package/src/ui-inputs.test.ts +118 -118
- package/src/ui-range.test.ts +70 -70
- package/src/ui-selection.test.ts +155 -155
- package/src/ui-tier1.test.ts +142 -142
- package/src/virtual.test.ts +88 -88
- package/src/virtualization/column-virtualizer.test.ts +27 -27
- package/src/virtualization/column-virtualizer.ts +30 -30
- package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
- package/src/virtualization/types.ts +30 -30
- package/src/virtualization/virtualizer.test.ts +47 -47
- package/src/virtualization/virtualizer.ts +296 -296
- package/themes/ember.css +71 -71
- package/dist/cdn/GridMenus-BzxEYNtW.js +0 -421
- package/dist/cdn/GridMenus-Dr-nGEXn.js +0 -417
|
@@ -12,7 +12,7 @@ import { getColumnBaseValue, isGroupRow, toolPanelHeaderLabel, formatSummaryNume
|
|
|
12
12
|
* the component lifecycle) and consumed through the returned getters.
|
|
13
13
|
*/
|
|
14
14
|
export type SvGridController<TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData> = ReturnType<typeof createSvGridController<TFeatures, TData>>;
|
|
15
|
-
export declare function createSvGridController<TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData>(rawProps: Props<TFeatures, TData
|
|
15
|
+
export declare function createSvGridController<TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData>(rawProps: Props<TFeatures, TData>, domIdBase?: string): {
|
|
16
16
|
readonly props: Props<TFeatures, TData>;
|
|
17
17
|
optionOverrides: Record<string, unknown>;
|
|
18
18
|
readonly editingEnabled: boolean;
|
|
@@ -126,6 +126,10 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
126
126
|
inSuggestPos: MenuPosition;
|
|
127
127
|
inSuggestQuery: string;
|
|
128
128
|
readonly inSuggestValues: string[];
|
|
129
|
+
readonly inSuggestOptions: {
|
|
130
|
+
value: string;
|
|
131
|
+
label: string;
|
|
132
|
+
}[];
|
|
129
133
|
readonly facetValuesForColumn: (columnId: string) => Array<string>;
|
|
130
134
|
chooseColumnsPos: MenuPosition | null;
|
|
131
135
|
contextMenuFor: ContextMenuTarget<TData> | null;
|
|
@@ -446,6 +450,7 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
446
450
|
readonly columnWindowRightSpacer: number;
|
|
447
451
|
readonly activeCell: any;
|
|
448
452
|
readonly activeDescendantId: string | null;
|
|
453
|
+
readonly gridDomId: string;
|
|
449
454
|
readonly formatSummaryNumeric: typeof formatSummaryNumeric;
|
|
450
455
|
readonly computeSummaries: (rows: readonly Row<TData>[], columns: readonly Column<TData>[]) => Record<string, string>;
|
|
451
456
|
readonly SUMMARY_DEFER_CELL_LIMIT: number;
|
|
@@ -549,6 +554,7 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
549
554
|
}, direction: "undo" | "redo") => void;
|
|
550
555
|
readonly updateEditingCellValue: (value: unknown) => void;
|
|
551
556
|
readonly onEditorKeyDown: (event: KeyboardEvent) => void;
|
|
557
|
+
readonly commitAndMoveByTab: (shiftKey: boolean) => void;
|
|
552
558
|
readonly focusOnMount: (node: HTMLInputElement | HTMLTextAreaElement) => void;
|
|
553
559
|
readonly onHeaderSortClick: (event: MouseEvent, columnId: string) => void;
|
|
554
560
|
readonly onGridKeyDown: (event: KeyboardEvent) => void;
|
|
@@ -594,6 +600,7 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
594
600
|
readonly addFilterToken: (columnId: string, token: string) => void;
|
|
595
601
|
readonly removeFilterToken: (columnId: string, token: string) => void;
|
|
596
602
|
readonly toggleFilterToken: (columnId: string, token: string) => void;
|
|
603
|
+
readonly setFilterTokens: (columnId: string, tokens: Iterable<string>) => void;
|
|
597
604
|
readonly sortColumnFromMenu: (columnId: string, desc: boolean) => void;
|
|
598
605
|
readonly clearColumnSort: (columnId: string) => void;
|
|
599
606
|
readonly groupByColumnFromMenu: (columnId: string) => void;
|
|
@@ -605,8 +612,14 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
605
612
|
readonly serverFacetLoading: string | null;
|
|
606
613
|
readonly columnMenuFacetValues: string[];
|
|
607
614
|
readonly columnMenuVisibleFacets: string[];
|
|
615
|
+
readonly columnMenuFacetOptions: {
|
|
616
|
+
value: string;
|
|
617
|
+
label: string;
|
|
618
|
+
}[];
|
|
619
|
+
readonly columnMenuSelectedFacets: ReadonlySet<string>;
|
|
608
620
|
readonly isFacetChecked: (columnId: string, value: string) => any;
|
|
609
621
|
readonly toggleFacetValue: (columnId: string, value: string) => void;
|
|
622
|
+
readonly setFacetSelection: (columnId: string, next: ReadonlySet<string>) => void;
|
|
610
623
|
readonly isAllFacetsChecked: (columnId: string) => boolean;
|
|
611
624
|
readonly toggleAllFacets: (columnId: string) => void;
|
|
612
625
|
readonly clearColumnFilter: (columnId: string) => void;
|
|
@@ -16,6 +16,7 @@ import { createRowDrag, } from "./row-drag";
|
|
|
16
16
|
import { createAlignedGrids, } from "./aligned-grids";
|
|
17
17
|
import { resolveColumnTypes, } from "./column-types";
|
|
18
18
|
import { computeColumnGroupMeta, hiddenLeavesForCollapse, } from "./column-groups";
|
|
19
|
+
import { resolveColumnId } from "./column-id";
|
|
19
20
|
import { createGridApi, } from "./build-api";
|
|
20
21
|
import { createClipboard, } from "./clipboard";
|
|
21
22
|
import { resolveGridMessages } from "./grid-messages";
|
|
@@ -23,6 +24,7 @@ import { getPivotEngine, hasPivotEngine } from "./pivot-view.svelte";
|
|
|
23
24
|
import { filterOperatorOptions, fallbackOperatorOption, TEXT_OPERATORS, NUMBER_OPERATORS, DATE_OPERATORS, CHECKBOX_OPERATORS, operatorOption, operatorsForColumn, defaultOperatorFor, operatorLabelFor, } from "./filter-operators";
|
|
24
25
|
import { isBucketableColumn, buildBuckets, isInBucket, } from "./facet-buckets";
|
|
25
26
|
import { getColumnBaseValue, isGroupRow, toolPanelHeaderLabel, formatSummaryNumeric, getColumnAlign, getPinnedCellValue, getColumnAccessorValue, columnDefMatchesId, } from "./cell-values";
|
|
27
|
+
import { untrack } from "svelte";
|
|
26
28
|
/**
|
|
27
29
|
* Conservative fallback for the browser's max element height, used during SSR
|
|
28
30
|
* or if runtime detection fails. 8M is below every known engine cap (Firefox
|
|
@@ -145,7 +147,15 @@ function observeSizeRaf(el, cb) {
|
|
|
145
147
|
observer.disconnect();
|
|
146
148
|
};
|
|
147
149
|
}
|
|
148
|
-
export function createSvGridController(rawProps) {
|
|
150
|
+
export function createSvGridController(rawProps, domIdBase) {
|
|
151
|
+
/**
|
|
152
|
+
* Base for every DOM id this grid mints (`<base>_cell_<row>_<col>`). The view
|
|
153
|
+
* passes Svelte's per-instance `$props.id()`, which is stable across SSR and
|
|
154
|
+
* hydration; two `<SvGrid>` instances on one page used to emit identical cell
|
|
155
|
+
* ids, so `aria-activedescendant` on the second pointed into the first (#77).
|
|
156
|
+
* Falls back to the historical literal for direct controller construction.
|
|
157
|
+
*/
|
|
158
|
+
const gridDomId = domIdBase ?? "svgrid";
|
|
149
159
|
// Runtime option overrides set via the imperative api (`api.setOption(key, value)`).
|
|
150
160
|
// Every controller read of a prop goes through the `props` proxy below (and the view
|
|
151
161
|
// reads controller-resolved gates like `_features` / `editingEnabled`, not the raw
|
|
@@ -620,16 +630,13 @@ export function createSvGridController(rawProps) {
|
|
|
620
630
|
if (depth === 0)
|
|
621
631
|
return [];
|
|
622
632
|
const leafEntries = [];
|
|
623
|
-
function buildId(def, parentId, fallbackIx) {
|
|
624
|
-
return def.id ?? def.field ?? `${parentId ?? 'col'}_d_${fallbackIx}`;
|
|
625
|
-
}
|
|
626
633
|
// Leaves hidden by a collapsed/expanded group are skipped everywhere here,
|
|
627
634
|
// so group colSpan + widthPx exclude them and stay aligned with the leaves
|
|
628
635
|
// the body actually renders.
|
|
629
636
|
const hiddenLeaf = hiddenByGroupCollapse;
|
|
630
637
|
function collectLeaves(defs, parentId, depthHere) {
|
|
631
638
|
defs.forEach((def, ix) => {
|
|
632
|
-
const id =
|
|
639
|
+
const id = resolveColumnId(def, parentId, depthHere, ix);
|
|
633
640
|
if (def.columns?.length) {
|
|
634
641
|
collectLeaves(def.columns, id, depthHere + 1);
|
|
635
642
|
}
|
|
@@ -639,17 +646,22 @@ export function createSvGridController(rawProps) {
|
|
|
639
646
|
});
|
|
640
647
|
}
|
|
641
648
|
collectLeaves(userCols, undefined, 0);
|
|
642
|
-
function indexTree(defs, parentId, cursor) {
|
|
649
|
+
function indexTree(defs, parentId, cursor, depthHere) {
|
|
643
650
|
const nodes = [];
|
|
644
|
-
|
|
645
|
-
|
|
651
|
+
// Walk by array index, not by a count of pushed nodes: the `continue`
|
|
652
|
+
// below skips hidden leaves without pushing, so a counter would drift and
|
|
653
|
+
// hand the next unnamed sibling a different id than `collectLeaves` and
|
|
654
|
+
// the engine give it (#63).
|
|
655
|
+
for (let ix = 0; ix < defs.length; ix += 1) {
|
|
656
|
+
const def = defs[ix];
|
|
657
|
+
const id = resolveColumnId(def, parentId, depthHere, ix);
|
|
646
658
|
// Skip leaves the collapse state hides, so leaf indices/colSpans match
|
|
647
659
|
// `leafEntries` (and the body's rendered columns) exactly.
|
|
648
660
|
if (!def.columns?.length && hiddenLeaf[id])
|
|
649
661
|
continue;
|
|
650
662
|
const leafStart = cursor.leaf;
|
|
651
663
|
if (def.columns?.length) {
|
|
652
|
-
indexTree(def.columns, id, cursor);
|
|
664
|
+
indexTree(def.columns, id, cursor, depthHere + 1);
|
|
653
665
|
}
|
|
654
666
|
else {
|
|
655
667
|
cursor.leaf += 1;
|
|
@@ -660,7 +672,7 @@ export function createSvGridController(rawProps) {
|
|
|
660
672
|
return nodes;
|
|
661
673
|
}
|
|
662
674
|
const cursor = { leaf: 0 };
|
|
663
|
-
const topNodes = indexTree(userCols, undefined, cursor);
|
|
675
|
+
const topNodes = indexTree(userCols, undefined, cursor, 0);
|
|
664
676
|
function nodesAtDepth(nodes, currentDepth, targetDepth) {
|
|
665
677
|
if (currentDepth === targetDepth)
|
|
666
678
|
return nodes;
|
|
@@ -668,7 +680,7 @@ export function createSvGridController(rawProps) {
|
|
|
668
680
|
for (const n of nodes) {
|
|
669
681
|
if (n.def.columns?.length) {
|
|
670
682
|
const childCursor = { leaf: n.leafStart };
|
|
671
|
-
const children = indexTree(n.def.columns, n.id, childCursor);
|
|
683
|
+
const children = indexTree(n.def.columns, n.id, childCursor, currentDepth + 1);
|
|
672
684
|
out.push(...nodesAtDepth(children, currentDepth + 1, targetDepth));
|
|
673
685
|
}
|
|
674
686
|
else {
|
|
@@ -760,10 +772,13 @@ export function createSvGridController(rawProps) {
|
|
|
760
772
|
const formats = props.conditionalFormats;
|
|
761
773
|
if (!formats?.length || !formatsNeedingStats(formats))
|
|
762
774
|
return map;
|
|
763
|
-
// `
|
|
764
|
-
//
|
|
765
|
-
//
|
|
766
|
-
|
|
775
|
+
// `filtered` (default): every row that survives the filters, ignoring the
|
|
776
|
+
// page slice - so a value keeps the same colour as you page through (#61).
|
|
777
|
+
// `visible`: only the rows on screen, rescaling per page. `all`: the full
|
|
778
|
+
// unfiltered dataset, for a scale that stays put as you filter.
|
|
779
|
+
const scope = props.conditionalStatScope ?? "filtered";
|
|
780
|
+
const scanAll = scope === "all";
|
|
781
|
+
const scanRows = scope === "visible" ? allRows : allRowsBeforePagination;
|
|
767
782
|
for (const column of allColumns) {
|
|
768
783
|
const needs = formats.some((f) => formatNeedsStats(f) && (!f.columns || f.columns.includes(column.id)));
|
|
769
784
|
if (!needs)
|
|
@@ -779,7 +794,7 @@ export function createSvGridController(rawProps) {
|
|
|
779
794
|
}
|
|
780
795
|
})()
|
|
781
796
|
: (function* () {
|
|
782
|
-
for (const row of
|
|
797
|
+
for (const row of scanRows) {
|
|
783
798
|
yield fieldFn
|
|
784
799
|
? fieldFn(row.original)
|
|
785
800
|
: field
|
|
@@ -1740,7 +1755,7 @@ export function createSvGridController(rawProps) {
|
|
|
1740
1755
|
const inCols = active.colIndex >= 0 && active.colIndex < allColumns.length;
|
|
1741
1756
|
if (!inRows || !inCols)
|
|
1742
1757
|
return null;
|
|
1743
|
-
return getGridCellDomId(
|
|
1758
|
+
return getGridCellDomId(gridDomId, active.rowIndex, active.colIndex);
|
|
1744
1759
|
});
|
|
1745
1760
|
// Above this many cells (rows x columns) the summary aggregation is
|
|
1746
1761
|
// deferred one animation frame so it never blocks first paint - a
|
|
@@ -1808,7 +1823,7 @@ export function createSvGridController(rawProps) {
|
|
|
1808
1823
|
grid.setActiveCell({
|
|
1809
1824
|
rowIndex: 0,
|
|
1810
1825
|
colIndex: 0,
|
|
1811
|
-
cellId: getGridCellDomId(
|
|
1826
|
+
cellId: getGridCellDomId(gridDomId, 0, 0),
|
|
1812
1827
|
});
|
|
1813
1828
|
});
|
|
1814
1829
|
$effect(() => {
|
|
@@ -2166,13 +2181,55 @@ export function createSvGridController(rawProps) {
|
|
|
2166
2181
|
}
|
|
2167
2182
|
return Array.from(seen).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
2168
2183
|
}
|
|
2184
|
+
/**
|
|
2185
|
+
* Facet values for the open menu, SNAPSHOTTED when it opens.
|
|
2186
|
+
*
|
|
2187
|
+
* `facetValuesForColumn` walks every row and natural-sorts the distinct
|
|
2188
|
+
* values, so deriving it live re-ran that whole scan on every data change.
|
|
2189
|
+
* On a streaming grid (the trading-desk demo replaces its row array a couple
|
|
2190
|
+
* of times a second) that meant rebuilding a 10k-entry set + sort - and
|
|
2191
|
+
* re-keying the rendered value list - continuously for as long as the menu
|
|
2192
|
+
* sat open. The offered values are frozen for the life of the popover
|
|
2193
|
+
* instead, which is also what a spreadsheet's filter checklist does.
|
|
2194
|
+
* Filtering itself is unaffected: `valueFilters` matches live row values.
|
|
2195
|
+
*
|
|
2196
|
+
* The cache is a plain local, not `$state`, so writing it here can't feed
|
|
2197
|
+
* back into this derived.
|
|
2198
|
+
*/
|
|
2199
|
+
// Stable identities for the closed-menu case, so the derives below don't hand
|
|
2200
|
+
// out a fresh empty array/set on every read.
|
|
2201
|
+
const EMPTY_FACETS = [];
|
|
2202
|
+
const EMPTY_FACET_SET = new Set();
|
|
2203
|
+
let facetCache = null;
|
|
2169
2204
|
const columnMenuFacetValues = $derived.by(() => {
|
|
2170
2205
|
// The funnel popover drives via `filterMenuFor`; the column menu's Filter
|
|
2171
2206
|
// tab drives via `columnMenuFor`. Support whichever is open.
|
|
2172
2207
|
const columnId = filterMenuFor ?? columnMenuFor;
|
|
2173
2208
|
if (!columnId)
|
|
2174
|
-
return
|
|
2175
|
-
|
|
2209
|
+
return EMPTY_FACETS;
|
|
2210
|
+
// Server-provided values land asynchronously, so they stay TRACKED and
|
|
2211
|
+
// re-snapshot when they arrive. Locally derived values are read untracked
|
|
2212
|
+
// so a live data tick can't retrigger the scan.
|
|
2213
|
+
const source = props.serverFilterValues
|
|
2214
|
+
? (serverFacetValues[columnId] ?? null)
|
|
2215
|
+
: null;
|
|
2216
|
+
if (facetCache?.columnId === columnId && facetCache.source === source) {
|
|
2217
|
+
return facetCache.values;
|
|
2218
|
+
}
|
|
2219
|
+
facetCache = {
|
|
2220
|
+
columnId,
|
|
2221
|
+
source,
|
|
2222
|
+
values: untrack(() => facetValuesForColumn(columnId)),
|
|
2223
|
+
};
|
|
2224
|
+
return facetCache.values;
|
|
2225
|
+
});
|
|
2226
|
+
// Drop the snapshot when the menu closes, so reopening the SAME column
|
|
2227
|
+
// re-scans and picks up whatever the data has become meanwhile. This has to
|
|
2228
|
+
// be an effect rather than a branch in the derived above: the derived is
|
|
2229
|
+
// lazy, and nothing reads it while the menu is shut.
|
|
2230
|
+
$effect(() => {
|
|
2231
|
+
if (!(filterMenuFor ?? columnMenuFor))
|
|
2232
|
+
facetCache = null;
|
|
2176
2233
|
});
|
|
2177
2234
|
const columnMenuVisibleFacets = $derived.by(() => {
|
|
2178
2235
|
const query = columnMenuSearch.trim().toLowerCase();
|
|
@@ -2180,20 +2237,40 @@ export function createSvGridController(rawProps) {
|
|
|
2180
2237
|
return columnMenuFacetValues;
|
|
2181
2238
|
return columnMenuFacetValues.filter((value) => value.toLowerCase().includes(query));
|
|
2182
2239
|
});
|
|
2240
|
+
/** Visible facets as listbox options ((Blanks) label for the empty value). */
|
|
2241
|
+
const columnMenuFacetOptions = $derived(columnMenuVisibleFacets.map((value) => ({
|
|
2242
|
+
value,
|
|
2243
|
+
label: value === "" ? "(Blanks)" : value,
|
|
2244
|
+
})));
|
|
2245
|
+
/**
|
|
2246
|
+
* Checked facets for the open menu. An ABSENT `valueFilters` entry means
|
|
2247
|
+
* "everything checked", so that case materializes the set once here rather
|
|
2248
|
+
* than every consumer re-deriving it.
|
|
2249
|
+
*/
|
|
2250
|
+
const columnMenuSelectedFacets = $derived.by(() => {
|
|
2251
|
+
const columnId = filterMenuFor ?? columnMenuFor;
|
|
2252
|
+
if (!columnId)
|
|
2253
|
+
return EMPTY_FACET_SET;
|
|
2254
|
+
return valueFilters[columnId] ?? new Set(columnMenuFacetValues);
|
|
2255
|
+
});
|
|
2183
2256
|
// Distinct values offered in the `in` / `notIn` suggestions dropdown for the
|
|
2184
|
-
// active chip input, narrowed by whatever the user has typed.
|
|
2185
|
-
// high-cardinality column
|
|
2186
|
-
|
|
2257
|
+
// active chip input, narrowed by whatever the user has typed. Uncapped - the
|
|
2258
|
+
// dropdown windows its rows, so a high-cardinality column costs a list of
|
|
2259
|
+
// strings, not thousands of nodes.
|
|
2187
2260
|
const inSuggestValues = $derived.by(() => {
|
|
2188
2261
|
if (!inSuggestFor)
|
|
2189
|
-
return
|
|
2262
|
+
return EMPTY_FACETS;
|
|
2190
2263
|
const query = inSuggestQuery.trim().toLowerCase();
|
|
2191
2264
|
const all = facetValuesForColumn(inSuggestFor);
|
|
2192
|
-
|
|
2265
|
+
return query
|
|
2193
2266
|
? all.filter((value) => value.toLowerCase().includes(query))
|
|
2194
2267
|
: all;
|
|
2195
|
-
return matched.slice(0, IN_SUGGEST_LIMIT);
|
|
2196
2268
|
});
|
|
2269
|
+
/** `in` / `notIn` suggestions as listbox options. */
|
|
2270
|
+
const inSuggestOptions = $derived(inSuggestValues.map((value) => ({
|
|
2271
|
+
value,
|
|
2272
|
+
label: value === "" ? "(Blanks)" : value,
|
|
2273
|
+
})));
|
|
2197
2274
|
// Fire onApiReady exactly once when the grid is first ready. Wrapping in
|
|
2198
2275
|
// an effect that tracks `props.onApiReady` was racy - every parent render
|
|
2199
2276
|
// creates a new inline arrow, the effect re-fired, and any synchronous
|
|
@@ -2332,6 +2409,7 @@ export function createSvGridController(rawProps) {
|
|
|
2332
2409
|
get inSuggestQuery() { return inSuggestQuery; },
|
|
2333
2410
|
set inSuggestQuery(v) { inSuggestQuery = v; },
|
|
2334
2411
|
get inSuggestValues() { return inSuggestValues; },
|
|
2412
|
+
get inSuggestOptions() { return inSuggestOptions; },
|
|
2335
2413
|
get facetValuesForColumn() { return facetValuesForColumn; },
|
|
2336
2414
|
get chooseColumnsPos() { return chooseColumnsPos; },
|
|
2337
2415
|
set chooseColumnsPos(v) { chooseColumnsPos = v; },
|
|
@@ -2621,6 +2699,7 @@ export function createSvGridController(rawProps) {
|
|
|
2621
2699
|
get columnWindowRightSpacer() { return columnWindowRightSpacer; },
|
|
2622
2700
|
get activeCell() { return activeCell; },
|
|
2623
2701
|
get activeDescendantId() { return activeDescendantId; },
|
|
2702
|
+
get gridDomId() { return gridDomId; },
|
|
2624
2703
|
get formatSummaryNumeric() { return formatSummaryNumeric; },
|
|
2625
2704
|
get computeSummaries() { return computeSummaries; },
|
|
2626
2705
|
get SUMMARY_DEFER_CELL_LIMIT() { return SUMMARY_DEFER_CELL_LIMIT; },
|
|
@@ -2703,6 +2782,7 @@ export function createSvGridController(rawProps) {
|
|
|
2703
2782
|
get applyHistoryStep() { return applyHistoryStep; },
|
|
2704
2783
|
get updateEditingCellValue() { return updateEditingCellValue; },
|
|
2705
2784
|
get onEditorKeyDown() { return onEditorKeyDown; },
|
|
2785
|
+
get commitAndMoveByTab() { return commitAndMoveByTab; },
|
|
2706
2786
|
get focusOnMount() { return focusOnMount; },
|
|
2707
2787
|
get onHeaderSortClick() { return onHeaderSortClick; },
|
|
2708
2788
|
get onGridKeyDown() { return onGridKeyDown; },
|
|
@@ -2743,6 +2823,7 @@ export function createSvGridController(rawProps) {
|
|
|
2743
2823
|
get addFilterToken() { return addFilterToken; },
|
|
2744
2824
|
get removeFilterToken() { return removeFilterToken; },
|
|
2745
2825
|
get toggleFilterToken() { return toggleFilterToken; },
|
|
2826
|
+
get setFilterTokens() { return setFilterTokens; },
|
|
2746
2827
|
get sortColumnFromMenu() { return sortColumnFromMenu; },
|
|
2747
2828
|
get clearColumnSort() { return clearColumnSort; },
|
|
2748
2829
|
get groupByColumnFromMenu() { return groupByColumnFromMenu; },
|
|
@@ -2754,8 +2835,11 @@ export function createSvGridController(rawProps) {
|
|
|
2754
2835
|
get serverFacetLoading() { return serverFacetLoading; },
|
|
2755
2836
|
get columnMenuFacetValues() { return columnMenuFacetValues; },
|
|
2756
2837
|
get columnMenuVisibleFacets() { return columnMenuVisibleFacets; },
|
|
2838
|
+
get columnMenuFacetOptions() { return columnMenuFacetOptions; },
|
|
2839
|
+
get columnMenuSelectedFacets() { return columnMenuSelectedFacets; },
|
|
2757
2840
|
get isFacetChecked() { return isFacetChecked; },
|
|
2758
2841
|
get toggleFacetValue() { return toggleFacetValue; },
|
|
2842
|
+
get setFacetSelection() { return setFacetSelection; },
|
|
2759
2843
|
get isAllFacetsChecked() { return isAllFacetsChecked; },
|
|
2760
2844
|
get toggleAllFacets() { return toggleAllFacets; },
|
|
2761
2845
|
get clearColumnFilter() { return clearColumnFilter; },
|
|
@@ -2769,9 +2853,9 @@ export function createSvGridController(rawProps) {
|
|
|
2769
2853
|
const { showTooltipFor, hideTooltip, flushScheduledScrollSync, scheduleScrollSync, onBodyScroll } = createScrollSync(ctx);
|
|
2770
2854
|
const { onGridKeyDown, onWindowKeydown, onHeaderSortClick } = createKeyboard(ctx);
|
|
2771
2855
|
const { computeSummaries, hasRenderedColumn } = createSummaries(ctx);
|
|
2772
|
-
const { updateFilterRow, updateFilterOperator, updateFilterMenuValue, updateFilterMenuValueTo, addFilterToken, removeFilterToken, toggleFilterToken, toggleCheckboxWithKeyboard, isColumnFiltered, closeMenus, openInSuggest, closeInSuggest, openChooseColumns, openColumnMenu, openFilterMenu, openOperatorMenu, sortColumnFromMenu, clearColumnSort, groupByColumnFromMenu, clearGroupingFromMenu, isFacetChecked, toggleFacetValue, isAllFacetsChecked, toggleAllFacets, clearColumnFilter, changePage, goToPage, setPageSize, openContextMenu, closeContextMenu, contextMenuItems, saveComment, removeComment, closeCommentEditor } = createMenus(ctx);
|
|
2856
|
+
const { updateFilterRow, updateFilterOperator, updateFilterMenuValue, updateFilterMenuValueTo, addFilterToken, removeFilterToken, toggleFilterToken, toggleCheckboxWithKeyboard, isColumnFiltered, closeMenus, openInSuggest, closeInSuggest, openChooseColumns, openColumnMenu, openFilterMenu, openOperatorMenu, sortColumnFromMenu, clearColumnSort, groupByColumnFromMenu, clearGroupingFromMenu, isFacetChecked, toggleFacetValue, setFacetSelection, setFilterTokens, isAllFacetsChecked, toggleAllFacets, clearColumnFilter, changePage, goToPage, setPageSize, openContextMenu, closeContextMenu, contextMenuItems, saveComment, removeComment, closeCommentEditor } = createMenus(ctx);
|
|
2773
2857
|
const { cellConditionalFormat, computeRowClass, computeCellClass, computeCellTooltip, computeCellValidity, computeCellNote, getColumnEditorOptions, formatListCellValue, formatCellValue, formatPinnedValue, computePinnedCellClass } = createCellRender(ctx);
|
|
2774
|
-
const { isCellEditable, isCellEditableAt, getRowColumnValue, getCellDisplayValue, startEditingWithChar, startEditing, stopEditing, startFullRowEdit, setFullRowDraft, commitFullRowEdit, cancelFullRowEdit, saveEditingCell, applyHistoryStep, updateEditingCellValue, onEditorKeyDown, focusOnMount, onCellDoubleClick, pasteFromClipboard, onGridPaste } = createEditing(ctx);
|
|
2858
|
+
const { isCellEditable, isCellEditableAt, getRowColumnValue, getCellDisplayValue, startEditingWithChar, startEditing, stopEditing, startFullRowEdit, setFullRowDraft, commitFullRowEdit, cancelFullRowEdit, saveEditingCell, applyHistoryStep, updateEditingCellValue, onEditorKeyDown, commitAndMoveByTab, focusOnMount, onCellDoubleClick, pasteFromClipboard, onGridPaste } = createEditing(ctx);
|
|
2775
2859
|
const { isRowSelected, toggleRowSelectionById, toggleSelectAllRows, setActiveCell, scrollActiveCellIntoView, setSelection, extendSelection, isCellInSelectedRange, getCellRangeEdges, getSelectionRects, isInFillPreview, fillMarqueeEdges, findColumnById, onCellPointerDown, onCellPointerEnter, endDragSelection, onWindowPointerMove, onCellClick, emitCellDoubleClick } = createSelection(ctx);
|
|
2776
2860
|
const { cellPinStyle, isColumnPinned, getCurrentColumnOrder, emitColumnOrder, setColumnOrderInternal, applyColumnDrop, onColumnHeaderDragStart, onColumnHeaderDragOver, onColumnHeaderDragLeave, onColumnHeaderDrop, onColumnHeaderDragEnd, pinColumnLeft, pinColumnRight, unpinColumn, toggleColumnVisibleInPanel, moveColumnInPanel, toggleGroupInPanel, getColumnBaseWidth, getColumnWidth, startColumnResize, onColumnResizeMove, endColumnResize, measureText, autosizeColumn, autosizeAllColumns, resetColumns } = createColumns(ctx);
|
|
2777
2861
|
const { onRowDragStart, onRowDragOver, onRowDragLeave, onRowDrop, onRowsContainerDragOver, onRowsContainerDrop, onRowDragEnd, destroyRowDrag } = createRowDrag(ctx);
|