@geotab/zenith 3.16.0-beta.2 → 3.16.0-beta.3

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.
Files changed (59) hide show
  1. package/README.md +15 -12
  2. package/dist/absolute/absolute.js +1 -1
  3. package/dist/chart/plugins/linePlugin/getInterpolatedValue.d.ts +2 -2
  4. package/dist/chart/plugins/linePlugin/getInterpolatedValue.js +3 -2
  5. package/dist/chart/plugins/linePlugin/linePlugin.js +2 -1
  6. package/dist/chart/utils/getFormattedLabel.js +5 -1
  7. package/dist/checkbox/checkbox.d.ts +2 -1
  8. package/dist/checkbox/checkbox.js +2 -2
  9. package/dist/checkboxListWithAction/checkboxListWithAction.js +1 -0
  10. package/dist/commonHelpers/hooks/useTrapFocus.d.ts +0 -9
  11. package/dist/commonHelpers/hooks/useTrapFocus.js +14 -66
  12. package/dist/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +2 -1
  13. package/dist/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
  14. package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +4 -2
  15. package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +10 -1
  16. package/dist/dataGrid/row/row.js +3 -2
  17. package/dist/dataGrid/withSelectableRows/withSelectableRows.js +73 -12
  18. package/dist/index.css +1 -1
  19. package/dist/table/selectable/interfaces.d.ts +9 -13
  20. package/dist/table/selectable/useDragSelection.d.ts +10 -0
  21. package/dist/table/selectable/useDragSelection.js +139 -0
  22. package/dist/table/selectable/useSelectableRows.d.ts +2 -2
  23. package/dist/table/selectable/useSelectableRows.js +59 -49
  24. package/dist/table/selectable/utils/calculateSelectionState.js +0 -35
  25. package/dist/table/selectable/utils/getDragSelectionRows.d.ts +15 -0
  26. package/dist/table/selectable/utils/getDragSelectionRows.js +28 -0
  27. package/dist/table/selectable/utils/getRangeIds.d.ts +2 -0
  28. package/dist/table/selectable/utils/getRangeIds.js +21 -0
  29. package/dist/table/selectable/utils/isRowChecked.js +1 -12
  30. package/dist/table/table.js +1 -1
  31. package/esm/absolute/absolute.js +1 -1
  32. package/esm/chart/plugins/linePlugin/getInterpolatedValue.d.ts +2 -2
  33. package/esm/chart/plugins/linePlugin/getInterpolatedValue.js +3 -2
  34. package/esm/chart/plugins/linePlugin/linePlugin.js +2 -1
  35. package/esm/chart/utils/getFormattedLabel.js +5 -1
  36. package/esm/checkbox/checkbox.d.ts +2 -1
  37. package/esm/checkbox/checkbox.js +2 -2
  38. package/esm/checkboxListWithAction/checkboxListWithAction.js +1 -0
  39. package/esm/commonHelpers/hooks/useTrapFocus.d.ts +0 -9
  40. package/esm/commonHelpers/hooks/useTrapFocus.js +15 -67
  41. package/esm/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +2 -1
  42. package/esm/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
  43. package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +4 -2
  44. package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +10 -1
  45. package/esm/dataGrid/row/row.js +3 -2
  46. package/esm/dataGrid/withSelectableRows/withSelectableRows.js +73 -12
  47. package/esm/table/selectable/interfaces.d.ts +9 -13
  48. package/esm/table/selectable/useDragSelection.d.ts +10 -0
  49. package/esm/table/selectable/useDragSelection.js +135 -0
  50. package/esm/table/selectable/useSelectableRows.d.ts +2 -2
  51. package/esm/table/selectable/useSelectableRows.js +59 -49
  52. package/esm/table/selectable/utils/calculateSelectionState.js +0 -35
  53. package/esm/table/selectable/utils/getDragSelectionRows.d.ts +15 -0
  54. package/esm/table/selectable/utils/getDragSelectionRows.js +24 -0
  55. package/esm/table/selectable/utils/getRangeIds.d.ts +2 -0
  56. package/esm/table/selectable/utils/getRangeIds.js +17 -0
  57. package/esm/table/selectable/utils/isRowChecked.js +1 -12
  58. package/esm/table/table.js +1 -1
  59. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDragSelection = void 0;
