@svgrid/grid 2.1.22 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/DockNodeView.svelte +306 -0
- package/dist/DockNodeView.svelte.d.ts +7 -0
- package/dist/DockPopoutHost.svelte +17 -0
- package/dist/DockPopoutHost.svelte.d.ts +14 -0
- package/dist/FlexRender.svelte +96 -96
- package/dist/GridFooter.svelte +178 -178
- package/dist/GridMenus.svelte +83 -3
- package/dist/SvAutoComplete.svelte +5 -3
- package/dist/SvCarousel.svelte +141 -163
- package/dist/SvColorInput.svelte +187 -186
- package/dist/SvColorInput.svelte.d.ts +1 -1
- package/dist/SvComboBox.svelte +7 -3
- package/dist/SvCommand.svelte +28 -85
- package/dist/SvContextMenu.svelte +116 -116
- package/dist/SvCountryInput.svelte +1 -1
- package/dist/SvDateRangeInput.svelte +1 -1
- package/dist/SvDateTimePicker.svelte +9 -3
- package/dist/SvDateTimePicker.svelte.d.ts +3 -0
- package/dist/SvDockLayout.svelte +244 -0
- package/dist/SvDockLayout.svelte.d.ts +77 -0
- package/dist/SvDockManager.svelte +922 -0
- package/dist/SvDockManager.svelte.d.ts +106 -0
- package/dist/SvDrawer.svelte +250 -228
- package/dist/SvDrawer.svelte.d.ts +4 -0
- package/dist/SvDropDownList.svelte +85 -13
- package/dist/SvDropDownList.svelte.d.ts +3 -0
- package/dist/SvField.svelte +21 -4
- package/dist/SvField.svelte.d.ts +1 -0
- package/dist/SvForm.svelte +201 -91
- package/dist/SvForm.svelte.d.ts +15 -22
- package/dist/SvGrid.controller.svelte.d.ts +32 -1
- package/dist/SvGrid.controller.svelte.js +156 -27
- package/dist/SvGrid.css +193 -5
- package/dist/SvGrid.svelte +3131 -2786
- package/dist/SvGrid.types.d.ts +452 -1
- package/dist/SvGridBoard.svelte +2339 -2339
- package/dist/SvGridChart.svelte +1724 -1724
- package/dist/SvGridChartPanel.svelte +485 -485
- package/dist/SvGridDropdown.svelte +689 -682
- package/dist/SvGridSelect.svelte +1 -0
- package/dist/SvGroupCell.svelte +109 -109
- package/dist/SvListBox.svelte +36 -14
- package/dist/SvMaskedInput.svelte +4 -3
- package/dist/SvMaskedInput.svelte.d.ts +1 -1
- package/dist/SvMenu.svelte +124 -124
- package/dist/SvMenuList.svelte +117 -165
- package/dist/SvMenuList.svelte.d.ts +2 -13
- package/dist/SvModal.svelte +12 -29
- package/dist/SvMultiSelect.svelte +1 -0
- package/dist/SvNumberInput.svelte +131 -130
- package/dist/SvNumberInput.svelte.d.ts +1 -1
- package/dist/SvOtpInput.svelte +158 -158
- package/dist/SvPagination.svelte +18 -18
- package/dist/SvPasswordInput.svelte +3 -2
- package/dist/SvPasswordInput.svelte.d.ts +1 -1
- package/dist/SvPhoneInput.svelte +3 -2
- package/dist/SvPhoneInput.svelte.d.ts +1 -1
- package/dist/SvPopover.svelte +139 -139
- package/dist/SvRowGroupPanel.svelte +170 -170
- package/dist/SvScrollArea.svelte +61 -61
- package/dist/SvStepper.svelte +6 -9
- package/dist/SvTagsInput.svelte +3 -2
- package/dist/SvTagsInput.svelte.d.ts +1 -1
- package/dist/SvTooltip.svelte +127 -138
- package/dist/SvTour.svelte +204 -176
- package/dist/SvTree.svelte +377 -377
- package/dist/SvTreeSelect.svelte +230 -229
- package/dist/build-api.js +76 -54
- package/dist/cdn/svgrid.js +10913 -6450
- package/dist/cdn/svgrid.svelte-external.js +9628 -5481
- package/dist/chart-export.js +8 -8
- package/dist/columns.js +6 -0
- package/dist/conditional-formatting.d.ts +67 -3
- package/dist/conditional-formatting.js +124 -17
- package/dist/createCarousel.svelte.d.ts +72 -0
- package/dist/createCarousel.svelte.js +80 -0
- package/dist/createCommand.svelte.d.ts +62 -0
- package/dist/createCommand.svelte.js +109 -0
- package/dist/createForm.svelte.d.ts +62 -0
- package/dist/createForm.svelte.js +374 -0
- package/dist/createMenu.svelte.d.ts +88 -0
- package/dist/createMenu.svelte.js +153 -0
- package/dist/createOverlay.svelte.d.ts +38 -0
- package/dist/createOverlay.svelte.js +68 -0
- package/dist/createPagination.d.ts +74 -0
- package/dist/createPagination.js +71 -0
- package/dist/createPopoverSelect.svelte.js +6 -12
- package/dist/createStepper.d.ts +44 -0
- package/dist/createStepper.js +26 -0
- package/dist/createTooltip.svelte.d.ts +32 -0
- package/dist/createTooltip.svelte.js +61 -0
- package/dist/datetime/timezone.d.ts +36 -0
- package/dist/datetime/timezone.js +110 -0
- package/dist/dock-context.d.ts +52 -0
- package/dist/dock-context.js +1 -0
- package/dist/dock-manager-model.d.ts +136 -0
- package/dist/dock-manager-model.js +514 -0
- package/dist/dock-model.d.ts +105 -0
- package/dist/dock-model.js +288 -0
- package/dist/dock-popout.d.ts +30 -0
- package/dist/dock-popout.js +81 -0
- package/dist/editor-contract.d.ts +2 -0
- package/dist/filter-operators.d.ts +6 -0
- package/dist/filter-operators.js +35 -2
- package/dist/filtering/excel-filters.d.ts +18 -1
- package/dist/filtering/excel-filters.js +56 -0
- package/dist/form-field.d.ts +73 -0
- package/dist/form-field.js +15 -0
- package/dist/index.d.ts +25 -5
- package/dist/index.js +40 -4
- package/dist/list-nav.d.ts +18 -0
- package/dist/list-nav.js +30 -0
- package/dist/list-option.d.ts +2 -0
- package/dist/menu-item.d.ts +20 -0
- package/dist/menu-item.js +1 -0
- package/dist/menus.d.ts +5 -0
- package/dist/menus.js +68 -16
- package/dist/panel-resize.d.ts +25 -0
- package/dist/panel-resize.js +40 -0
- package/dist/popover.d.ts +29 -3
- package/dist/popover.js +22 -6
- package/dist/recurrence.d.ts +33 -7
- package/dist/recurrence.js +151 -13
- package/dist/row-drag.d.ts +8 -0
- package/dist/row-drag.js +11 -0
- package/dist/scheduler-ical.d.ts +30 -0
- package/dist/scheduler-ical.js +180 -0
- package/dist/scheduler-model.d.ts +269 -0
- package/dist/scheduler-model.js +602 -0
- package/dist/scheduler-view.svelte.d.ts +22 -0
- package/dist/scheduler-view.svelte.js +13 -0
- package/dist/spreadsheet.js +20 -12
- package/dist/ui-app.types.d.ts +3 -0
- package/package.json +14 -10
- package/src/DockNodeView.svelte +306 -0
- package/src/DockPopoutHost.svelte +17 -0
- package/src/FlexRender.svelte +96 -96
- package/src/GridFooter.svelte +178 -178
- package/src/GridMenus.svelte +83 -3
- package/src/SvAutoComplete.svelte +5 -3
- package/src/SvCarousel.svelte +141 -163
- package/src/SvCarousel.test.ts +68 -0
- package/src/SvColorInput.svelte +187 -186
- package/src/SvComboBox.svelte +7 -3
- package/src/SvCommand.svelte +28 -85
- package/src/SvCommand.test.ts +78 -0
- package/src/SvContextMenu.svelte +116 -116
- package/src/SvCountryInput.svelte +1 -1
- package/src/SvDateRangeInput.svelte +1 -1
- package/src/SvDateTimePicker.svelte +9 -3
- package/src/SvDockLayout.svelte +244 -0
- package/src/SvDockManager.svelte +922 -0
- package/src/SvDrawer.svelte +250 -228
- package/src/SvDropDownList.svelte +85 -13
- package/src/SvField.svelte +21 -4
- package/src/SvForm.svelte +201 -91
- package/src/SvForm.test.ts +299 -0
- package/src/SvGrid.controller.svelte.ts +3158 -3034
- package/src/SvGrid.css +193 -5
- package/src/SvGrid.svelte +3131 -2786
- package/src/SvGrid.types.ts +1489 -1027
- package/src/SvGridBoard.svelte +2339 -2339
- package/src/SvGridChart.svelte +1724 -1724
- package/src/SvGridChartPanel.svelte +485 -485
- package/src/SvGridDropdown.svelte +689 -682
- package/src/SvGridSelect.svelte +1 -0
- package/src/SvGroupCell.svelte +109 -109
- package/src/SvListBox.svelte +36 -14
- package/src/SvMaskedInput.svelte +4 -3
- package/src/SvMenu.svelte +124 -124
- package/src/SvMenu.test.ts +97 -73
- package/src/SvMenuList.svelte +117 -165
- package/src/SvModal.svelte +12 -29
- package/src/SvModal.test.ts +82 -0
- package/src/SvMultiSelect.svelte +1 -0
- package/src/SvNumberInput.svelte +131 -130
- package/src/SvOtpInput.svelte +158 -158
- package/src/SvPagination.svelte +18 -18
- package/src/SvPasswordInput.svelte +3 -2
- package/src/SvPhoneInput.svelte +3 -2
- package/src/SvPopover.svelte +139 -139
- package/src/SvRowGroupPanel.svelte +170 -170
- package/src/SvScrollArea.svelte +61 -61
- package/src/SvStepper.svelte +6 -9
- package/src/SvTagsInput.svelte +3 -2
- package/src/SvTooltip.svelte +127 -138
- package/src/SvTooltip.test.ts +73 -0
- package/src/SvTour.svelte +204 -176
- package/src/SvTree.svelte +377 -377
- package/src/SvTreeSelect.svelte +230 -229
- package/src/a11y.contract.test.ts +49 -49
- package/src/a11y.test.ts +59 -59
- package/src/a11y.ts +61 -61
- package/src/build-api.ts +870 -847
- package/src/cell-formatting.ts +169 -169
- package/src/cell-render.ts +469 -469
- package/src/chart-export.ts +201 -201
- package/src/chart.ts +2296 -2296
- package/src/collaboration.test.ts +104 -104
- package/src/collaboration.ts +167 -167
- package/src/columns.ts +5 -0
- package/src/conditional-formatting.test.ts +104 -0
- package/src/conditional-formatting.ts +176 -19
- package/src/core.performance.test.ts +30 -30
- package/src/core.ts +1111 -1111
- package/src/createAutocomplete.svelte.ts +132 -132
- package/src/createCarousel.svelte.ts +104 -0
- package/src/createCombobox.svelte.ts +179 -179
- package/src/createCommand.svelte.ts +125 -0
- package/src/createCountryInput.svelte.ts +157 -157
- package/src/createDropdownList.svelte.ts +162 -162
- package/src/createForm.svelte.ts +333 -0
- package/src/createGrid.svelte.ts +42 -42
- package/src/createGrid.test.ts +10 -10
- package/src/createGridState.svelte.ts +17 -17
- package/src/createMenu.svelte.ts +202 -0
- package/src/createOverlay.svelte.ts +101 -0
- package/src/createPagination.test.ts +65 -0
- package/src/createPagination.ts +84 -0
- package/src/createPopoverSelect.svelte.ts +206 -210
- package/src/createStepper.test.ts +62 -0
- package/src/createStepper.ts +61 -0
- package/src/createTooltip.svelte.ts +86 -0
- package/src/createTree.svelte.ts +319 -319
- package/src/datetime/timezone.test.ts +69 -0
- package/src/datetime/timezone.ts +134 -0
- package/src/dock-context.ts +47 -0
- package/src/dock-manager-model.test.ts +275 -0
- package/src/dock-manager-model.ts +593 -0
- package/src/dock-model.test.ts +163 -0
- package/src/dock-model.ts +368 -0
- package/src/dock-popout.ts +94 -0
- package/src/editing.test.ts +859 -859
- package/src/editing.ts +675 -675
- package/src/editor-contract.ts +2 -0
- 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.test.ts +59 -0
- package/src/filter-operators.ts +35 -2
- package/src/filtering/excel-filters.test.ts +86 -1
- package/src/filtering/excel-filters.ts +65 -0
- package/src/flex-render.ts +3 -3
- package/src/form-field.ts +87 -0
- package/src/index.ts +623 -469
- package/src/keyboard.test.ts +59 -59
- package/src/keyboard.ts +97 -97
- package/src/list-nav.test.ts +49 -0
- package/src/list-nav.ts +29 -0
- package/src/list-option.ts +2 -0
- package/src/menu-item.ts +21 -0
- package/src/menus.test.ts +48 -0
- package/src/menus.ts +639 -582
- package/src/merge-objects.ts +48 -48
- package/src/overlays.test.ts +90 -90
- package/src/panel-resize.ts +52 -0
- package/src/popover.bounds.test.ts +93 -0
- package/src/popover.ts +51 -7
- package/src/recurrence.test.ts +88 -1
- package/src/recurrence.ts +166 -15
- package/src/render-component.ts +28 -28
- package/src/row-drag.ts +10 -0
- package/src/scheduler-ical.test.ts +68 -0
- package/src/scheduler-ical.ts +180 -0
- package/src/scheduler-model.test.ts +546 -0
- package/src/scheduler-model.ts +853 -0
- package/src/scheduler-view.svelte.ts +33 -0
- 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 -304
- package/src/static-functions.ts +11 -11
- package/src/subscribe.ts +38 -38
- package/src/svgrid-wrapper.types.ts +501 -501
- package/src/svgrid.behavior.test.ts +706 -706
- package/src/svgrid.charting.test.ts +527 -527
- package/src/svgrid.effect-driven-filter.svelte.test.ts +116 -0
- package/src/svgrid.features.test.ts +157 -157
- 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 +159 -159
- package/src/ui-app.types.ts +3 -0
- package/src/virtual.test.ts +6 -4
- 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
|
@@ -121,6 +121,11 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
121
121
|
filterMenuPos: MenuPosition;
|
|
122
122
|
operatorMenuFor: string | null;
|
|
123
123
|
operatorMenuPos: MenuPosition;
|
|
124
|
+
inSuggestFor: string | null;
|
|
125
|
+
inSuggestPos: MenuPosition;
|
|
126
|
+
inSuggestQuery: string;
|
|
127
|
+
readonly inSuggestValues: string[];
|
|
128
|
+
readonly facetValuesForColumn: (columnId: string) => Array<string>;
|
|
124
129
|
chooseColumnsPos: MenuPosition | null;
|
|
125
130
|
contextMenuFor: ContextMenuTarget<TData> | null;
|
|
126
131
|
contextMenuPos: MenuPosition;
|
|
@@ -155,6 +160,7 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
155
160
|
internalData: readonly TData[];
|
|
156
161
|
internalColumns: ColumnDef<TFeatures, TData>[];
|
|
157
162
|
hiddenColumns: Record<string, boolean>;
|
|
163
|
+
readonly declaredHiddenColumns: Record<string, boolean>;
|
|
158
164
|
readonly toggleColumnGroup: (groupId: string) => void;
|
|
159
165
|
readonly isColumnGroupCollapsed: (groupId: string) => boolean;
|
|
160
166
|
readonly externalSortEnabled: boolean;
|
|
@@ -188,6 +194,26 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
188
194
|
collapsed: boolean;
|
|
189
195
|
}[];
|
|
190
196
|
}[];
|
|
197
|
+
readonly groupHeaderRowsWindowed: {
|
|
198
|
+
id: string;
|
|
199
|
+
cells: {
|
|
200
|
+
key: string;
|
|
201
|
+
label: string;
|
|
202
|
+
colSpan: number;
|
|
203
|
+
widthPx: number;
|
|
204
|
+
/** First leaf-column index this cell spans. */
|
|
205
|
+
firstLeafIndex: number;
|
|
206
|
+
/** True for the placeholder cells that fill the column above an
|
|
207
|
+
* early-bottoming leaf (e.g. the row-label column to the left of a
|
|
208
|
+
* multi-level value tree). They render as empty cells so the
|
|
209
|
+
* layout stays aligned without showing duplicate labels. */
|
|
210
|
+
isPlaceholder: boolean;
|
|
211
|
+
/** Set when this group cell has a collapse toggle. */
|
|
212
|
+
groupId?: string;
|
|
213
|
+
collapsible: boolean;
|
|
214
|
+
collapsed: boolean;
|
|
215
|
+
}[];
|
|
216
|
+
}[];
|
|
191
217
|
readonly pinnedOffsets: {
|
|
192
218
|
left: Record<string, number>;
|
|
193
219
|
right: Record<string, number>;
|
|
@@ -435,7 +461,7 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
435
461
|
readonly computePinnedCellClass: (rowData: TData, column: Column<TData>) => string;
|
|
436
462
|
readonly isRowSelected: (rowId: string) => boolean;
|
|
437
463
|
readonly toggleRowSelectionById: (rowId: string) => void;
|
|
438
|
-
readonly headerSelectionState: "
|
|
464
|
+
readonly headerSelectionState: "none" | "all" | "some";
|
|
439
465
|
readonly toggleSelectAllRows: () => void;
|
|
440
466
|
userHasActivatedCell: boolean;
|
|
441
467
|
readonly setActiveCell: (rowIndex: number, colIndex: number) => void;
|
|
@@ -552,6 +578,11 @@ export declare function createSvGridController<TFeatures extends TableFeatures =
|
|
|
552
578
|
readonly openColumnMenu: (event: MouseEvent, columnId: string) => void;
|
|
553
579
|
readonly openFilterMenu: (event: MouseEvent, columnId: string) => void;
|
|
554
580
|
readonly openOperatorMenu: (event: MouseEvent, columnId: string) => void;
|
|
581
|
+
readonly openInSuggest: (anchor: HTMLElement, columnId: string) => void;
|
|
582
|
+
readonly closeInSuggest: () => void;
|
|
583
|
+
readonly addFilterToken: (columnId: string, token: string) => void;
|
|
584
|
+
readonly removeFilterToken: (columnId: string, token: string) => void;
|
|
585
|
+
readonly toggleFilterToken: (columnId: string, token: string) => void;
|
|
555
586
|
readonly sortColumnFromMenu: (columnId: string, desc: boolean) => void;
|
|
556
587
|
readonly clearColumnSort: (columnId: string) => void;
|
|
557
588
|
readonly groupByColumnFromMenu: (columnId: string) => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { applyExcelFilter, normalizeForFilter, createColumnVirtualizer, createCoreRowModel, createExpandedRowModel, createFilteredRowModel, createGroupedRowModel, createSvelteVirtualizer, createSortedRowModel, createSvGrid, getGridCellDomId, rowsToChartSpec, sortFns, } from "./index";
|
|
2
2
|
import { createRowScrollScaling, resolveMaxDomHeight, } from "./virtualization/scroll-scaling";
|
|
3
3
|
import "./sv-grid-scrollbar";
|
|
4
|
-
import { computeColumnStat, formatsNeedingStats, } from "./conditional-formatting";
|
|
4
|
+
import { computeColumnStat, formatsNeedingStats, formatNeedsStats, } from "./conditional-formatting";
|
|
5
5
|
import { rawToNumber, } from "./SvGrid.helpers";
|
|
6
6
|
import { createFeatures } from "./features";
|
|
7
7
|
import { createScrollSync, } from "./scroll-sync";
|
|
@@ -41,9 +41,12 @@ const MAX_DOM_SCROLL_HEIGHT_FALLBACK = 8000000;
|
|
|
41
41
|
* matters because mobile WebKit/Blink can report a generous `offsetHeight` yet
|
|
42
42
|
* expose a smaller scrollable range - trusting the layout height alone is what
|
|
43
43
|
* stranded the last rows on phones. Using a real scroll container also folds in
|
|
44
|
-
* DPR clamping for free. Cached
|
|
44
|
+
* DPR clamping for free. Cached, but re-probed when the device pixel ratio
|
|
45
|
+
* changes (browser zoom) since the physical-pixel cap moves with it (#85).
|
|
45
46
|
*/
|
|
46
47
|
let detectedMaxDomHeight = null;
|
|
48
|
+
let detectedAtDpr = 0;
|
|
49
|
+
const currentDpr = () => (typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1);
|
|
47
50
|
/**
|
|
48
51
|
* Seed the `hiddenColumns` map from any column def marked `visible: false`.
|
|
49
52
|
* Walks groups so a hidden group hides all of its leaf columns. Keyed by the
|
|
@@ -81,7 +84,7 @@ function getMaxDomScrollHeight() {
|
|
|
81
84
|
return forced;
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
|
-
if (detectedMaxDomHeight != null)
|
|
87
|
+
if (detectedMaxDomHeight != null && detectedAtDpr === currentDpr())
|
|
85
88
|
return detectedMaxDomHeight;
|
|
86
89
|
if (typeof document === "undefined" || !document.body) {
|
|
87
90
|
return MAX_DOM_SCROLL_HEIGHT_FALLBACK;
|
|
@@ -107,6 +110,7 @@ function getMaxDomScrollHeight() {
|
|
|
107
110
|
catch {
|
|
108
111
|
detectedMaxDomHeight = MAX_DOM_SCROLL_HEIGHT_FALLBACK;
|
|
109
112
|
}
|
|
113
|
+
detectedAtDpr = currentDpr();
|
|
110
114
|
return detectedMaxDomHeight;
|
|
111
115
|
}
|
|
112
116
|
/**
|
|
@@ -258,6 +262,12 @@ export function createSvGridController(props) {
|
|
|
258
262
|
let filterMenuPos = $state({ x: 0, y: 0 });
|
|
259
263
|
let operatorMenuFor = $state(null);
|
|
260
264
|
let operatorMenuPos = $state({ x: 0, y: 0 });
|
|
265
|
+
// `in` / `notIn` value-suggestions dropdown: the column whose chip input is
|
|
266
|
+
// active, its anchor position, and the current typed query (for filtering
|
|
267
|
+
// the distinct-value list as the user types).
|
|
268
|
+
let inSuggestFor = $state(null);
|
|
269
|
+
let inSuggestPos = $state({ x: 0, y: 0 });
|
|
270
|
+
let inSuggestQuery = $state("");
|
|
261
271
|
let chooseColumnsPos = $state(null);
|
|
262
272
|
let contextMenuFor = $state(null);
|
|
263
273
|
let contextMenuPos = $state({ x: 0, y: 0 });
|
|
@@ -366,6 +376,10 @@ export function createSvGridController(props) {
|
|
|
366
376
|
let internalColumns = $state.raw(resolveCols(props.columns));
|
|
367
377
|
// svelte-ignore state_referenced_locally
|
|
368
378
|
let hiddenColumns = $state(initialHiddenColumns(props.columns));
|
|
379
|
+
// The columns declared `visible: false` in the ColumnDefs. Kept separately so
|
|
380
|
+
// applying a saved view (setState) can re-seed from these and never un-hide a
|
|
381
|
+
// column the app declared hidden (#54).
|
|
382
|
+
const declaredHiddenColumns = $derived(initialHiddenColumns(props.columns));
|
|
369
383
|
// Collapsible column groups (columnGroupShow). Meta is derived from the tree;
|
|
370
384
|
// `collapsedColumnGroups` is the live set of collapsed group ids, seeded once
|
|
371
385
|
// from each collapsible group's `openByDefault` (default: collapsed).
|
|
@@ -680,6 +694,11 @@ export function createSvGridController(props) {
|
|
|
680
694
|
const left = {};
|
|
681
695
|
let leftAcc = rowNumberWidth + selectionWidth;
|
|
682
696
|
for (const id of effectivePinning.left) {
|
|
697
|
+
// Hidden pinned columns don't render, so they must contribute neither an
|
|
698
|
+
// offset entry nor width - otherwise the next visible pinned column is
|
|
699
|
+
// pushed out by a phantom gap (#75).
|
|
700
|
+
if (hiddenColumns[id] || hiddenByGroupCollapse[id])
|
|
701
|
+
continue;
|
|
683
702
|
left[id] = leftAcc;
|
|
684
703
|
leftAcc += getColumnWidth(id);
|
|
685
704
|
}
|
|
@@ -689,6 +708,8 @@ export function createSvGridController(props) {
|
|
|
689
708
|
const id = effectivePinning.right[i];
|
|
690
709
|
if (!id)
|
|
691
710
|
continue;
|
|
711
|
+
if (hiddenColumns[id] || hiddenByGroupCollapse[id])
|
|
712
|
+
continue;
|
|
692
713
|
right[id] = rightAcc;
|
|
693
714
|
rightAcc += getColumnWidth(id);
|
|
694
715
|
}
|
|
@@ -717,23 +738,33 @@ export function createSvGridController(props) {
|
|
|
717
738
|
const formats = props.conditionalFormats;
|
|
718
739
|
if (!formats?.length || !formatsNeedingStats(formats))
|
|
719
740
|
return map;
|
|
741
|
+
// `visible` (default): the currently displayed rows (filtered + paged),
|
|
742
|
+
// so the heat map reflects what the user is looking at. `all`: the full
|
|
743
|
+
// unfiltered dataset, for a stable scale independent of filter/paging.
|
|
744
|
+
const scanAll = props.conditionalStatScope === "all";
|
|
720
745
|
for (const column of allColumns) {
|
|
721
|
-
const needs = formats.some((f) => (f
|
|
722
|
-
(!f.columns || f.columns.includes(column.id)));
|
|
746
|
+
const needs = formats.some((f) => formatNeedsStats(f) && (!f.columns || f.columns.includes(column.id)));
|
|
723
747
|
if (!needs)
|
|
724
748
|
continue;
|
|
725
749
|
const def = column.columnDef;
|
|
726
750
|
const fieldFn = def.fieldFn;
|
|
727
751
|
const field = def.field;
|
|
728
|
-
const stat = computeColumnStat(
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
: field
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
752
|
+
const stat = computeColumnStat(scanAll
|
|
753
|
+
? (function* () {
|
|
754
|
+
// Raw data objects (unfiltered); field/fieldFn only - no Row wrapper.
|
|
755
|
+
for (const obj of internalData) {
|
|
756
|
+
yield fieldFn ? fieldFn(obj) : field ? obj[field] : undefined;
|
|
757
|
+
}
|
|
758
|
+
})()
|
|
759
|
+
: (function* () {
|
|
760
|
+
for (const row of allRows) {
|
|
761
|
+
yield fieldFn
|
|
762
|
+
? fieldFn(row.original)
|
|
763
|
+
: field
|
|
764
|
+
? row.original[field]
|
|
765
|
+
: row.getCellValueByColumnId(column.id);
|
|
766
|
+
}
|
|
767
|
+
})());
|
|
737
768
|
if (stat)
|
|
738
769
|
map.set(column.id, stat);
|
|
739
770
|
}
|
|
@@ -785,7 +816,7 @@ export function createSvGridController(props) {
|
|
|
785
816
|
}
|
|
786
817
|
// A single condition is "active" if it has the value(s) it needs.
|
|
787
818
|
const condActive = (op, value, valueTo) => {
|
|
788
|
-
if (op === "isBlank")
|
|
819
|
+
if (op === "isBlank" || op === "isNotBlank")
|
|
789
820
|
return true;
|
|
790
821
|
if (op === "between")
|
|
791
822
|
return value.trim().length > 0 && (valueTo ?? "").trim().length > 0;
|
|
@@ -890,11 +921,15 @@ export function createSvGridController(props) {
|
|
|
890
921
|
const callback = props.onRowSelectionChange;
|
|
891
922
|
if (!callback)
|
|
892
923
|
return;
|
|
893
|
-
|
|
924
|
+
// Resolve selected rows by row id (not numeric index) so this is correct
|
|
925
|
+
// with a custom getRowId and after sorting (#45). Iterate the full filtered
|
|
926
|
+
// model - not the paginated slice - so selections on other pages are kept.
|
|
894
927
|
const selectedRows = [];
|
|
895
|
-
for (
|
|
896
|
-
if (
|
|
897
|
-
|
|
928
|
+
for (const row of allRowsBeforePagination) {
|
|
929
|
+
if (isGroupRow(row))
|
|
930
|
+
continue;
|
|
931
|
+
if (rowSelectionState[row.id])
|
|
932
|
+
selectedRows.push(row.original);
|
|
898
933
|
}
|
|
899
934
|
callback(rowSelectionState, selectedRows);
|
|
900
935
|
});
|
|
@@ -1389,7 +1424,7 @@ export function createSvGridController(props) {
|
|
|
1389
1424
|
return;
|
|
1390
1425
|
const menuEntries = Object.entries(filterMenuValues)
|
|
1391
1426
|
.filter(([, f]) => {
|
|
1392
|
-
if (f.operator === "isBlank")
|
|
1427
|
+
if (f.operator === "isBlank" || f.operator === "isNotBlank")
|
|
1393
1428
|
return true;
|
|
1394
1429
|
if (f.operator === "between") {
|
|
1395
1430
|
return f.value.trim().length > 0 && (f.valueTo ?? "").trim().length > 0;
|
|
@@ -1586,6 +1621,46 @@ export function createSvGridController(props) {
|
|
|
1586
1621
|
const columnWindowStart = $derived.by(() => renderedColumnItems[0]?.start ?? 0);
|
|
1587
1622
|
const columnWindowEnd = $derived.by(() => renderedColumnItems[renderedColumnItems.length - 1]?.end ?? 0);
|
|
1588
1623
|
const columnWindowRightSpacer = $derived.by(() => Math.max(totalColumnWidth - columnWindowEnd, 0));
|
|
1624
|
+
/**
|
|
1625
|
+
* `groupHeaderRows` clipped to the rendered column window. The multi-level
|
|
1626
|
+
* group-header band must virtualize in lock-step with the leaf-header row
|
|
1627
|
+
* and the body: otherwise a group cell spanning off-window leaves renders a
|
|
1628
|
+
* header over empty space (its cells were dropped by body virtualization),
|
|
1629
|
+
* so wide grouped/pivot grids show group headers with no cells beneath.
|
|
1630
|
+
*
|
|
1631
|
+
* We reuse each cell's `firstLeafIndex` + `colSpan` (leaf-index range) to
|
|
1632
|
+
* clip against the rendered leaf window, dropping fully-off-window cells and
|
|
1633
|
+
* shrinking partially-visible ones to their visible leaves. The template
|
|
1634
|
+
* frames the result with the SAME left/right spacers the leaf row uses, so
|
|
1635
|
+
* everything stays pixel-aligned. When virtualization is off this is a
|
|
1636
|
+
* pass-through.
|
|
1637
|
+
*/
|
|
1638
|
+
const groupHeaderRowsWindowed = $derived.by(() => {
|
|
1639
|
+
const base = groupHeaderRows;
|
|
1640
|
+
if (!columnVirtualizationEnabled || base.length === 0)
|
|
1641
|
+
return base;
|
|
1642
|
+
const items = renderedColumnItems;
|
|
1643
|
+
if (items.length === 0)
|
|
1644
|
+
return base;
|
|
1645
|
+
const winFirst = items[0].index;
|
|
1646
|
+
const winLast = items[items.length - 1].index; // inclusive
|
|
1647
|
+
return base.map((row) => {
|
|
1648
|
+
const cells = [];
|
|
1649
|
+
for (const cell of row.cells) {
|
|
1650
|
+
const start = cell.firstLeafIndex;
|
|
1651
|
+
const end = start + cell.colSpan; // exclusive
|
|
1652
|
+
const from = Math.max(start, winFirst);
|
|
1653
|
+
const to = Math.min(end, winLast + 1);
|
|
1654
|
+
if (to <= from)
|
|
1655
|
+
continue; // cell is entirely outside the window
|
|
1656
|
+
let widthPx = 0;
|
|
1657
|
+
for (let i = from; i < to; i += 1)
|
|
1658
|
+
widthPx += getColumnWidth(allColumns[i].id);
|
|
1659
|
+
cells.push({ ...cell, colSpan: to - from, widthPx, firstLeafIndex: from });
|
|
1660
|
+
}
|
|
1661
|
+
return { ...row, cells };
|
|
1662
|
+
});
|
|
1663
|
+
});
|
|
1589
1664
|
const activeCell = $derived.by(() => {
|
|
1590
1665
|
gridStateVersion;
|
|
1591
1666
|
return (grid.getState().activeCell ?? { rowIndex: 0, colIndex: 0, cellId: null });
|
|
@@ -1848,7 +1923,9 @@ export function createSvGridController(props) {
|
|
|
1848
1923
|
// Narrow responsive mode pans instead of scaling, so skip fit scaling.
|
|
1849
1924
|
if (!props.fitColumns || isNarrowResponsive)
|
|
1850
1925
|
return null;
|
|
1851
|
-
|
|
1926
|
+
// Exclude columns hidden by a collapsed group too (#57) - otherwise their
|
|
1927
|
+
// widths stay in the fit distribution and leave a blank gap at the edge.
|
|
1928
|
+
const cols = grid.getAllColumns().filter((c) => !hiddenColumns[c.id] && !hiddenByGroupCollapse[c.id]);
|
|
1852
1929
|
if (!cols.length)
|
|
1853
1930
|
return null;
|
|
1854
1931
|
const rowNumberWidth = showRowNumbersEffective ? rowNumberColumnWidth : 0;
|
|
@@ -1993,10 +2070,14 @@ export function createSvGridController(props) {
|
|
|
1993
2070
|
cancelled = true;
|
|
1994
2071
|
};
|
|
1995
2072
|
});
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2073
|
+
/**
|
|
2074
|
+
* Distinct values for a column, for the set-filter checklist and the
|
|
2075
|
+
* `in` / `notIn` suggestions dropdown. Server-provided values win; numeric /
|
|
2076
|
+
* date columns with many values collapse into range buckets; otherwise the
|
|
2077
|
+
* distinct raw values are collected and sorted naturally. Callable for any
|
|
2078
|
+
* column id (not just the open menu) so the filter row can drive it too.
|
|
2079
|
+
*/
|
|
2080
|
+
function facetValuesForColumn(columnId) {
|
|
2000
2081
|
if (!columnId)
|
|
2001
2082
|
return [];
|
|
2002
2083
|
// Server-provided distinct values win (fetched + cached above).
|
|
@@ -2015,6 +2096,14 @@ export function createSvGridController(props) {
|
|
|
2015
2096
|
seen.add(String(getColumnAccessorValue(rowData, column) ?? ""));
|
|
2016
2097
|
}
|
|
2017
2098
|
return Array.from(seen).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
2099
|
+
}
|
|
2100
|
+
const columnMenuFacetValues = $derived.by(() => {
|
|
2101
|
+
// The funnel popover drives via `filterMenuFor`; the column menu's Filter
|
|
2102
|
+
// tab drives via `columnMenuFor`. Support whichever is open.
|
|
2103
|
+
const columnId = filterMenuFor ?? columnMenuFor;
|
|
2104
|
+
if (!columnId)
|
|
2105
|
+
return [];
|
|
2106
|
+
return facetValuesForColumn(columnId);
|
|
2018
2107
|
});
|
|
2019
2108
|
const columnMenuVisibleFacets = $derived.by(() => {
|
|
2020
2109
|
const query = columnMenuSearch.trim().toLowerCase();
|
|
@@ -2022,6 +2111,20 @@ export function createSvGridController(props) {
|
|
|
2022
2111
|
return columnMenuFacetValues;
|
|
2023
2112
|
return columnMenuFacetValues.filter((value) => value.toLowerCase().includes(query));
|
|
2024
2113
|
});
|
|
2114
|
+
// Distinct values offered in the `in` / `notIn` suggestions dropdown for the
|
|
2115
|
+
// active chip input, narrowed by whatever the user has typed. Capped so a
|
|
2116
|
+
// high-cardinality column can't render thousands of rows into the popover.
|
|
2117
|
+
const IN_SUGGEST_LIMIT = 200;
|
|
2118
|
+
const inSuggestValues = $derived.by(() => {
|
|
2119
|
+
if (!inSuggestFor)
|
|
2120
|
+
return [];
|
|
2121
|
+
const query = inSuggestQuery.trim().toLowerCase();
|
|
2122
|
+
const all = facetValuesForColumn(inSuggestFor);
|
|
2123
|
+
const matched = query
|
|
2124
|
+
? all.filter((value) => value.toLowerCase().includes(query))
|
|
2125
|
+
: all;
|
|
2126
|
+
return matched.slice(0, IN_SUGGEST_LIMIT);
|
|
2127
|
+
});
|
|
2025
2128
|
// Fire onApiReady exactly once when the grid is first ready. Wrapping in
|
|
2026
2129
|
// an effect that tracks `props.onApiReady` was racy - every parent render
|
|
2027
2130
|
// creates a new inline arrow, the effect re-fired, and any synchronous
|
|
@@ -2151,6 +2254,14 @@ export function createSvGridController(props) {
|
|
|
2151
2254
|
set operatorMenuFor(v) { operatorMenuFor = v; },
|
|
2152
2255
|
get operatorMenuPos() { return operatorMenuPos; },
|
|
2153
2256
|
set operatorMenuPos(v) { operatorMenuPos = v; },
|
|
2257
|
+
get inSuggestFor() { return inSuggestFor; },
|
|
2258
|
+
set inSuggestFor(v) { inSuggestFor = v; },
|
|
2259
|
+
get inSuggestPos() { return inSuggestPos; },
|
|
2260
|
+
set inSuggestPos(v) { inSuggestPos = v; },
|
|
2261
|
+
get inSuggestQuery() { return inSuggestQuery; },
|
|
2262
|
+
set inSuggestQuery(v) { inSuggestQuery = v; },
|
|
2263
|
+
get inSuggestValues() { return inSuggestValues; },
|
|
2264
|
+
get facetValuesForColumn() { return facetValuesForColumn; },
|
|
2154
2265
|
get chooseColumnsPos() { return chooseColumnsPos; },
|
|
2155
2266
|
set chooseColumnsPos(v) { chooseColumnsPos = v; },
|
|
2156
2267
|
get contextMenuFor() { return contextMenuFor; },
|
|
@@ -2183,6 +2294,7 @@ export function createSvGridController(props) {
|
|
|
2183
2294
|
set internalColumns(v) { internalColumns = v; },
|
|
2184
2295
|
get hiddenColumns() { return hiddenColumns; },
|
|
2185
2296
|
set hiddenColumns(v) { hiddenColumns = v; },
|
|
2297
|
+
get declaredHiddenColumns() { return declaredHiddenColumns; },
|
|
2186
2298
|
get toggleColumnGroup() { return toggleColumnGroup; },
|
|
2187
2299
|
get isColumnGroupCollapsed() { return isColumnGroupCollapsed; },
|
|
2188
2300
|
get externalSortEnabled() { return externalSortEnabled; },
|
|
@@ -2197,6 +2309,7 @@ export function createSvGridController(props) {
|
|
|
2197
2309
|
get allColumns() { return allColumns; },
|
|
2198
2310
|
get headerGroups() { return headerGroups; },
|
|
2199
2311
|
get groupHeaderRows() { return groupHeaderRows; },
|
|
2312
|
+
get groupHeaderRowsWindowed() { return groupHeaderRowsWindowed; },
|
|
2200
2313
|
get pinnedOffsets() { return pinnedOffsets; },
|
|
2201
2314
|
get cellPinStyle() { return cellPinStyle; },
|
|
2202
2315
|
get isColumnPinned() { return isColumnPinned; },
|
|
@@ -2545,6 +2658,11 @@ export function createSvGridController(props) {
|
|
|
2545
2658
|
get openColumnMenu() { return openColumnMenu; },
|
|
2546
2659
|
get openFilterMenu() { return openFilterMenu; },
|
|
2547
2660
|
get openOperatorMenu() { return openOperatorMenu; },
|
|
2661
|
+
get openInSuggest() { return openInSuggest; },
|
|
2662
|
+
get closeInSuggest() { return closeInSuggest; },
|
|
2663
|
+
get addFilterToken() { return addFilterToken; },
|
|
2664
|
+
get removeFilterToken() { return removeFilterToken; },
|
|
2665
|
+
get toggleFilterToken() { return toggleFilterToken; },
|
|
2548
2666
|
get sortColumnFromMenu() { return sortColumnFromMenu; },
|
|
2549
2667
|
get clearColumnSort() { return clearColumnSort; },
|
|
2550
2668
|
get groupByColumnFromMenu() { return groupByColumnFromMenu; },
|
|
@@ -2571,12 +2689,12 @@ export function createSvGridController(props) {
|
|
|
2571
2689
|
const { showTooltipFor, hideTooltip, flushScheduledScrollSync, scheduleScrollSync, onBodyScroll } = createScrollSync(ctx);
|
|
2572
2690
|
const { onGridKeyDown, onWindowKeydown, onHeaderSortClick } = createKeyboard(ctx);
|
|
2573
2691
|
const { computeSummaries, hasRenderedColumn } = createSummaries(ctx);
|
|
2574
|
-
const { updateFilterRow, updateFilterOperator, updateFilterMenuValue, updateFilterMenuValueTo, toggleCheckboxWithKeyboard, isColumnFiltered, closeMenus, openChooseColumns, openColumnMenu, openFilterMenu, openOperatorMenu, sortColumnFromMenu, clearColumnSort, groupByColumnFromMenu, clearGroupingFromMenu, isFacetChecked, toggleFacetValue, isAllFacetsChecked, toggleAllFacets, clearColumnFilter, changePage, goToPage, setPageSize, openContextMenu, closeContextMenu, contextMenuItems, saveComment, removeComment, closeCommentEditor } = createMenus(ctx);
|
|
2692
|
+
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);
|
|
2575
2693
|
const { cellConditionalFormat, computeRowClass, computeCellClass, computeCellTooltip, computeCellValidity, computeCellNote, getColumnEditorOptions, formatListCellValue, formatCellValue, formatPinnedValue, computePinnedCellClass } = createCellRender(ctx);
|
|
2576
2694
|
const { isCellEditable, isCellEditableAt, getRowColumnValue, getCellDisplayValue, startEditingWithChar, startEditing, stopEditing, startFullRowEdit, setFullRowDraft, commitFullRowEdit, cancelFullRowEdit, saveEditingCell, applyHistoryStep, updateEditingCellValue, onEditorKeyDown, focusOnMount, onCellDoubleClick, pasteFromClipboard, onGridPaste } = createEditing(ctx);
|
|
2577
2695
|
const { isRowSelected, toggleRowSelectionById, toggleSelectAllRows, setActiveCell, scrollActiveCellIntoView, setSelection, extendSelection, isCellInSelectedRange, getCellRangeEdges, getSelectionRects, isInFillPreview, fillMarqueeEdges, findColumnById, onCellPointerDown, onCellPointerEnter, endDragSelection, onWindowPointerMove, onCellClick, emitCellDoubleClick } = createSelection(ctx);
|
|
2578
2696
|
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);
|
|
2579
|
-
const { onRowDragStart, onRowDragOver, onRowDragLeave, onRowDrop, onRowsContainerDragOver, onRowsContainerDrop, onRowDragEnd } = createRowDrag(ctx);
|
|
2697
|
+
const { onRowDragStart, onRowDragOver, onRowDragLeave, onRowDrop, onRowsContainerDragOver, onRowsContainerDrop, onRowDragEnd, destroyRowDrag } = createRowDrag(ctx);
|
|
2580
2698
|
const { register: registerAlignedGrid, broadcastScroll: broadcastAlignedScroll, broadcastWidths: broadcastAlignedWidths } = createAlignedGrids(ctx);
|
|
2581
2699
|
const { buildApi } = createGridApi(ctx);
|
|
2582
2700
|
const { readCellRaw, writeCellRaw, applyFillPattern, clearSelectedCellValues, startFillDrag, onFillPointerMove, onFillPointerUp, toggleBooleanCell, copySelectionToClipboard, clearSelectedCells, cutSelectionToClipboard } = createClipboard(ctx);
|
|
@@ -2593,5 +2711,16 @@ export function createSvGridController(props) {
|
|
|
2593
2711
|
void columnWidths;
|
|
2594
2712
|
broadcastAlignedWidths();
|
|
2595
2713
|
});
|
|
2714
|
+
// Unmount teardown. Reads no reactive state, so the cleanup runs once on
|
|
2715
|
+
// destroy - tearing down an in-flight column resize (its document pointer
|
|
2716
|
+
// listeners, #58), a pending tooltip timer (#64), and any managed row drag
|
|
2717
|
+
// this grid still owns (#68). Each of these is a no-op when idle.
|
|
2718
|
+
$effect(() => {
|
|
2719
|
+
return () => {
|
|
2720
|
+
endColumnResize();
|
|
2721
|
+
hideTooltip();
|
|
2722
|
+
destroyRowDrag();
|
|
2723
|
+
};
|
|
2724
|
+
});
|
|
2596
2725
|
return ctx;
|
|
2597
2726
|
}
|
package/dist/SvGrid.css
CHANGED
|
@@ -485,13 +485,28 @@
|
|
|
485
485
|
justify-content: flex-end;
|
|
486
486
|
}
|
|
487
487
|
/* The custom vertical scrollbar overlays the right 16px of the viewport
|
|
488
|
-
(absolute, z-index 40)
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
.
|
|
492
|
-
|
|
488
|
+
(absolute, z-index 40) and does NOT shrink the scroll container's
|
|
489
|
+
clientWidth. Two cases keep the last column clear of it:
|
|
490
|
+
|
|
491
|
+
1. No horizontal overflow (content fits, nothing to scroll): nudge the last
|
|
492
|
+
column's right-aligned content in by the scrollbar width so numbers
|
|
493
|
+
aren't hidden underneath it. Left/center content already clears it.
|
|
494
|
+
2. Horizontal overflow: there's nothing to nudge (you scroll to the end and
|
|
495
|
+
the last 16px sit under the bar with no room left). Instead reserve a
|
|
496
|
+
trailing gutter on the scroll container so you can scroll the last column
|
|
497
|
+
fully out from under the overlay. See `.sv-grid-has-vscroll.sv-grid-has-hscroll`. */
|
|
498
|
+
.sv-grid-has-vscroll:not(.sv-grid-has-hscroll) .sv-grid-table tr > :last-child.sv-grid-cell[data-align="right"],
|
|
499
|
+
.sv-grid-has-vscroll:not(.sv-grid-has-hscroll) .sv-grid-table tr > :last-child.sv-grid-column[data-align="right"] {
|
|
493
500
|
padding-right: calc(var(--sg-cell-px, 7px) + 16px);
|
|
494
501
|
}
|
|
502
|
+
/* Case 2: reserve the overlay scrollbar's width as end-of-scroll space so the
|
|
503
|
+
final column can be scrolled clear of the vertical scrollbar. Modern browsers
|
|
504
|
+
include a scroll container's inline-end padding in its scrollable overflow;
|
|
505
|
+
the custom scrollbars are siblings of this container, so their layout is
|
|
506
|
+
unaffected. */
|
|
507
|
+
.sv-grid-container.sv-grid-has-vscroll.sv-grid-has-hscroll {
|
|
508
|
+
padding-right: 16px;
|
|
509
|
+
}
|
|
495
510
|
.sv-grid-column[data-align="center"] .sv-grid-header-sort {
|
|
496
511
|
justify-content: center;
|
|
497
512
|
}
|
|
@@ -857,6 +872,11 @@
|
|
|
857
872
|
flex-direction: row;
|
|
858
873
|
align-items: center;
|
|
859
874
|
gap: 4px;
|
|
875
|
+
box-sizing: border-box;
|
|
876
|
+
/* Inset the operator button + input from the cell edges so the filter row
|
|
877
|
+
lines up with the header label / body text (same --sg-cell-px gutter) and
|
|
878
|
+
isn't cramped against the top/side borders. */
|
|
879
|
+
padding: 5px var(--sg-filter-cell-px, var(--sg-cell-px, 7px));
|
|
860
880
|
}
|
|
861
881
|
|
|
862
882
|
.sv-grid-filter-operator {
|
|
@@ -871,6 +891,100 @@
|
|
|
871
891
|
box-sizing: border-box;
|
|
872
892
|
}
|
|
873
893
|
|
|
894
|
+
/* Invalid regex pattern: flag the input so the user knows the half-typed
|
|
895
|
+
pattern isn't being applied (it matches nothing until it compiles). */
|
|
896
|
+
.sv-grid-filter-value.sv-grid-filter-value-invalid,
|
|
897
|
+
.sv-grid-tp-filter-input.sv-grid-filter-value-invalid {
|
|
898
|
+
border-color: var(--sg-danger, #e5484d) !important;
|
|
899
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--sg-danger, #e5484d) 45%, transparent);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/* In / Not-in chip (token) input: chips + a flex-growing text box share one
|
|
903
|
+
bordered control that reads like a single field. */
|
|
904
|
+
.sv-grid-filter-chips {
|
|
905
|
+
flex: 3 1 0;
|
|
906
|
+
min-width: 0;
|
|
907
|
+
box-sizing: border-box;
|
|
908
|
+
display: flex;
|
|
909
|
+
flex-wrap: nowrap;
|
|
910
|
+
align-items: center;
|
|
911
|
+
gap: 3px;
|
|
912
|
+
padding: 2px 4px;
|
|
913
|
+
border: 1px solid var(--sg-input-border, #8794a8);
|
|
914
|
+
border-radius: 4px;
|
|
915
|
+
background: var(--sg-input-bg, #fff);
|
|
916
|
+
overflow: hidden;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/* A few chips stay visible; the rest collapse into a non-wrapping "+N" pill
|
|
920
|
+
that opens the value dropdown (select / unselect). */
|
|
921
|
+
.sv-grid-filter-chip .sv-grid-filter-chip-label {
|
|
922
|
+
max-width: 84px;
|
|
923
|
+
}
|
|
924
|
+
.sv-grid-filter-chip-more {
|
|
925
|
+
flex: none;
|
|
926
|
+
border: 0;
|
|
927
|
+
cursor: pointer;
|
|
928
|
+
font: inherit;
|
|
929
|
+
font-size: 11px;
|
|
930
|
+
line-height: 16px;
|
|
931
|
+
color: var(--sg-text, inherit);
|
|
932
|
+
}
|
|
933
|
+
.sv-grid-filter-chip-more:hover {
|
|
934
|
+
background: color-mix(in srgb, var(--sg-accent, #0b63f3) 26%, transparent);
|
|
935
|
+
}
|
|
936
|
+
.sv-grid-filter-chips:focus-within {
|
|
937
|
+
border-color: var(--sg-accent, #0b63f3);
|
|
938
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--sg-accent, #0b63f3) 45%, transparent);
|
|
939
|
+
}
|
|
940
|
+
.sv-grid-filter-chip {
|
|
941
|
+
display: inline-flex;
|
|
942
|
+
align-items: center;
|
|
943
|
+
gap: 2px;
|
|
944
|
+
max-width: 120px;
|
|
945
|
+
padding: 0 2px 0 6px;
|
|
946
|
+
border-radius: 3px;
|
|
947
|
+
font-size: 11px;
|
|
948
|
+
line-height: 16px;
|
|
949
|
+
background: color-mix(in srgb, var(--sg-accent, #0b63f3) 16%, transparent);
|
|
950
|
+
color: var(--sg-text, inherit);
|
|
951
|
+
}
|
|
952
|
+
.sv-grid-filter-chip-label {
|
|
953
|
+
overflow: hidden;
|
|
954
|
+
text-overflow: ellipsis;
|
|
955
|
+
white-space: nowrap;
|
|
956
|
+
}
|
|
957
|
+
.sv-grid-filter-chip-x {
|
|
958
|
+
flex: none;
|
|
959
|
+
display: inline-flex;
|
|
960
|
+
align-items: center;
|
|
961
|
+
justify-content: center;
|
|
962
|
+
width: 14px;
|
|
963
|
+
height: 14px;
|
|
964
|
+
padding: 0;
|
|
965
|
+
border: 0;
|
|
966
|
+
border-radius: 3px;
|
|
967
|
+
background: transparent;
|
|
968
|
+
color: inherit;
|
|
969
|
+
font-size: 13px;
|
|
970
|
+
line-height: 1;
|
|
971
|
+
cursor: pointer;
|
|
972
|
+
opacity: 0.7;
|
|
973
|
+
}
|
|
974
|
+
.sv-grid-filter-chip-x:hover {
|
|
975
|
+
opacity: 1;
|
|
976
|
+
background: color-mix(in srgb, var(--sg-accent, #0b63f3) 28%, transparent);
|
|
977
|
+
}
|
|
978
|
+
.sv-grid-filter-chips .sv-grid-filter-chip-input {
|
|
979
|
+
flex: 1 1 14px;
|
|
980
|
+
min-width: 14px;
|
|
981
|
+
border: 0 !important;
|
|
982
|
+
padding: 0 2px;
|
|
983
|
+
background: transparent;
|
|
984
|
+
box-shadow: none !important;
|
|
985
|
+
outline: none;
|
|
986
|
+
}
|
|
987
|
+
|
|
874
988
|
/* Brief glow used when the user clicks the funnel icon while the grid
|
|
875
989
|
is in row-filter mode - draws attention to where the input is so
|
|
876
990
|
the click isn't a no-op. */
|
|
@@ -1220,6 +1334,22 @@ select.sv-grid-fr-editor {
|
|
|
1220
1334
|
width: 100%;
|
|
1221
1335
|
font-size: 0.8125rem;
|
|
1222
1336
|
}
|
|
1337
|
+
/* The global "Filter all rows" search: a labelled input bar above the grid. Ships
|
|
1338
|
+
styled so it never renders as a bare, unpositioned text label + input. */
|
|
1339
|
+
.sv-grid-global-filter {
|
|
1340
|
+
display: inline-flex;
|
|
1341
|
+
align-items: center;
|
|
1342
|
+
gap: 8px;
|
|
1343
|
+
margin-bottom: 8px;
|
|
1344
|
+
font-size: 0.8125rem;
|
|
1345
|
+
font-weight: 550;
|
|
1346
|
+
color: var(--sg-muted, #64748b);
|
|
1347
|
+
}
|
|
1348
|
+
.sv-grid-global-filter input {
|
|
1349
|
+
height: 30px;
|
|
1350
|
+
min-width: 220px;
|
|
1351
|
+
font-size: 0.8125rem;
|
|
1352
|
+
}
|
|
1223
1353
|
.sv-grid-column-filter::placeholder,
|
|
1224
1354
|
.sv-grid-filter-value::placeholder,
|
|
1225
1355
|
.sv-grid-menu-search::placeholder,
|
|
@@ -1752,6 +1882,38 @@ select.sv-grid-fr-editor {
|
|
|
1752
1882
|
background: var(--sg-row-hover-bg, #eef2f8);
|
|
1753
1883
|
}
|
|
1754
1884
|
|
|
1885
|
+
/* In / Not-in value-suggestions dropdown (anchored under the chip input).
|
|
1886
|
+
Defined AFTER .sv-grid-menu so its tighter sizing wins - the element
|
|
1887
|
+
carries both classes. Compact rows keep a long value list scannable. */
|
|
1888
|
+
.sv-grid-menu.sv-grid-in-suggest {
|
|
1889
|
+
min-width: 140px;
|
|
1890
|
+
max-width: 260px;
|
|
1891
|
+
max-height: 220px;
|
|
1892
|
+
overflow-y: auto;
|
|
1893
|
+
font-size: 12px;
|
|
1894
|
+
}
|
|
1895
|
+
.sv-grid-in-suggest-item {
|
|
1896
|
+
gap: 6px;
|
|
1897
|
+
padding: 3px 8px;
|
|
1898
|
+
border-radius: 4px;
|
|
1899
|
+
line-height: 1.4;
|
|
1900
|
+
}
|
|
1901
|
+
.sv-grid-in-suggest-item[aria-selected="true"] {
|
|
1902
|
+
color: var(--sg-accent, #0b63f3);
|
|
1903
|
+
font-weight: 600;
|
|
1904
|
+
}
|
|
1905
|
+
.sv-grid-in-suggest-check {
|
|
1906
|
+
flex: none;
|
|
1907
|
+
width: 12px;
|
|
1908
|
+
text-align: center;
|
|
1909
|
+
color: var(--sg-accent, #0b63f3);
|
|
1910
|
+
}
|
|
1911
|
+
.sv-grid-in-suggest-label {
|
|
1912
|
+
overflow: hidden;
|
|
1913
|
+
text-overflow: ellipsis;
|
|
1914
|
+
white-space: nowrap;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1755
1917
|
.sv-grid-menu-item[aria-checked="true"] {
|
|
1756
1918
|
background: var(--sg-selection-bg, #eaf2ff);
|
|
1757
1919
|
color: var(--sg-accent, #0b63f3);
|
|
@@ -2376,6 +2538,32 @@ select.sv-grid-fr-editor {
|
|
|
2376
2538
|
color: var(--sg-fg, #101828);
|
|
2377
2539
|
}
|
|
2378
2540
|
|
|
2541
|
+
/* Placeholder shown when `scheduler` is set but the enterprise renderer that
|
|
2542
|
+
powers the calendar view has not been registered. */
|
|
2543
|
+
.sv-grid-scheduler-upsell {
|
|
2544
|
+
display: flex;
|
|
2545
|
+
flex-direction: column;
|
|
2546
|
+
gap: 6px;
|
|
2547
|
+
align-items: flex-start;
|
|
2548
|
+
justify-content: center;
|
|
2549
|
+
height: 100%;
|
|
2550
|
+
padding: 24px;
|
|
2551
|
+
text-align: left;
|
|
2552
|
+
border: 1px dashed var(--sg-border, #e4e7ec);
|
|
2553
|
+
border-radius: var(--sg-radius, 8px);
|
|
2554
|
+
background: color-mix(in srgb, var(--sg-fg, #1f2937) 5%, transparent);
|
|
2555
|
+
color: color-mix(in srgb, var(--sg-fg, #101828) 70%, transparent);
|
|
2556
|
+
}
|
|
2557
|
+
.sv-grid-scheduler-upsell strong { font-size: 0.95rem; }
|
|
2558
|
+
.sv-grid-scheduler-upsell p { margin: 0; font-size: 0.85rem; max-width: 42ch; }
|
|
2559
|
+
.sv-grid-scheduler-upsell code {
|
|
2560
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
2561
|
+
font-size: 0.82em;
|
|
2562
|
+
padding: 1px 4px;
|
|
2563
|
+
border-radius: 4px;
|
|
2564
|
+
background: color-mix(in srgb, var(--sg-fg, #101828) 8%, transparent);
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2379
2567
|
/* ===================================================================
|
|
2380
2568
|
Integrated chart panel (the `charting` prop)
|
|
2381
2569
|
=================================================================== */
|