4
+ const react_1 = require("react");
5
+ const zen_1 = require("../../utils/zen");
6
+ const getRangeIds_1 = require("./utils/getRangeIds");
7
+ const DRAG_CLASS = "zen-not-selectable";
8
+ /**
9
+ * @param rows every checkbox row in render order, expanded nested rows included, so ranges can
10
+ * span nesting levels.
11
+ */
12
+ const useDragSelection = (rows, gridRef, onBatchSelect, getBaseSelection, isSelectable, isEnabled) => {
13
+ const rowsRef = (0, react_1.useRef)(rows);
14
+ rowsRef.current = rows;
15
+ const getBaseSelectionRef = (0, react_1.useRef)(getBaseSelection);
16
+ getBaseSelectionRef.current = getBaseSelection;
17
+ const onBatchSelectRef = (0, react_1.useRef)(onBatchSelect);
18
+ onBatchSelectRef.current = onBatchSelect;
19
+ const isSelectableRef = (0, react_1.useRef)(isSelectable);
20
+ isSelectableRef.current = isSelectable;
21
+ const isEnabledRef = (0, react_1.useRef)(isEnabled);
22
+ isEnabledRef.current = isEnabled;
23
+ const anchorIdRef = (0, react_1.useRef)(null);
24
+ const anchorSelectRef = (0, react_1.useRef)(true);
25
+ const baseSelectedRef = (0, react_1.useRef)(new Set());
26
+ const isDraggingRef = (0, react_1.useRef)(false);
27
+ const movedRef = (0, react_1.useRef)(false);
28
+ const lastResultKeyRef = (0, react_1.useRef)("");
29
+ const lastPointRef = (0, react_1.useRef)(null);
30
+ const suppressNextChangeRef = (0, react_1.useRef)(false);
31
+ const attachedGridElementRef = (0, react_1.useRef)(null);
32
+ const emitRange = (0, react_1.useCallback)((currentId) => {
33
+ const anchorId = anchorIdRef.current;
34
+ if (anchorId === null) {
35
+ return;
36
+ }
37
+ const range = (0, getRangeIds_1.getRangeIds)(rowsRef.current, anchorId, currentId, isSelectableRef.current);
38
+ if (range.length === 0) {
39
+ return;
40
+ }
41
+ const select = anchorSelectRef.current;
42
+ const key = `${select}|${range.join(",")}`;
43
+ if (key === lastResultKeyRef.current) {
44
+ return;
45
+ }
46
+ lastResultKeyRef.current = key;
47
+ onBatchSelectRef.current(range, select, baseSelectedRef.current);
48
+ }, []);
49
+ const extend = (0, react_1.useCallback)((x, y) => {
50
+ var _a, _b;
51
+ lastPointRef.current = { x, y };
52
+ const row = (_b = (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.elementFromPoint(x, y)) === null || _b === void 0 ? void 0 : _b.closest("[data-row-id]");
53
+ const currentId = row === null || row === void 0 ? void 0 : row.getAttribute("data-row-id");
54
+ if (!currentId) {
55
+ return;
56
+ }
57
+ if (currentId !== anchorIdRef.current) {
58
+ movedRef.current = true;
59
+ }
60
+ if (!movedRef.current) {
61
+ return;
62
+ }
63
+ emitRange(currentId);
64
+ }, [emitRange]);
65
+ const onMouseMove = (0, react_1.useCallback)((e) => {
66
+ extend(e.clientX, e.clientY);
67
+ }, [extend]);
68
+ const onScroll = (0, react_1.useCallback)(() => {
69
+ const point = lastPointRef.current;
70
+ if (point) {
71
+ extend(point.x, point.y);
72
+ }
73
+ }, [extend]);
74
+ const endDrag = (0, react_1.useCallback)(() => {
75
+ var _a, _b, _c, _d;
76
+ if (!isDraggingRef.current) {
77
+ return;
78
+ }
79
+ isDraggingRef.current = false;
80
+ if (movedRef.current) {
81
+ suppressNextChangeRef.current = true;
82
+ }
83
+ (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.removeEventListener("mousemove", onMouseMove);
84
+ (_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.removeEventListener("mouseup", endDrag);
85
+ (_c = attachedGridElementRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener("scroll", onScroll);
86
+ (_d = attachedGridElementRef.current) === null || _d === void 0 ? void 0 : _d.classList.remove(DRAG_CLASS);
87
+ attachedGridElementRef.current = null;
88
+ }, [onMouseMove, onScroll]); // eslint-disable-line react-hooks/exhaustive-deps
89
+ const onCheckboxMouseDown = (0, react_1.useCallback)((id, checked, e) => {
90
+ var _a, _b, _c, _d, _e;
91
+ // Right-click between drag-end and the trailing click must not clear suppression.
92
+ if (e.button === 0) {
93
+ suppressNextChangeRef.current = false;
94
+ }
95
+ if (!isEnabledRef.current || e.button !== 0) {
96
+ return;
97
+ }
98
+ if (e.shiftKey && anchorIdRef.current !== null) {
99
+ e.preventDefault();
100
+ const anchorId = anchorIdRef.current;
101
+ const anchorInList = rowsRef.current.some(row => row.id === anchorId);
102
+ if (!anchorInList) {
103
+ // The anchor is no longer rendered (e.g. its parent was collapsed, or the list was
104
+ // re-filtered/paginated since). Drop the stale anchor and let the target row's own
105
+ // onChange fire normally, rather than swallowing it as a silent no-op.
106
+ anchorIdRef.current = null;
107
+ return;
108
+ }
109
+ // Gmail-style: every shift-click re-applies the range to the selection captured when
110
+ // the anchor was clicked, so moving the target closer to the anchor deselects the rows
111
+ // that dropped out of the range. Shift-clicking the anchor itself collapses the range
112
+ // to nothing, restoring that captured selection — the anchor included.
113
+ const range = id === anchorId ? [] : (0, getRangeIds_1.getRangeIds)(rowsRef.current, anchorId, id, isSelectableRef.current);
114
+ // Suppress even when the range is empty to prevent the anchor from double-toggling
115
+ // on a same-row shift-click.
116
+ suppressNextChangeRef.current = true;
117
+ onBatchSelectRef.current(range, anchorSelectRef.current, baseSelectedRef.current);
118
+ return;
119
+ }
120
+ anchorIdRef.current = id;
121
+ anchorSelectRef.current = !checked;
122
+ baseSelectedRef.current = getBaseSelectionRef.current();
123
+ isDraggingRef.current = true;
124
+ movedRef.current = false;
125
+ lastResultKeyRef.current = "";
126
+ lastPointRef.current = { x: e.clientX, y: e.clientY };
127
+ attachedGridElementRef.current = (_a = gridRef === null || gridRef === void 0 ? void 0 : gridRef.current) !== null && _a !== void 0 ? _a : null;
128
+ (_b = attachedGridElementRef.current) === null || _b === void 0 ? void 0 : _b.classList.add(DRAG_CLASS);
129
+ (_c = zen_1.zen.document) === null || _c === void 0 ? void 0 : _c.addEventListener("mousemove", onMouseMove);
130
+ (_d = zen_1.zen.document) === null || _d === void 0 ? void 0 : _d.addEventListener("mouseup", endDrag);
131
+ (_e = attachedGridElementRef.current) === null || _e === void 0 ? void 0 : _e.addEventListener("scroll", onScroll);
132
+ }, [gridRef, onMouseMove, onScroll, endDrag]);
133
+ (0, react_1.useEffect)(() => {
134
+ anchorIdRef.current = null;
135
+ }, [rows]);
136
+ (0, react_1.useEffect)(() => endDrag, [endDrag]);
137
+ return { onCheckboxMouseDown, suppressNextChangeRef };
138
+ };
139
+ exports.useDragSelection = useDragSelection;
@@ -1,4 +1,4 @@
1
- import { ReactNode } from "react";
1
+ import { ReactNode, RefObject } from "react";
2
2
  import { IListColumn } from "../table";
3
3
  import { ISelectionValue, SelectionState } from "./interfaces";
4
4
  import "./selectableColumn.less";
@@ -33,7 +33,7 @@ export declare const getEmptySelection: () => {
33
33
  selected: string[];
34
34
  };
35
35
  export declare const SelectableWrapperName = "Selectable";
36
- export declare const useSelectableRows: <T extends IRowEntity<N>, N extends IEntityWithId>(columns: IListColumn<T, N>[], entities: T[], isMobile: boolean, selectMode: boolean, setSelectMode: (value: boolean) => void, selectable?: ISelectableRowsOptions<T, N>, isInfinite?: boolean) => {
36
+ export declare const useSelectableRows: <T extends IRowEntity<N>, N extends IEntityWithId>(columns: IListColumn<T, N>[], entities: T[], isMobile: boolean, selectMode: boolean, setSelectMode: (value: boolean) => void, selectable?: ISelectableRowsOptions<T, N>, isInfinite?: boolean, gridRef?: RefObject<HTMLElement | null>, expandedRows?: string[]) => {
37
37
  selectableColumns: IListColumn<T, N>[];
38
38
  selectableFeedWrapper: (primaryData: ReactNode, secondaryData: ReactNode, entity: T | N, isNested: boolean) => [ReactNode, ReactNode];
39
39
  };
@@ -84,6 +84,8 @@ const useLanguage_1 = require("../../utils/localization/useLanguage");
84
84
  const checkRow_1 = require("./utils/checkRow");
85
85
  const isRowChecked_1 = require("./utils/isRowChecked");
86
86
  const getCurrentPageSelection_1 = require("./utils/getCurrentPageSelection");
87
+ const useDragSelection_1 = require("./useDragSelection");
88
+ const getDragSelectionRows_1 = require("./utils/getDragSelectionRows");
87
89
  const getEmptySelection = () => ({
88
90
  all: false,
89
91
  selected: []
@@ -92,7 +94,7 @@ exports.getEmptySelection = getEmptySelection;
92
94
  exports.SelectableWrapperName = "Selectable";
93
95
  // Infinite scroll has no pages, so the header checkbox always means "select all" (never current page).
94
96
  const resolveCheckboxEmitsCurrentPage = (isInfinite, checkboxSelectsCurrentPage, turnOffSelectAll) => isInfinite ? false : checkboxSelectsCurrentPage !== null && checkboxSelectsCurrentPage !== void 0 ? checkboxSelectsCurrentPage : turnOffSelectAll;
95
- const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false) => {
97
+ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false, gridRef, expandedRows) => {
96
98
  var _a;
97
99
  const {
98
100
  translate
@@ -142,30 +144,19 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
142
144
  }
143
145
  }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
144
146
  const getNewSelection = (0, react_1.useCallback)((id, checked) => {
145
- var _a;
146
- if ((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all) {
147
- // MYG-142234: `selections` holds the ids excluded from the "all" selection.
148
- // Toggling a row here must only ever add/remove that single id from the
149
- // exclusion set - it must never be rebuilt from `entities` (the current page),
150
- // otherwise every other page's rows would silently fall out of the selection.
151
- const excluded = new Set(selections);
152
- (0, checkRow_1.checkRow)(excluded, selectable, entities, id, !checked);
153
- return excluded;
147
+ if (state === interfaces_1.SelectionState.All) {
148
+ const newSelection = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable);
149
+ (0, checkRow_1.checkRow)(newSelection, selectable, entities, id, false);
150
+ return newSelection;
154
151
  }
155
152
  (0, checkRow_1.checkRow)(selections, selectable, entities, id, checked);
156
153
  return selections;
157
- }, [entities, selectable, selections]);
154
+ }, [state, entities, selectable, selections]);
158
155
  const onSelectListener = (0, react_1.useCallback)((id, checked) => {
159
156
  var _a;
160
- const wasAllSelected = ((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all) || false;
161
157
  const newSelection = getNewSelection(id, checked);
162
- const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, newSelection, wasAllSelected, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy);
163
- // MYG-142234: once selection spans "all" pages, unchecking a row must keep `all: true`
164
- // and only record the exclusion - it must not collapse to the current page's ids.
165
- const newValue = wasAllSelected ? {
166
- selected: [...newSelection],
167
- all: true
168
- } : {
158
+ const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, newSelection, ((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all) || false, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy);
159
+ const newValue = {
169
160
  selected: [...newSelection],
170
161
  all: newState === interfaces_1.SelectionState.All
171
162
  };
@@ -173,8 +164,49 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
173
164
  selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
174
165
  setSelectMode(newValue.all || newValue.selected.length > 0);
175
166
  }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, setState, getNewSelection]);
167
+ const onBatchSelect = (0, react_1.useCallback)((rangeIds, select, base) => {
168
+ var _a;
169
+ const result = new Set(base);
170
+ const limit = selectable === null || selectable === void 0 ? void 0 : selectable.selectionLimit;
171
+ for (const id of rangeIds) {
172
+ if (select && limit !== undefined && result.size >= limit) {
173
+ break;
174
+ }
175
+ (0, checkRow_1.checkRow)(result, selectable, entities, id, select);
176
+ }
177
+ const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, result, ((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all) || false, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy);
178
+ const newValue = {
179
+ selected: [...result],
180
+ all: newState === interfaces_1.SelectionState.All
181
+ };
182
+ setState(newState);
183
+ selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
184
+ setSelectMode(newValue.all || newValue.selected.length > 0);
185
+ }, [entities, selectable, checkboxVisible, checkboxDisabled, setSelectMode]);
186
+ // Deliberately independent of the current selection, so the drag anchor survives the
187
+ // selection changes a drag itself produces.
188
+ const {
189
+ rows: dragRows,
190
+ entityById
191
+ } = (0, react_1.useMemo)(() => (0, getDragSelectionRows_1.getDragSelectionRows)(entities, expandedRows), [entities, expandedRows]);
192
+ const isSelectable = (0, react_1.useCallback)(row => {
193
+ const entity = entityById.get(row.id);
194
+ return !!entity && checkboxVisible(entity, row.isNested) && !checkboxDisabled(entity, row.isNested);
195
+ }, [entityById, checkboxVisible, checkboxDisabled]);
196
+ const getBaseSelection = (0, react_1.useCallback)(() => state === interfaces_1.SelectionState.All ? (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable) : new Set(selections), [state, entities, selectable, selections]);
197
+ const {
198
+ onCheckboxMouseDown,
199
+ suppressNextChangeRef
200
+ } = (0, useDragSelection_1.useDragSelection)(dragRows, gridRef, onBatchSelect, getBaseSelection, isSelectable, !!selectable);
201
+ const onCheckboxChange = (0, react_1.useCallback)((id, checked) => {
202
+ if (suppressNextChangeRef.current) {
203
+ suppressNextChangeRef.current = false;
204
+ return;
205
+ }
206
+ onSelectListener(id, checked);
207
+ }, [onSelectListener, suppressNextChangeRef]);
176
208
  const onChangeSelectionState = (0, react_1.useCallback)(newState => {
177
- var _a, _b, _c;
209
+ var _a, _b;
178
210
  if (newState === interfaces_1.SelectionState.All) {
179
211
  (selectable === null || selectable === void 0 ? void 0 : selectable.onSelect) && selectable.onSelect({
180
212
  selected: [],
@@ -193,11 +225,7 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
193
225
  }
194
226
  const newSelections = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable);
195
227
  setState(newState);
196
- // MYG-142234: previous `selected` ids mean something different depending on `all` -
197
- // included ids when `all` is false, excluded ids when `all` is true. Switching to an
198
- // explicit "select current page" here always leaves `all: false`, so a previous
199
- // exclusion list must not be reinterpreted as an inclusion list.
200
- const previousSelections = ((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all) ? [] : (_c = (_b = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _b === void 0 ? void 0 : _b.selected) !== null && _c !== void 0 ? _c : [];
228
+ const previousSelections = (_b = (_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.selected) !== null && _b !== void 0 ? _b : [];
201
229
  const mergedSelections = new Set([...previousSelections, ...newSelections]);
202
230
  const newValue = {
203
231
  selected: [...mergedSelections],
@@ -216,12 +244,7 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
216
244
  }
217
245
  return translate("Deselect all");
218
246
  }, [selectable, selectableState, state, translate]);
219
- const isEntityChecked = (0, react_1.useCallback)(
220
- // MYG-142234: while `selection.all` is true, `selections` holds excluded ids, and every
221
- // row must be evaluated through the SelectionState.All (exclusion-aware) branch of
222
- // isRowChecked - not the per-page `state`, which can be Partial/None for a page that
223
- // contains some of those exclusions.
224
- (entity, isNested) => (0, isRowChecked_1.isRowChecked)(selections, isAllSelected ? interfaces_1.SelectionState.All : state, selectable === null || selectable === void 0 ? void 0 : selectable.strategy, entity, isNested), [selections, isAllSelected, state, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
247
+ const isEntityChecked = (0, react_1.useCallback)((entity, isNested) => (0, isRowChecked_1.isRowChecked)(selections, state, selectable === null || selectable === void 0 ? void 0 : selectable.strategy, entity, isNested), [selections, state, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
225
248
  const hasSelectable = !!selectable;
226
249
  const selectableCheckboxSelectsCurrentPage = selectable === null || selectable === void 0 ? void 0 : selectable.checkboxSelectsCurrentPage;
227
250
  const selectableTurnOffSelectAll = selectable === null || selectable === void 0 ? void 0 : selectable.turnOffSelectAll;
@@ -259,7 +282,8 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
259
282
  indeterminate: checked.indeterminate,
260
283
  disabled: isDisable,
261
284
  label: checkboxTitle(entity),
262
- onChange: onSelectListener,
285
+ onChange: onCheckboxChange,
286
+ onMouseDown: isDisable ? undefined : onCheckboxMouseDown,
263
287
  children: (0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell.Content, {
264
288
  children: value
265
289
  })
@@ -273,30 +297,16 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
273
297
  checked: state === interfaces_1.SelectionState.CurrentPage || state === interfaces_1.SelectionState.All,
274
298
  indeterminate: state === interfaces_1.SelectionState.Partial,
275
299
  onChange: newValue => {
276
- var _a, _b, _c;
300
+ var _a, _b;
277
301
  if (newValue) {
278
302
  const newState = checkboxEmitsCurrentPage ? interfaces_1.SelectionState.CurrentPage : interfaces_1.SelectionState.All;
279
303
  setState(newState);
280
304
  onChangeSelectionState(newState);
281
- } else if ((_a = selectable.selection) === null || _a === void 0 ? void 0 : _a.all) {
282
- // MYG-142234: in exclusion mode, `selected` holds excluded ids. Unchecking
283
- // the header must add the current page's ids to that exclusion set and
284
- // keep `all: true` - it must never be treated as an inclusion list, or
285
- // every other page's selection would be silently wiped out.
286
- const currentPageIds = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable);
287
- const newExcluded = new Set([...selectable.selection.selected, ...currentPageIds]);
288
- const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, newExcluded, true, checkboxVisible, checkboxDisabled, selectable.strategy);
289
- setState(newState);
290
- selectable.onSelect({
291
- selected: [...newExcluded],
292
- all: true
293
- });
294
- setSelectMode(true);
295
305
  } else {
296
306
  // Intentionally different from onSelect(None) ("Deselect all" menu item, which clears everything).
297
307
  // Unchecking the header checkbox only removes the current page from the selection, preserving other pages.
298
308
  const currentPageIds = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable);
299
- const remaining = ((_c = (_b = selectable.selection) === null || _b === void 0 ? void 0 : _b.selected) !== null && _c !== void 0 ? _c : []).filter(id => !currentPageIds.has(id));
309
+ const remaining = ((_b = (_a = selectable.selection) === null || _a === void 0 ? void 0 : _a.selected) !== null && _b !== void 0 ? _b : []).filter(id => !currentPageIds.has(id));
300
310
  const newState = remaining.length > 0 ? interfaces_1.SelectionState.Partial : interfaces_1.SelectionState.None;
301
311
  setState(newState);
302
312
  selectable.onSelect({
@@ -319,7 +329,7 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
319
329
  return cell;
320
330
  }
321
331
  };
322
- }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onSelectListener, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
332
+ }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onCheckboxChange, onCheckboxMouseDown, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
323
333
  const selectableFeedWrapper = (0, react_1.useCallback)((primaryData, secondaryData, entity, isNested) => {
324
334
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
325
335
  if (!entity) {
@@ -6,41 +6,6 @@ const calculateSelectionState = (entities, selections, all, checkboxVisible, che
6
6
  if (selections.size === 0) {
7
7
  return all ? interfaces_1.SelectionState.All : interfaces_1.SelectionState.None;
8
8
  }
9
- if (all) {
10
- // When `all` is true, `selections` holds the ids explicitly excluded from the
11
- // otherwise-fully-selected set (see ISelectionValue), rather than included ids.
12
- const isExcluded = (entity) => {
13
- if (strategy === "nested" && entity.children) {
14
- if (entity.children.length === 0) {
15
- return false;
16
- }
17
- return entity.children.every(child => {
18
- if (!checkboxVisible(child)) {
19
- return true;
20
- }
21
- if (checkboxDisabled(child)) {
22
- return true;
23
- }
24
- return selections.has(child.id);
25
- });
26
- }
27
- return selections.has(entity.id);
28
- };
29
- const isPartiallyExcluded = (entity) => {
30
- if (strategy === "nested" && entity.children) {
31
- return entity.children.some(child => selections.has(child.id));
32
- }
33
- return selections.has(entity.id);
34
- };
35
- const relevantEntities = entities.filter(entity => checkboxVisible(entity) && !checkboxDisabled(entity));
36
- if (relevantEntities.length === 0) {
37
- return interfaces_1.SelectionState.All;
38
- }
39
- if (relevantEntities.every(entity => !isPartiallyExcluded(entity))) {
40
- return interfaces_1.SelectionState.All;
41
- }
42
- return relevantEntities.every(entity => isExcluded(entity)) ? interfaces_1.SelectionState.None : interfaces_1.SelectionState.Partial;
43
- }
44
9
  return entities.every(entity => {
45
10
  if (!checkboxVisible(entity)) {
46
11
  return true;
@@ -0,0 +1,15 @@
1
+ import { IEntityWithId } from "../../../commonHelpers/entity";
2
+ import { IRowEntity } from "../../../dataGrid/row/row";
3
+ import { IDragSelectionRow } from "../interfaces";
4
+ export interface IDragSelection<T> {
5
+ /** The rows in render order. */
6
+ rows: IDragSelectionRow[];
7
+ /** Every entity a row can point at, parents and children alike. */
8
+ entityById: Map<string, T>;
9
+ }
10
+ /**
11
+ * Flattens the entities into the rows the grid actually renders: each entity followed by its
12
+ * children while it is expanded. Drag and shift-click ranges walk this list, so they cross
13
+ * nesting levels the way the user sees them on screen.
14
+ */
15
+ export declare const getDragSelectionRows: <T extends IRowEntity<N>, N extends IEntityWithId>(entities: T[], expandedRows?: string[]) => IDragSelection<T | N>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDragSelectionRows = void 0;
4
+ /**
5
+ * Flattens the entities into the rows the grid actually renders: each entity followed by its
6
+ * children while it is expanded. Drag and shift-click ranges walk this list, so they cross
7
+ * nesting levels the way the user sees them on screen.
8
+ */
9
+ const getDragSelectionRows = (entities, expandedRows) => {
10
+ const expanded = new Set(expandedRows);
11
+ const rows = [];
12
+ const entityById = new Map();
13
+ entities.forEach(entity => {
14
+ rows.push({ id: entity.id, isNested: false });
15
+ entityById.set(entity.id, entity);
16
+ // Children are always indexed — a collapsed row's children still need to resolve for
17
+ // the selection predicates — but only an expanded row contributes them to the range.
18
+ const isExpanded = expanded.has(entity.id);
19
+ (entity.children || []).forEach(child => {
20
+ entityById.set(child.id, child);
21
+ if (isExpanded) {
22
+ rows.push({ id: child.id, isNested: true });
23
+ }
24
+ });
25
+ });
26
+ return { rows, entityById };
27
+ };
28
+ exports.getDragSelectionRows = getDragSelectionRows;
@@ -0,0 +1,2 @@
1
+ import { IDragSelectionRow } from "../interfaces";
2
+ export declare const getRangeIds: (rows: IDragSelectionRow[], fromId: string, toId: string, isSelectable: (row: IDragSelectionRow) => boolean) => string[];
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRangeIds = void 0;
4
+ const getRangeIds = (rows, fromId, toId, isSelectable) => {
5
+ const fromIdx = rows.findIndex(row => row.id === fromId);
6
+ const toIdx = rows.findIndex(row => row.id === toId);
7
+ if (fromIdx === -1 || toIdx === -1) {
8
+ return [];
9
+ }
10
+ const start = Math.min(fromIdx, toIdx);
11
+ const end = Math.max(fromIdx, toIdx);
12
+ const ids = [];
13
+ for (let i = start; i <= end; i++) {
14
+ const row = rows[i];
15
+ if (isSelectable(row)) {
16
+ ids.push(row.id);
17
+ }
18
+ }
19
+ return ids;
20
+ };
21
+ exports.getRangeIds = getRangeIds;
@@ -4,18 +4,7 @@ exports.isRowChecked = void 0;
4
4
  const interfaces_1 = require("../interfaces");
5
5
  const isRowChecked = (selections, state, strategy, entity, isNested) => {
6
6
  if (state === interfaces_1.SelectionState.All) {
7
- // When the overall selection is "all", `selections` holds the ids that have been
8
- // explicitly excluded from that selection (see ISelectionValue), not included ids.
9
- if (isNested) {
10
- return { indeterminate: false, checked: !selections.has(entity.id) };
11
- }
12
- const mainEntity = entity;
13
- if (strategy === "nested" && mainEntity.children && mainEntity.children.length > 0) {
14
- const allChildrenChecked = mainEntity.children.every(child => !selections.has(child.id));
15
- const someChildrenChecked = mainEntity.children.some(child => !selections.has(child.id));
16
- return { indeterminate: someChildrenChecked && !allChildrenChecked, checked: allChildrenChecked };
17
- }
18
- return { indeterminate: false, checked: !selections.has(entity.id) };
7
+ return { indeterminate: false, checked: true };
19
8
  }
20
9
  if (isNested) {
21
10
  return { indeterminate: false, checked: selections.has(entity.id) };
@@ -288,7 +288,7 @@ const TableInner = ({
288
288
  const {
289
289
  selectableColumns,
290
290
  selectableFeedWrapper
291
- } = (0, useSelectableRows_1.useSelectableRows)(nestedColumns, entities, isMobile, selectMode, setMobileSelectMode, isLoading ? undefined : selectable, isInfinite);
291
+ } = (0, useSelectableRows_1.useSelectableRows)(nestedColumns, entities, isMobile, selectMode, setMobileSelectMode, isLoading ? undefined : selectable, isInfinite, gridRef, expanded);
292
292
  const {
293
293
  sortableColumns,
294
294
  feedSortControl
@@ -108,7 +108,7 @@ export const Absolute = ({ isOpen, id, paddingX, paddingY, className, children,
108
108
  returnFocusToTrigger();
109
109
  }
110
110
  }, [isOpen, returnFocusToTrigger]);
111
- const condition = useCallback((subscriptionTrigger) => useTrapFocusWithTrigger !== "off" && !!subscriptionTrigger, [useTrapFocusWithTrigger]);
111
+ const condition = useCallback(() => (useTrapFocusWithTrigger === "off" ? false : true), [useTrapFocusWithTrigger]);
112
112
  useTrapFocus(popupRef, useTrapFocusWithTrigger === "withTrigger" ? triggerRef : undefined, isOpen, condition);
113
113
  useEscape(popupRef, handleEscape, isOpen);
114
114
  useArrowKey(popupRef, handleEscape, isOpen);
@@ -1,3 +1,3 @@
1
- import { Scale } from "chart.js";
1
+ import { Scale, type ChartOptions } from "chart.js";
2
2
  import { ILineChartData } from "../../lineChart/interfaces";
3
- export declare function getInterpolatedValue(xScale: Scale, data: ILineChartData, datasetIndex: number, xPixel: number): number | null;
3
+ export declare function getInterpolatedValue(xScale: Scale, data: ILineChartData, datasetIndex: number, xPixel: number, parsing?: ChartOptions<"line">["parsing"]): number | null;
@@ -1,4 +1,4 @@
1
- export function getInterpolatedValue(xScale, data, datasetIndex, xPixel) {
1
+ export function getInterpolatedValue(xScale, data, datasetIndex, xPixel, parsing) {
2
2
  const dataset = data.datasets[datasetIndex];
3
3
  const dataPoints = dataset.data;
4
4
  if (dataPoints.length < 2) {
@@ -15,7 +15,8 @@ export function getInterpolatedValue(xScale, data, datasetIndex, xPixel) {
15
15
  if (y === null) {
16
16
  continue;
17
17
  }
18
- const pointXPixel = xScale.getPixelForValue(x);
18
+ const parsedX = parsing === false ? x : xScale.parse(x, i);
19
+ const pointXPixel = xScale.getPixelForValue(parsedX);
19
20
  if (pointXPixel <= xPixel && pointXPixel > lowerXPixel) {
20
21
  lowerPoint = y;
21
22
  lowerXPixel = pointXPixel;
@@ -57,6 +57,7 @@ export const LinePlugin = (containerId, options, isDark) => ({
57
57
  let lowestValueY = Infinity;
58
58
  const items = datasets
59
59
  .map((dataset, dsIndex) => {
60
+ var _a;
60
61
  if (!chart.isDatasetVisible(dsIndex)) {
61
62
  return undefined;
62
63
  }
@@ -64,7 +65,7 @@ export const LinePlugin = (containerId, options, isDark) => ({
64
65
  return undefined;
65
66
  }
66
67
  const xScale = chart.scales.x;
67
- const value = getInterpolatedValue(xScale, chart.data, dsIndex, x);
68
+ const value = getInterpolatedValue(xScale, chart.data, dsIndex, x, (_a = dataset.parsing) !== null && _a !== void 0 ? _a : chart.options.parsing);
68
69
  const yAxisID = dataset.yAxisID || "y";
69
70
  const yScale = chart.scales[yAxisID];
70
71
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
@@ -3,14 +3,18 @@ export function getFormattedLabel(value, dateFormatter, options) {
3
3
  var _a, _b, _c;
4
4
  const scaleType = (_b = (_a = options === null || options === void 0 ? void 0 : options.scales) === null || _a === void 0 ? void 0 : _a.x) === null || _b === void 0 ? void 0 : _b.type;
5
5
  let format;
6
+ let parser;
6
7
  if (((_c = options === null || options === void 0 ? void 0 : options.scales) === null || _c === void 0 ? void 0 : _c.x) && scaleType) {
7
8
  const scaleFormat = options.scales.x[scaleType];
8
9
  if ((scaleFormat === null || scaleFormat === void 0 ? void 0 : scaleFormat.unit) && scaleFormat.displayFormats && scaleFormat.displayFormats[scaleFormat.unit]) {
9
10
  format = scaleFormat.displayFormats[scaleFormat.unit];
10
11
  }
12
+ if (options.parsing !== false && scaleFormat && "parser" in scaleFormat && typeof scaleFormat.parser === "function") {
13
+ parser = scaleFormat.parser;
14
+ }
11
15
  }
12
16
  if (value instanceof Date || (typeof value === "string" && isDateString(value))) {
13
- return dateFormatter(value, format);
17
+ return dateFormatter(parser ? new Date(parser(value)) : value, format);
14
18
  }
15
19
  return String(value);
16
20
  }
@@ -8,6 +8,7 @@ export interface ICheckbox extends IZenComponentProps {
8
8
  checked?: boolean;
9
9
  indeterminate?: boolean;
10
10
  title?: string;
11
+ ariaLabel?: string;
11
12
  disabled?: boolean;
12
13
  fullWidth?: boolean;
13
14
  reverse?: boolean;
@@ -16,4 +17,4 @@ export interface ICheckbox extends IZenComponentProps {
16
17
  tabIndex?: number;
17
18
  describedBy?: string;
18
19
  }
19
- export declare const Checkbox: ({ reverse, fullWidth, id, checked, indeterminate, title, className, children, disabled, wrapped, describedBy, ...rest }: ICheckbox) => import("react/jsx-runtime").JSX.Element;
20
+ export declare const Checkbox: ({ reverse, fullWidth, id, checked, indeterminate, title, ariaLabel, className, children, disabled, wrapped, describedBy, ...rest }: ICheckbox) => import("react/jsx-runtime").JSX.Element;
@@ -20,14 +20,14 @@ import { CheckboxIconCheckmark } from "./checkboxIconCheckmark";
20
20
  import { CheckboxIconMinus } from "./checkboxIconMinus";
21
21
  import { useMobile } from "../commonHelpers/hooks/useMobile";
22
22
  export const Checkbox = (_a) => {
23
- var { reverse, fullWidth, id, checked, indeterminate, title, className = "", children, disabled, wrapped, describedBy } = _a, rest = __rest(_a, ["reverse", "fullWidth", "id", "checked", "indeterminate", "title", "className", "children", "disabled", "wrapped", "describedBy"]);
23
+ var { reverse, fullWidth, id, checked, indeterminate, title, ariaLabel, className = "", children, disabled, wrapped, describedBy } = _a, rest = __rest(_a, ["reverse", "fullWidth", "id", "checked", "indeterminate", "title", "ariaLabel", "className", "children", "disabled", "wrapped", "describedBy"]);
24
24
  const state = getCheckboxState(checked, indeterminate);
25
25
  const generatedId = React.useId();
26
26
  const intId = id || generatedId;
27
27
  const driveClasses = useDriveClassName("zen-checkbox");
28
28
  const isMobile = useMobile();
29
29
  const checkboxIconClasses = useMemo(() => classNames(["zen-checkbox__icon", disabled ? "zen-checkbox__icon--disabled" : ""]), [disabled]);
30
- const checkbox = (_jsx(TriStateCheckbox, Object.assign({ className: "zen-checkbox__input", id: intId, checked: checked, indeterminate: indeterminate, disabled: disabled, "aria-label": title, "aria-describedby": describedBy }, rest)));
30
+ const checkbox = (_jsx(TriStateCheckbox, Object.assign({ className: "zen-checkbox__input", id: intId, checked: checked, indeterminate: indeterminate, disabled: disabled, "aria-label": ariaLabel || title, "aria-describedby": describedBy }, rest)));
31
31
  const iconAndLabel = (_jsxs(_Fragment, { children: [_jsx("div", { className: "zen-checkbox__box", "aria-hidden": true, children: state === CheckboxState.Indeterminate ? (_jsx(CheckboxIconMinus, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" })) : state === CheckboxState.On ? (_jsx(CheckboxIconCheckmark, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" })) : null }), children ? (_jsx("div", { className: classNames(["zen-checkbox__label-text", fullWidth ? "zen-checkbox__label-text--full-width" : ""]), children: children })) : null] }));
32
32
  if (wrapped) {
33
33
  return (_jsxs("label", { className: classNames(["zen-checkbox", driveClasses || "", className]), title: title, children: [checkbox, _jsx("div", { className: classNames(["zen-checkbox__label", reverse ? "zen-checkbox__label--reverse" : ""]), children: iconAndLabel })] }));
@@ -445,6 +445,7 @@ export const CheckboxListWithAction = ({
445
445
  checked: opt.checked,
446
446
  disabled: opt.blocked,
447
447
  title: translate("Toggle {groupName} filter").replace("{groupName}", titleForRender),
448
+ ariaLabel: titleForRender,
448
449
  describedBy: opt.isWithAction ? navigationInstructionsId : undefined,
449
450
  "data-indeterminate": opt.partialChecked,
450
451
  tabIndex: getTabIndex(ind, "checkbox", opt.blocked),
@@ -1,13 +1,4 @@
1
1
  import { RefObject } from "react";
2
2
  type TElementToBool = (element: HTMLElement) => boolean;
3
- /**
4
- * Traps keyboard (Tab) focus within `containerRef` (and optionally its `triggerRef`).
5
- *
6
- * Nested-popup contract: for correct nested-popup behaviour, a focused element that triggers an
7
- * open child popup must expose a `data-popup-id` attribute whose value is the `id` of the child
8
- * popup element rendered in the DOM. When present, focus is deferred to that child popup's trap.
9
- * This contract is fulfilled automatically by `ControlledPopup`; callers using `useTrapFocus`
10
- * directly must set `data-popup-id` themselves or nested popups will silently lose focus handling.
11
- */
12
3
  export declare const useTrapFocus: (containerRef: RefObject<HTMLElement | null>, triggerRef: RefObject<HTMLElement | null> | undefined, subscriptionTrigger: unknown, condition?: (t: unknown) => boolean, isElementVisible?: TElementToBool) => void;
13
4
  export {};