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

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 (33) hide show
  1. package/dist/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +1 -2
  2. package/dist/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
  3. package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +2 -4
  4. package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +1 -10
  5. package/dist/dataGrid/row/row.js +2 -3
  6. package/dist/dataGrid/withSelectableRows/withSelectableRows.js +12 -73
  7. package/dist/table/selectable/interfaces.d.ts +0 -9
  8. package/dist/table/selectable/useSelectableRows.d.ts +2 -2
  9. package/dist/table/selectable/useSelectableRows.js +3 -47
  10. package/dist/table/table.js +1 -1
  11. package/esm/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +1 -2
  12. package/esm/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
  13. package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +2 -4
  14. package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +1 -10
  15. package/esm/dataGrid/row/row.js +2 -3
  16. package/esm/dataGrid/withSelectableRows/withSelectableRows.js +12 -73
  17. package/esm/table/selectable/interfaces.d.ts +0 -9
  18. package/esm/table/selectable/useSelectableRows.d.ts +2 -2
  19. package/esm/table/selectable/useSelectableRows.js +3 -47
  20. package/esm/table/table.js +1 -1
  21. package/package.json +1 -1
  22. package/dist/table/selectable/useDragSelection.d.ts +0 -10
  23. package/dist/table/selectable/useDragSelection.js +0 -139
  24. package/dist/table/selectable/utils/getDragSelectionRows.d.ts +0 -15
  25. package/dist/table/selectable/utils/getDragSelectionRows.js +0 -28
  26. package/dist/table/selectable/utils/getRangeIds.d.ts +0 -2
  27. package/dist/table/selectable/utils/getRangeIds.js +0 -21
  28. package/esm/table/selectable/useDragSelection.d.ts +0 -10
  29. package/esm/table/selectable/useDragSelection.js +0 -135
  30. package/esm/table/selectable/utils/getDragSelectionRows.d.ts +0 -15
  31. package/esm/table/selectable/utils/getDragSelectionRows.js +0 -24
  32. package/esm/table/selectable/utils/getRangeIds.d.ts +0 -2
  33. package/esm/table/selectable/utils/getRangeIds.js +0 -17
@@ -1,4 +1,4 @@
1
- import { FC, MouseEvent as ReactMouseEvent, PropsWithChildren, ReactElement } from "react";
1
+ import { FC, PropsWithChildren, ReactElement } from "react";
2
2
  import { IZenIdComponentProps } from "../../../commonHelpers/zenComponent";
3
3
  import "./checkboxColumn.less";
4
4
  interface ICheckboxCellProps extends IZenIdComponentProps {
@@ -8,7 +8,6 @@ interface ICheckboxCellProps extends IZenIdComponentProps {
8
8
  disabled?: boolean;
9
9
  children?: ReactElement<typeof CheckboxCell.Content>;
10
10
  onChange?: (id: string, checked: boolean) => void;
11
- onMouseDown?: (id: string, checked: boolean, e: ReactMouseEvent) => void;
12
11
  }
13
12
  interface ICheckboxCell extends FC<ICheckboxCellProps> {
14
13
  Content: FC<PropsWithChildren>;
@@ -4,7 +4,7 @@ exports.CheckboxCell = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const checkbox_1 = require("../../../checkbox/checkbox");
6
6
  const classNames_1 = require("../../../commonHelpers/classNames/classNames");
7
- const CheckboxCell = ({ id, checked, indeterminate, label, disabled, className, onChange, onMouseDown, children }) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-checkbox-column", className || ""]), onMouseDown: onMouseDown ? e => onMouseDown(id, checked, e) : undefined, children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { className: "zen-checkbox-column__checkbox", checked: checked, indeterminate: indeterminate, disabled: disabled, title: label, onChange: e => onChange && onChange(id, e.target.checked), wrapped: true }), children] }));
7
+ const CheckboxCell = ({ id, checked, indeterminate, label, disabled, className, onChange, children }) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-checkbox-column", className || ""]), children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { className: "zen-checkbox-column__checkbox", checked: checked, indeterminate: indeterminate, disabled: disabled, title: label, onChange: e => onChange && onChange(id, e.target.checked), wrapped: true }), children] }));
8
8
  exports.CheckboxCell = CheckboxCell;
9
9
  exports.CheckboxCell.Content = function content({ children }) {
10
10
  return (0, jsx_runtime_1.jsx)("div", { className: "zen-checkbox-column__content", children: children });
@@ -1,4 +1,4 @@
1
- import { MouseEvent as ReactMouseEvent, ReactNode, RefObject } from "react";
1
+ import { ReactNode, RefObject } from "react";
2
2
  import { IListColumnWrapper } from "../../listColumn";
3
3
  import "./checkboxColumn.less";
4
4
  import { SimpleEventHandler } from "../../../commonHelpers/simpleEventHandler";
@@ -17,8 +17,7 @@ export interface ICheckboxColumnWrapper<T extends object> extends IListColumnWra
17
17
  attach(event: "toggle", handler: (state: [Event, HTMLButtonElement]) => void): this;
18
18
  attach(event: "change", handler: (state: [string, boolean]) => void): this;
19
19
  attach(event: "change-all", handler: (state: [boolean]) => void): this;
20
- attach(event: "mousedown", handler: (state: [string, boolean, ReactMouseEvent]) => void): this;
21
- detach(event: "change" | "toggle" | "change-all" | "mousedown", handler?: (state: unknown) => void): this;
20
+ detach(event: "change" | "toggle" | "change-all", handler?: (state: unknown) => void): this;
22
21
  }
23
22
  export declare enum SelectionState {
24
23
  All = 0,
@@ -35,7 +34,6 @@ export declare class CheckboxColumnWrapper<T extends IEntityWithId> extends Simp
35
34
  private state;
36
35
  private readonly actionsClickHandler;
37
36
  private readonly changeHandler;
38
- private readonly mouseDownHandler;
39
37
  private readonly changeHandlerAll;
40
38
  constructor(selections: Set<string>, options: ICheckboxColumnOptions<T>, menuTriggerRef: RefObject<HTMLButtonElement | null>);
41
39
  get selectionState(): SelectionState;
@@ -67,15 +67,6 @@ class CheckboxColumnWrapper extends simpleEventHandler_1.SimpleEventHandler {
67
67
  this.fire("change", [id, checked]);
68
68
  }
69
69
  });
70
- // Only fired for enabled checkboxes, so a disabled row can never become a drag anchor.
71
- Object.defineProperty(this, "mouseDownHandler", {
72
- enumerable: true,
73
- configurable: true,
74
- writable: true,
75
- value: (id, checked, e) => {
76
- this.fire("mousedown", [id, checked, e]);
77
- }
78
- });
79
70
  Object.defineProperty(this, "changeHandlerAll", {
80
71
  enumerable: true,
81
72
  configurable: true,
@@ -101,7 +92,7 @@ class CheckboxColumnWrapper extends simpleEventHandler_1.SimpleEventHandler {
101
92
  }
102
93
  const allowed = this.condition(entity);
103
94
  const isDisable = this.disabled ? this.disabled(entity) : this.state === SelectionState.All;
104
- const cell = ((0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell, { id: entity.id, className: allowed ? "" : "zen-checkbox-column--no-checkbox", checked: this.state === SelectionState.All || this.selections.has(entity.id), indeterminate: false, disabled: isDisable, label: this.options.createTitle(entity), onChange: this.changeHandler, onMouseDown: isDisable ? undefined : this.mouseDownHandler, children: (0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell.Content, { children: value }) }));
95
+ const cell = ((0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell, { id: entity.id, className: allowed ? "" : "zen-checkbox-column--no-checkbox", checked: this.state === SelectionState.All || this.selections.has(entity.id), indeterminate: false, disabled: isDisable, label: this.options.createTitle(entity), onChange: this.changeHandler, children: (0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell.Content, { children: value }) }));
105
96
  return cell;
106
97
  }
107
98
  renderHeader(title) {
@@ -60,8 +60,7 @@ const Row = ({ id, entity, columns, visibleRows, flexibleColumnWidth, isLastRow,
60
60
  return acc;
61
61
  }, { cells: [], colspan: 0 }).cells, [columns, expanded, getCellParams, isVisible, onExpandedChange, isActive, active, onClick]);
62
62
  const cells = (0, react_1.useMemo)(() => renderCells(entity, false), [entity, renderCells]);
63
- const nestedEntities = (0, react_1.useMemo)(() => (expanded && entity.children ? entity.children : []), [entity.children, expanded]);
64
- const nestedCells = (0, react_1.useMemo)(() => nestedEntities.map(nestedEntity => renderCells(nestedEntity, true)), [nestedEntities, renderCells]);
65
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("tr", { "data-row-id": id, id: mainRowId, role: "row", "aria-level": isTreeGrid ? 1 : undefined, "aria-posinset": isTreeGrid ? ariaPosinset : undefined, "aria-setsize": isTreeGrid ? ariaSetsize : undefined, "aria-expanded": isTreeGrid ? expanded : undefined, className: (0, classNames_1.classNames)(["zen-data-grid__row", className || "", isLastRow ? "zen-data-grid__row--last" : ""]), children: cells }, mainRowId), nestedCells.map((nestedRow, index) => ((0, jsx_runtime_1.jsx)("tr", { "data-row-id": nestedEntities[index].id, id: `${mainRowId}_child_${index}`, role: "row", "aria-level": 2, "aria-posinset": index + 1, "aria-setsize": nestedCells.length, className: "zen-data-grid__row zen-data-grid__row--nested", children: nestedRow }, `${mainRowId}_child_${index}`)))] }));
63
+ const nestedCells = (0, react_1.useMemo)(() => (expanded && entity.children ? entity.children : []).map(nestedEntity => renderCells(nestedEntity, true)), [entity.children, expanded, renderCells]);
64
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("tr", { "data-row-id": id, id: mainRowId, role: "row", "aria-level": isTreeGrid ? 1 : undefined, "aria-posinset": isTreeGrid ? ariaPosinset : undefined, "aria-setsize": isTreeGrid ? ariaSetsize : undefined, "aria-expanded": isTreeGrid ? expanded : undefined, className: (0, classNames_1.classNames)(["zen-data-grid__row", className || "", isLastRow ? "zen-data-grid__row--last" : ""]), children: cells }, mainRowId), nestedCells.map((nestedRow, index) => ((0, jsx_runtime_1.jsx)("tr", { id: `${mainRowId}_child_${index}`, role: "row", "aria-level": 2, "aria-posinset": index + 1, "aria-setsize": nestedCells.length, className: "zen-data-grid__row zen-data-grid__row--nested", children: nestedRow }, `${mainRowId}_child_${index}`)))] }));
66
65
  };
67
66
  exports.DataGridRow = (0, react_1.memo)(Row);
@@ -15,8 +15,6 @@ const selectList_1 = require("../../selectList/selectList");
15
15
  const checkboxState_1 = require("../../checkbox/checkboxState");
16
16
  const selectableRowsColumnWrapper_1 = require("./columns/selectableRowsColumnWrapper");
17
17
  const useLanguage_1 = require("../../utils/localization/useLanguage");
18
- const useDragSelection_1 = require("../../table/selectable/useDragSelection");
19
- const getDragSelectionRows_1 = require("../../table/selectable/utils/getDragSelectionRows");
20
18
  injectString("cs", "Select all", "Vybrat v\u0161e");
21
19
  injectString("da-DK", "Select all", "V\xE6lg alle");
22
20
  injectString("de", "Select all", "Alle ausw\xE4hlen");
@@ -211,29 +209,13 @@ const withSelectableRows = DataGridComponent => {
211
209
  const selectMenuRef = (0, react_1.useRef)(null);
212
210
  const selections = (0, exports.getSelections)(selection);
213
211
  const allSelected = selection !== undefined && selection.allSelected;
214
- const isCheckboxVisible = (0, react_1.useCallback)(entity => {
215
- const condition = options.condition || options.checkboxVisible;
216
- return condition ? condition(entity) : true;
217
- }, [options.condition, options.checkboxVisible]);
218
- const isCheckboxDisabled = (0, react_1.useCallback)(entity => {
219
- if (options.checkboxDisabled) {
220
- return options.checkboxDisabled(entity);
221
- }
222
- if (options.selectionLimit !== undefined) {
223
- return !selections.has(entity.id) && selections.size >= options.selectionLimit;
224
- }
225
- return false;
226
- }, [options, selections]);
227
- const wrapper = (0, react_1.useMemo)(() => {
228
- var _a;
229
- return selectMode ? new selectableRowsColumnWrapper_1.SelectableRowsColumnWrapper(selections, {
230
- createTitle: options.createTitle,
231
- headerTitle: options.headerTitle,
232
- condition: options.condition || options.checkboxVisible,
233
- disabled: (_a = options.checkboxDisabled) !== null && _a !== void 0 ? _a : isCheckboxDisabled,
234
- header: options.selectionLimit === undefined && options.checkboxDisabled === undefined && options.checkboxVisible === undefined && options.condition === undefined || options.checkboxInHeader === true && !options.selectionLimit
235
- }, selectMenuRef) : null;
236
- }, [selectMode, selections, options.createTitle, options.headerTitle, options.condition, options.checkboxVisible, options.checkboxDisabled, options.selectionLimit, options.checkboxInHeader, isCheckboxDisabled]);
212
+ const wrapper = (0, react_1.useMemo)(() => selectMode ? new selectableRowsColumnWrapper_1.SelectableRowsColumnWrapper(selections, {
213
+ createTitle: options.createTitle,
214
+ headerTitle: options.headerTitle,
215
+ condition: options.condition || options.checkboxVisible,
216
+ disabled: options.checkboxDisabled ? options.checkboxDisabled : entity => options.selectionLimit !== undefined ? !selections.has(entity.id) && selections.size >= options.selectionLimit : false,
217
+ header: options.selectionLimit === undefined && options.checkboxDisabled === undefined && options.checkboxVisible === undefined && options.condition === undefined || options.checkboxInHeader === true && !options.selectionLimit
218
+ }, selectMenuRef) : null, [selectMode, selections, options.createTitle, options.headerTitle, options.condition, options.checkboxVisible, options.checkboxDisabled, options.selectionLimit, options.checkboxInHeader]);
237
219
  if (wrapper) {
238
220
  wrapper.selectionState = calculateSelectionState(entities, selections, allSelected, options);
239
221
  }
@@ -241,10 +223,9 @@ const withSelectableRows = DataGridComponent => {
241
223
  const newSelections = new Set(selections);
242
224
  entities.forEach(entity => {
243
225
  if (checked) {
244
- // Intentionally not isCheckboxDisabled: "select all" ignores the selection
245
- // limit, it only skips rows the consumer explicitly disabled.
226
+ const isVisible = options.condition ? options.condition(entity) : options.checkboxVisible ? options.checkboxVisible(entity) : true;
246
227
  const isEnabled = !options.checkboxDisabled || !options.checkboxDisabled(entity);
247
- if (isCheckboxVisible(entity) && isEnabled) {
228
+ if (isVisible && isEnabled) {
248
229
  newSelections.add(entity.id);
249
230
  }
250
231
  return;
@@ -257,49 +238,8 @@ const withSelectableRows = DataGridComponent => {
257
238
  allSelected: newState === checkboxColumnWrapper_1.SelectionState.All,
258
239
  turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
259
240
  });
260
- }, [selections, entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll, isCheckboxVisible]);
261
- const {
262
- rows: dragRows,
263
- entityById
264
- } = (0, react_1.useMemo)(() => (0, getDragSelectionRows_1.getDragSelectionRows)(entities), [entities]);
265
- const isRowSelectable = (0, react_1.useCallback)(row => {
266
- const entity = entityById.get(row.id);
267
- return !!entity && isCheckboxVisible(entity) && !isCheckboxDisabled(entity);
268
- }, [entityById, isCheckboxVisible, isCheckboxDisabled]);
269
- // "Select all" is held as a flag rather than a list of ids, so materialise the page before
270
- // a range starts editing it — otherwise the range would be applied to an empty selection.
271
- const getBaseSelection = (0, react_1.useCallback)(() => allSelected ? new Set(entities.map(entity => entity.id)) : new Set(selections), [allSelected, entities, selections]);
272
- const onBatchSelect = (0, react_1.useCallback)((rangeIds, select, base) => {
273
- const result = new Set(base);
274
- const limit = options.selectionLimit;
275
- for (const id of rangeIds) {
276
- if (select) {
277
- if (limit !== undefined && result.size >= limit) {
278
- break;
279
- }
280
- result.add(id);
281
- } else {
282
- result.delete(id);
283
- }
284
- }
285
- const newState = calculateSelectionState(entities, result, false, options);
286
- onSelect({
287
- selected: [...result],
288
- allSelected: newState === checkboxColumnWrapper_1.SelectionState.All,
289
- turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
290
- });
291
- }, [entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
292
- const {
293
- onCheckboxMouseDown,
294
- suppressNextChangeRef
295
- } = (0, useDragSelection_1.useDragSelection)(dragRows, props.ref, onBatchSelect, getBaseSelection, isRowSelectable, selectMode);
241
+ }, [selections, entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
296
242
  const onSelectListener = (0, react_1.useCallback)(([id, checked]) => {
297
- // A drag or shift-click has already emitted the whole range; swallow the click that
298
- // ends it so the row it landed on is not toggled back.
299
- if (suppressNextChangeRef.current) {
300
- suppressNextChangeRef.current = false;
301
- return;
302
- }
303
243
  if (allSelected) {
304
244
  const newSelection = new Set(entities.map(entity => entity.id));
305
245
  newSelection.delete(id);
@@ -321,7 +261,7 @@ const withSelectableRows = DataGridComponent => {
321
261
  allSelected: newState === checkboxColumnWrapper_1.SelectionState.All,
322
262
  turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
323
263
  });
324
- }, [entities, selections, allSelected, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll, suppressNextChangeRef]);
264
+ }, [entities, selections, allSelected, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
325
265
  const onSelectAll = (0, react_1.useCallback)(([checked]) => {
326
266
  if (checked && ((selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll) || options.turnOffSelectAll)) {
327
267
  selectAll(true);
@@ -370,11 +310,10 @@ const withSelectableRows = DataGridComponent => {
370
310
  wrapper.attach("change", onSelectListener);
371
311
  wrapper.attach("change-all", onSelectAll);
372
312
  wrapper.attach("toggle", onTriggerClick);
373
- wrapper.attach("mousedown", ([id, checked, e]) => onCheckboxMouseDown(id, checked, e));
374
313
  return () => {
375
314
  wrapper.detach();
376
315
  };
377
- }, [wrapper, onSelectListener, onSelectAll, onTriggerClick, onCheckboxMouseDown]);
316
+ }, [wrapper, onSelectListener, onSelectAll, onTriggerClick]);
378
317
  const listColumns = (0, react_1.useMemo)(() => {
379
318
  const newColumns = columns.map(c => Object.assign({}, c));
380
319
  // Remove CheckboxColumnWrappers from wrappers list
@@ -8,12 +8,3 @@ export interface ISelectionValue {
8
8
  all: boolean;
9
9
  selected: string[];
10
10
  }
11
- /**
12
- * One checkbox row in the order it is rendered. Expanded nested rows are part of this list,
13
- * directly after their parent, so a drag or shift-click range can span nesting levels the
14
- * same way it spans sibling rows.
15
- */
16
- export interface IDragSelectionRow {
17
- id: string;
18
- isNested: boolean;
19
- }
@@ -1,4 +1,4 @@
1
- import { ReactNode, RefObject } from "react";
1
+ import { ReactNode } 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, gridRef?: RefObject<HTMLElement | null>, expandedRows?: string[]) => {
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) => {
37
37
  selectableColumns: IListColumn<T, N>[];
38
38
  selectableFeedWrapper: (primaryData: ReactNode, secondaryData: ReactNode, entity: T | N, isNested: boolean) => [ReactNode, ReactNode];
39
39
  };
@@ -84,8 +84,6 @@ 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");
89
87
  const getEmptySelection = () => ({
90
88
  all: false,
91
89
  selected: []
@@ -94,7 +92,7 @@ exports.getEmptySelection = getEmptySelection;
94
92
  exports.SelectableWrapperName = "Selectable";
95
93
  // Infinite scroll has no pages, so the header checkbox always means "select all" (never current page).
96
94
  const resolveCheckboxEmitsCurrentPage = (isInfinite, checkboxSelectsCurrentPage, turnOffSelectAll) => isInfinite ? false : checkboxSelectsCurrentPage !== null && checkboxSelectsCurrentPage !== void 0 ? checkboxSelectsCurrentPage : turnOffSelectAll;
97
- const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false, gridRef, expandedRows) => {
95
+ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false) => {
98
96
  var _a;
99
97
  const {
100
98
  translate
@@ -164,47 +162,6 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
164
162
  selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
165
163
  setSelectMode(newValue.all || newValue.selected.length > 0);
166
164
  }, [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]);
208
165
  const onChangeSelectionState = (0, react_1.useCallback)(newState => {
209
166
  var _a, _b;
210
167
  if (newState === interfaces_1.SelectionState.All) {
@@ -282,8 +239,7 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
282
239
  indeterminate: checked.indeterminate,
283
240
  disabled: isDisable,
284
241
  label: checkboxTitle(entity),
285
- onChange: onCheckboxChange,
286
- onMouseDown: isDisable ? undefined : onCheckboxMouseDown,
242
+ onChange: onSelectListener,
287
243
  children: (0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell.Content, {
288
244
  children: value
289
245
  })
@@ -329,7 +285,7 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
329
285
  return cell;
330
286
  }
331
287
  };
332
- }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onCheckboxChange, onCheckboxMouseDown, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
288
+ }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onSelectListener, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
333
289
  const selectableFeedWrapper = (0, react_1.useCallback)((primaryData, secondaryData, entity, isNested) => {
334
290
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
335
291
  if (!entity) {
@@ -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, gridRef, expanded);
291
+ } = (0, useSelectableRows_1.useSelectableRows)(nestedColumns, entities, isMobile, selectMode, setMobileSelectMode, isLoading ? undefined : selectable, isInfinite);
292
292
  const {
293
293
  sortableColumns,
294
294
  feedSortControl
@@ -1,4 +1,4 @@
1
- import { FC, MouseEvent as ReactMouseEvent, PropsWithChildren, ReactElement } from "react";
1
+ import { FC, PropsWithChildren, ReactElement } from "react";
2
2
  import { IZenIdComponentProps } from "../../../commonHelpers/zenComponent";
3
3
  import "./checkboxColumn.less";
4
4
  interface ICheckboxCellProps extends IZenIdComponentProps {
@@ -8,7 +8,6 @@ interface ICheckboxCellProps extends IZenIdComponentProps {
8
8
  disabled?: boolean;
9
9
  children?: ReactElement<typeof CheckboxCell.Content>;
10
10
  onChange?: (id: string, checked: boolean) => void;
11
- onMouseDown?: (id: string, checked: boolean, e: ReactMouseEvent) => void;
12
11
  }
13
12
  interface ICheckboxCell extends FC<ICheckboxCellProps> {
14
13
  Content: FC<PropsWithChildren>;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Checkbox } from "../../../checkbox/checkbox";
3
3
  import { classNames } from "../../../commonHelpers/classNames/classNames";
4
- export const CheckboxCell = ({ id, checked, indeterminate, label, disabled, className, onChange, onMouseDown, children }) => (_jsxs("div", { className: classNames(["zen-checkbox-column", className || ""]), onMouseDown: onMouseDown ? e => onMouseDown(id, checked, e) : undefined, children: [_jsx(Checkbox, { className: "zen-checkbox-column__checkbox", checked: checked, indeterminate: indeterminate, disabled: disabled, title: label, onChange: e => onChange && onChange(id, e.target.checked), wrapped: true }), children] }));
4
+ export const CheckboxCell = ({ id, checked, indeterminate, label, disabled, className, onChange, children }) => (_jsxs("div", { className: classNames(["zen-checkbox-column", className || ""]), children: [_jsx(Checkbox, { className: "zen-checkbox-column__checkbox", checked: checked, indeterminate: indeterminate, disabled: disabled, title: label, onChange: e => onChange && onChange(id, e.target.checked), wrapped: true }), children] }));
5
5
  CheckboxCell.Content = function content({ children }) {
6
6
  return _jsx("div", { className: "zen-checkbox-column__content", children: children });
7
7
  };
@@ -1,4 +1,4 @@
1
- import { MouseEvent as ReactMouseEvent, ReactNode, RefObject } from "react";
1
+ import { ReactNode, RefObject } from "react";
2
2
  import { IListColumnWrapper } from "../../listColumn";
3
3
  import "./checkboxColumn.less";
4
4
  import { SimpleEventHandler } from "../../../commonHelpers/simpleEventHandler";
@@ -17,8 +17,7 @@ export interface ICheckboxColumnWrapper<T extends object> extends IListColumnWra
17
17
  attach(event: "toggle", handler: (state: [Event, HTMLButtonElement]) => void): this;
18
18
  attach(event: "change", handler: (state: [string, boolean]) => void): this;
19
19
  attach(event: "change-all", handler: (state: [boolean]) => void): this;
20
- attach(event: "mousedown", handler: (state: [string, boolean, ReactMouseEvent]) => void): this;
21
- detach(event: "change" | "toggle" | "change-all" | "mousedown", handler?: (state: unknown) => void): this;
20
+ detach(event: "change" | "toggle" | "change-all", handler?: (state: unknown) => void): this;
22
21
  }
23
22
  export declare enum SelectionState {
24
23
  All = 0,
@@ -35,7 +34,6 @@ export declare class CheckboxColumnWrapper<T extends IEntityWithId> extends Simp
35
34
  private state;
36
35
  private readonly actionsClickHandler;
37
36
  private readonly changeHandler;
38
- private readonly mouseDownHandler;
39
37
  private readonly changeHandlerAll;
40
38
  constructor(selections: Set<string>, options: ICheckboxColumnOptions<T>, menuTriggerRef: RefObject<HTMLButtonElement | null>);
41
39
  get selectionState(): SelectionState;
@@ -64,15 +64,6 @@ export class CheckboxColumnWrapper extends SimpleEventHandler {
64
64
  this.fire("change", [id, checked]);
65
65
  }
66
66
  });
67
- // Only fired for enabled checkboxes, so a disabled row can never become a drag anchor.
68
- Object.defineProperty(this, "mouseDownHandler", {
69
- enumerable: true,
70
- configurable: true,
71
- writable: true,
72
- value: (id, checked, e) => {
73
- this.fire("mousedown", [id, checked, e]);
74
- }
75
- });
76
67
  Object.defineProperty(this, "changeHandlerAll", {
77
68
  enumerable: true,
78
69
  configurable: true,
@@ -98,7 +89,7 @@ export class CheckboxColumnWrapper extends SimpleEventHandler {
98
89
  }
99
90
  const allowed = this.condition(entity);
100
91
  const isDisable = this.disabled ? this.disabled(entity) : this.state === SelectionState.All;
101
- const cell = (_jsx(CheckboxCell, { id: entity.id, className: allowed ? "" : "zen-checkbox-column--no-checkbox", checked: this.state === SelectionState.All || this.selections.has(entity.id), indeterminate: false, disabled: isDisable, label: this.options.createTitle(entity), onChange: this.changeHandler, onMouseDown: isDisable ? undefined : this.mouseDownHandler, children: _jsx(CheckboxCell.Content, { children: value }) }));
92
+ const cell = (_jsx(CheckboxCell, { id: entity.id, className: allowed ? "" : "zen-checkbox-column--no-checkbox", checked: this.state === SelectionState.All || this.selections.has(entity.id), indeterminate: false, disabled: isDisable, label: this.options.createTitle(entity), onChange: this.changeHandler, children: _jsx(CheckboxCell.Content, { children: value }) }));
102
93
  return cell;
103
94
  }
104
95
  renderHeader(title) {
@@ -57,8 +57,7 @@ const Row = ({ id, entity, columns, visibleRows, flexibleColumnWidth, isLastRow,
57
57
  return acc;
58
58
  }, { cells: [], colspan: 0 }).cells, [columns, expanded, getCellParams, isVisible, onExpandedChange, isActive, active, onClick]);
59
59
  const cells = useMemo(() => renderCells(entity, false), [entity, renderCells]);
60
- const nestedEntities = useMemo(() => (expanded && entity.children ? entity.children : []), [entity.children, expanded]);
61
- const nestedCells = useMemo(() => nestedEntities.map(nestedEntity => renderCells(nestedEntity, true)), [nestedEntities, renderCells]);
62
- return (_jsxs(_Fragment, { children: [_jsx("tr", { "data-row-id": id, id: mainRowId, role: "row", "aria-level": isTreeGrid ? 1 : undefined, "aria-posinset": isTreeGrid ? ariaPosinset : undefined, "aria-setsize": isTreeGrid ? ariaSetsize : undefined, "aria-expanded": isTreeGrid ? expanded : undefined, className: classNames(["zen-data-grid__row", className || "", isLastRow ? "zen-data-grid__row--last" : ""]), children: cells }, mainRowId), nestedCells.map((nestedRow, index) => (_jsx("tr", { "data-row-id": nestedEntities[index].id, id: `${mainRowId}_child_${index}`, role: "row", "aria-level": 2, "aria-posinset": index + 1, "aria-setsize": nestedCells.length, className: "zen-data-grid__row zen-data-grid__row--nested", children: nestedRow }, `${mainRowId}_child_${index}`)))] }));
60
+ const nestedCells = useMemo(() => (expanded && entity.children ? entity.children : []).map(nestedEntity => renderCells(nestedEntity, true)), [entity.children, expanded, renderCells]);
61
+ return (_jsxs(_Fragment, { children: [_jsx("tr", { "data-row-id": id, id: mainRowId, role: "row", "aria-level": isTreeGrid ? 1 : undefined, "aria-posinset": isTreeGrid ? ariaPosinset : undefined, "aria-setsize": isTreeGrid ? ariaSetsize : undefined, "aria-expanded": isTreeGrid ? expanded : undefined, className: classNames(["zen-data-grid__row", className || "", isLastRow ? "zen-data-grid__row--last" : ""]), children: cells }, mainRowId), nestedCells.map((nestedRow, index) => (_jsx("tr", { id: `${mainRowId}_child_${index}`, role: "row", "aria-level": 2, "aria-posinset": index + 1, "aria-setsize": nestedCells.length, className: "zen-data-grid__row zen-data-grid__row--nested", children: nestedRow }, `${mainRowId}_child_${index}`)))] }));
63
62
  };
64
63
  export const DataGridRow = memo(Row);
@@ -7,8 +7,6 @@ import { SelectList } from "../../selectList/selectList";
7
7
  import { CheckboxState } from "../../checkbox/checkboxState";
8
8
  import { SelectableRowsColumnWrapper } from "./columns/selectableRowsColumnWrapper";
9
9
  import { useLanguage } from "../../utils/localization/useLanguage";
10
- import { useDragSelection } from "../../table/selectable/useDragSelection";
11
- import { getDragSelectionRows } from "../../table/selectable/utils/getDragSelectionRows";
12
10
  injectString("cs", "Select all", "Vybrat v\u0161e");
13
11
  injectString("da-DK", "Select all", "V\xE6lg alle");
14
12
  injectString("de", "Select all", "Alle ausw\xE4hlen");
@@ -202,29 +200,13 @@ export const withSelectableRows = DataGridComponent => {
202
200
  const selectMenuRef = useRef(null);
203
201
  const selections = getSelections(selection);
204
202
  const allSelected = selection !== undefined && selection.allSelected;
205
- const isCheckboxVisible = useCallback(entity => {
206
- const condition = options.condition || options.checkboxVisible;
207
- return condition ? condition(entity) : true;
208
- }, [options.condition, options.checkboxVisible]);
209
- const isCheckboxDisabled = useCallback(entity => {
210
- if (options.checkboxDisabled) {
211
- return options.checkboxDisabled(entity);
212
- }
213
- if (options.selectionLimit !== undefined) {
214
- return !selections.has(entity.id) && selections.size >= options.selectionLimit;
215
- }
216
- return false;
217
- }, [options, selections]);
218
- const wrapper = useMemo(() => {
219
- var _a;
220
- return selectMode ? new SelectableRowsColumnWrapper(selections, {
221
- createTitle: options.createTitle,
222
- headerTitle: options.headerTitle,
223
- condition: options.condition || options.checkboxVisible,
224
- disabled: (_a = options.checkboxDisabled) !== null && _a !== void 0 ? _a : isCheckboxDisabled,
225
- header: options.selectionLimit === undefined && options.checkboxDisabled === undefined && options.checkboxVisible === undefined && options.condition === undefined || options.checkboxInHeader === true && !options.selectionLimit
226
- }, selectMenuRef) : null;
227
- }, [selectMode, selections, options.createTitle, options.headerTitle, options.condition, options.checkboxVisible, options.checkboxDisabled, options.selectionLimit, options.checkboxInHeader, isCheckboxDisabled]);
203
+ const wrapper = useMemo(() => selectMode ? new SelectableRowsColumnWrapper(selections, {
204
+ createTitle: options.createTitle,
205
+ headerTitle: options.headerTitle,
206
+ condition: options.condition || options.checkboxVisible,
207
+ disabled: options.checkboxDisabled ? options.checkboxDisabled : entity => options.selectionLimit !== undefined ? !selections.has(entity.id) && selections.size >= options.selectionLimit : false,
208
+ header: options.selectionLimit === undefined && options.checkboxDisabled === undefined && options.checkboxVisible === undefined && options.condition === undefined || options.checkboxInHeader === true && !options.selectionLimit
209
+ }, selectMenuRef) : null, [selectMode, selections, options.createTitle, options.headerTitle, options.condition, options.checkboxVisible, options.checkboxDisabled, options.selectionLimit, options.checkboxInHeader]);
228
210
  if (wrapper) {
229
211
  wrapper.selectionState = calculateSelectionState(entities, selections, allSelected, options);
230
212
  }
@@ -232,10 +214,9 @@ export const withSelectableRows = DataGridComponent => {
232
214
  const newSelections = new Set(selections);
233
215
  entities.forEach(entity => {
234
216
  if (checked) {
235
- // Intentionally not isCheckboxDisabled: "select all" ignores the selection
236
- // limit, it only skips rows the consumer explicitly disabled.
217
+ const isVisible = options.condition ? options.condition(entity) : options.checkboxVisible ? options.checkboxVisible(entity) : true;
237
218
  const isEnabled = !options.checkboxDisabled || !options.checkboxDisabled(entity);
238
- if (isCheckboxVisible(entity) && isEnabled) {
219
+ if (isVisible && isEnabled) {
239
220
  newSelections.add(entity.id);
240
221
  }
241
222
  return;
@@ -248,49 +229,8 @@ export const withSelectableRows = DataGridComponent => {
248
229
  allSelected: newState === SelectionState.All,
249
230
  turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
250
231
  });
251
- }, [selections, entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll, isCheckboxVisible]);
252
- const {
253
- rows: dragRows,
254
- entityById
255
- } = useMemo(() => getDragSelectionRows(entities), [entities]);
256
- const isRowSelectable = useCallback(row => {
257
- const entity = entityById.get(row.id);
258
- return !!entity && isCheckboxVisible(entity) && !isCheckboxDisabled(entity);
259
- }, [entityById, isCheckboxVisible, isCheckboxDisabled]);
260
- // "Select all" is held as a flag rather than a list of ids, so materialise the page before
261
- // a range starts editing it — otherwise the range would be applied to an empty selection.
262
- const getBaseSelection = useCallback(() => allSelected ? new Set(entities.map(entity => entity.id)) : new Set(selections), [allSelected, entities, selections]);
263
- const onBatchSelect = useCallback((rangeIds, select, base) => {
264
- const result = new Set(base);
265
- const limit = options.selectionLimit;
266
- for (const id of rangeIds) {
267
- if (select) {
268
- if (limit !== undefined && result.size >= limit) {
269
- break;
270
- }
271
- result.add(id);
272
- } else {
273
- result.delete(id);
274
- }
275
- }
276
- const newState = calculateSelectionState(entities, result, false, options);
277
- onSelect({
278
- selected: [...result],
279
- allSelected: newState === SelectionState.All,
280
- turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
281
- });
282
- }, [entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
283
- const {
284
- onCheckboxMouseDown,
285
- suppressNextChangeRef
286
- } = useDragSelection(dragRows, props.ref, onBatchSelect, getBaseSelection, isRowSelectable, selectMode);
232
+ }, [selections, entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
287
233
  const onSelectListener = useCallback(([id, checked]) => {
288
- // A drag or shift-click has already emitted the whole range; swallow the click that
289
- // ends it so the row it landed on is not toggled back.
290
- if (suppressNextChangeRef.current) {
291
- suppressNextChangeRef.current = false;
292
- return;
293
- }
294
234
  if (allSelected) {
295
235
  const newSelection = new Set(entities.map(entity => entity.id));
296
236
  newSelection.delete(id);
@@ -312,7 +252,7 @@ export const withSelectableRows = DataGridComponent => {
312
252
  allSelected: newState === SelectionState.All,
313
253
  turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
314
254
  });
315
- }, [entities, selections, allSelected, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll, suppressNextChangeRef]);
255
+ }, [entities, selections, allSelected, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
316
256
  const onSelectAll = useCallback(([checked]) => {
317
257
  if (checked && ((selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll) || options.turnOffSelectAll)) {
318
258
  selectAll(true);
@@ -361,11 +301,10 @@ export const withSelectableRows = DataGridComponent => {
361
301
  wrapper.attach("change", onSelectListener);
362
302
  wrapper.attach("change-all", onSelectAll);
363
303
  wrapper.attach("toggle", onTriggerClick);
364
- wrapper.attach("mousedown", ([id, checked, e]) => onCheckboxMouseDown(id, checked, e));
365
304
  return () => {
366
305
  wrapper.detach();
367
306
  };
368
- }, [wrapper, onSelectListener, onSelectAll, onTriggerClick, onCheckboxMouseDown]);
307
+ }, [wrapper, onSelectListener, onSelectAll, onTriggerClick]);
369
308
  const listColumns = useMemo(() => {
370
309
  const newColumns = columns.map(c => Object.assign({}, c));
371
310
  // Remove CheckboxColumnWrappers from wrappers list
@@ -8,12 +8,3 @@ export interface ISelectionValue {
8
8
  all: boolean;
9
9
  selected: string[];
10
10
  }
11
- /**
12
- * One checkbox row in the order it is rendered. Expanded nested rows are part of this list,
13
- * directly after their parent, so a drag or shift-click range can span nesting levels the
14
- * same way it spans sibling rows.
15
- */
16
- export interface IDragSelectionRow {
17
- id: string;
18
- isNested: boolean;
19
- }
@@ -1,4 +1,4 @@
1
- import { ReactNode, RefObject } from "react";
1
+ import { ReactNode } 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, gridRef?: RefObject<HTMLElement | null>, expandedRows?: string[]) => {
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) => {
37
37
  selectableColumns: IListColumn<T, N>[];
38
38
  selectableFeedWrapper: (primaryData: ReactNode, secondaryData: ReactNode, entity: T | N, isNested: boolean) => [ReactNode, ReactNode];
39
39
  };
@@ -10,8 +10,6 @@ import { useLanguage } from "../../utils/localization/useLanguage";
10
10
  import { checkRow } from "./utils/checkRow";
11
11
  import { isRowChecked } from "./utils/isRowChecked";
12
12
  import { getCurrentPageSelection } from "./utils/getCurrentPageSelection";
13
- import { useDragSelection } from "./useDragSelection";
14
- import { getDragSelectionRows } from "./utils/getDragSelectionRows";
15
13
  injectString("cs", "Select all", "Vybrat v\u0161e");
16
14
  injectString("da-DK", "Select all", "V\xE6lg alle");
17
15
  injectString("de", "Select all", "Alle ausw\xE4hlen");
@@ -85,7 +83,7 @@ export const getEmptySelection = () => ({
85
83
  export const SelectableWrapperName = "Selectable";
86
84
  // Infinite scroll has no pages, so the header checkbox always means "select all" (never current page).
87
85
  const resolveCheckboxEmitsCurrentPage = (isInfinite, checkboxSelectsCurrentPage, turnOffSelectAll) => isInfinite ? false : checkboxSelectsCurrentPage !== null && checkboxSelectsCurrentPage !== void 0 ? checkboxSelectsCurrentPage : turnOffSelectAll;
88
- export const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false, gridRef, expandedRows) => {
86
+ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false) => {
89
87
  var _a;
90
88
  const {
91
89
  translate
@@ -155,47 +153,6 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
155
153
  selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
156
154
  setSelectMode(newValue.all || newValue.selected.length > 0);
157
155
  }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, setState, getNewSelection]);
158
- const onBatchSelect = useCallback((rangeIds, select, base) => {
159
- var _a;
160
- const result = new Set(base);
161
- const limit = selectable === null || selectable === void 0 ? void 0 : selectable.selectionLimit;
162
- for (const id of rangeIds) {
163
- if (select && limit !== undefined && result.size >= limit) {
164
- break;
165
- }
166
- checkRow(result, selectable, entities, id, select);
167
- }
168
- const newState = 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);
169
- const newValue = {
170
- selected: [...result],
171
- all: newState === SelectionState.All
172
- };
173
- setState(newState);
174
- selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
175
- setSelectMode(newValue.all || newValue.selected.length > 0);
176
- }, [entities, selectable, checkboxVisible, checkboxDisabled, setSelectMode]);
177
- // Deliberately independent of the current selection, so the drag anchor survives the
178
- // selection changes a drag itself produces.
179
- const {
180
- rows: dragRows,
181
- entityById
182
- } = useMemo(() => getDragSelectionRows(entities, expandedRows), [entities, expandedRows]);
183
- const isSelectable = useCallback(row => {
184
- const entity = entityById.get(row.id);
185
- return !!entity && checkboxVisible(entity, row.isNested) && !checkboxDisabled(entity, row.isNested);
186
- }, [entityById, checkboxVisible, checkboxDisabled]);
187
- const getBaseSelection = useCallback(() => state === SelectionState.All ? getCurrentPageSelection(entities, selectable) : new Set(selections), [state, entities, selectable, selections]);
188
- const {
189
- onCheckboxMouseDown,
190
- suppressNextChangeRef
191
- } = useDragSelection(dragRows, gridRef, onBatchSelect, getBaseSelection, isSelectable, !!selectable);
192
- const onCheckboxChange = useCallback((id, checked) => {
193
- if (suppressNextChangeRef.current) {
194
- suppressNextChangeRef.current = false;
195
- return;
196
- }
197
- onSelectListener(id, checked);
198
- }, [onSelectListener, suppressNextChangeRef]);
199
156
  const onChangeSelectionState = useCallback(newState => {
200
157
  var _a, _b;
201
158
  if (newState === SelectionState.All) {
@@ -273,8 +230,7 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
273
230
  indeterminate: checked.indeterminate,
274
231
  disabled: isDisable,
275
232
  label: checkboxTitle(entity),
276
- onChange: onCheckboxChange,
277
- onMouseDown: isDisable ? undefined : onCheckboxMouseDown,
233
+ onChange: onSelectListener,
278
234
  children: _jsx(CheckboxCell.Content, {
279
235
  children: value
280
236
  })
@@ -320,7 +276,7 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
320
276
  return cell;
321
277
  }
322
278
  };
323
- }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onCheckboxChange, onCheckboxMouseDown, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
279
+ }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onSelectListener, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
324
280
  const selectableFeedWrapper = useCallback((primaryData, secondaryData, entity, isNested) => {
325
281
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
326
282
  if (!entity) {
@@ -238,7 +238,7 @@ const TableInner = ({
238
238
  const {
239
239
  selectableColumns,
240
240
  selectableFeedWrapper
241
- } = useSelectableRows(nestedColumns, entities, isMobile, selectMode, setMobileSelectMode, isLoading ? undefined : selectable, isInfinite, gridRef, expanded);
241
+ } = useSelectableRows(nestedColumns, entities, isMobile, selectMode, setMobileSelectMode, isLoading ? undefined : selectable, isInfinite);
242
242
  const {
243
243
  sortableColumns,
244
244
  feedSortControl
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geotab/zenith",
3
- "version": "3.16.0-beta.3",
3
+ "version": "3.16.0-beta.4",
4
4
  "description": "Zenith components library on React",
5
5
  "main": "dist/index.js",
6
6
  "types": "esm/index.d.ts",
@@ -1,10 +0,0 @@
1
- import { MouseEvent as ReactMouseEvent, RefObject } from "react";
2
- import { IDragSelectionRow } from "./interfaces";
3
- /**
4
- * @param rows every checkbox row in render order, expanded nested rows included, so ranges can
5
- * span nesting levels.
6
- */
7
- export declare const useDragSelection: (rows: IDragSelectionRow[], gridRef: RefObject<HTMLElement | null> | undefined, onBatchSelect: (rangeIds: string[], select: boolean, base: Set<string>) => void, getBaseSelection: () => Set<string>, isSelectable: (row: IDragSelectionRow) => boolean, isEnabled: boolean) => {
8
- onCheckboxMouseDown: (id: string, checked: boolean, e: ReactMouseEvent) => void;
9
- suppressNextChangeRef: RefObject<boolean>;
10
- };
@@ -1,139 +0,0 @@
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,15 +0,0 @@
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>;
@@ -1,28 +0,0 @@
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;
@@ -1,2 +0,0 @@
1
- import { IDragSelectionRow } from "../interfaces";
2
- export declare const getRangeIds: (rows: IDragSelectionRow[], fromId: string, toId: string, isSelectable: (row: IDragSelectionRow) => boolean) => string[];
@@ -1,21 +0,0 @@
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;
@@ -1,10 +0,0 @@
1
- import { MouseEvent as ReactMouseEvent, RefObject } from "react";
2
- import { IDragSelectionRow } from "./interfaces";
3
- /**
4
- * @param rows every checkbox row in render order, expanded nested rows included, so ranges can
5
- * span nesting levels.
6
- */
7
- export declare const useDragSelection: (rows: IDragSelectionRow[], gridRef: RefObject<HTMLElement | null> | undefined, onBatchSelect: (rangeIds: string[], select: boolean, base: Set<string>) => void, getBaseSelection: () => Set<string>, isSelectable: (row: IDragSelectionRow) => boolean, isEnabled: boolean) => {
8
- onCheckboxMouseDown: (id: string, checked: boolean, e: ReactMouseEvent) => void;
9
- suppressNextChangeRef: RefObject<boolean>;
10
- };
@@ -1,135 +0,0 @@
1
- import { useCallback, useEffect, useRef } from "react";
2
- import { zen } from "../../utils/zen";
3
- import { getRangeIds } from "./utils/getRangeIds";
4
- const DRAG_CLASS = "zen-not-selectable";
5
- /**
6
- * @param rows every checkbox row in render order, expanded nested rows included, so ranges can
7
- * span nesting levels.
8
- */
9
- export const useDragSelection = (rows, gridRef, onBatchSelect, getBaseSelection, isSelectable, isEnabled) => {
10
- const rowsRef = useRef(rows);
11
- rowsRef.current = rows;
12
- const getBaseSelectionRef = useRef(getBaseSelection);
13
- getBaseSelectionRef.current = getBaseSelection;
14
- const onBatchSelectRef = useRef(onBatchSelect);
15
- onBatchSelectRef.current = onBatchSelect;
16
- const isSelectableRef = useRef(isSelectable);
17
- isSelectableRef.current = isSelectable;
18
- const isEnabledRef = useRef(isEnabled);
19
- isEnabledRef.current = isEnabled;
20
- const anchorIdRef = useRef(null);
21
- const anchorSelectRef = useRef(true);
22
- const baseSelectedRef = useRef(new Set());
23
- const isDraggingRef = useRef(false);
24
- const movedRef = useRef(false);
25
- const lastResultKeyRef = useRef("");
26
- const lastPointRef = useRef(null);
27
- const suppressNextChangeRef = useRef(false);
28
- const attachedGridElementRef = useRef(null);
29
- const emitRange = useCallback((currentId) => {
30
- const anchorId = anchorIdRef.current;
31
- if (anchorId === null) {
32
- return;
33
- }
34
- const range = getRangeIds(rowsRef.current, anchorId, currentId, isSelectableRef.current);
35
- if (range.length === 0) {
36
- return;
37
- }
38
- const select = anchorSelectRef.current;
39
- const key = `${select}|${range.join(",")}`;
40
- if (key === lastResultKeyRef.current) {
41
- return;
42
- }
43
- lastResultKeyRef.current = key;
44
- onBatchSelectRef.current(range, select, baseSelectedRef.current);
45
- }, []);
46
- const extend = useCallback((x, y) => {
47
- var _a, _b;
48
- lastPointRef.current = { x, y };
49
- const row = (_b = (_a = zen.document) === null || _a === void 0 ? void 0 : _a.elementFromPoint(x, y)) === null || _b === void 0 ? void 0 : _b.closest("[data-row-id]");
50
- const currentId = row === null || row === void 0 ? void 0 : row.getAttribute("data-row-id");
51
- if (!currentId) {
52
- return;
53
- }
54
- if (currentId !== anchorIdRef.current) {
55
- movedRef.current = true;
56
- }
57
- if (!movedRef.current) {
58
- return;
59
- }
60
- emitRange(currentId);
61
- }, [emitRange]);
62
- const onMouseMove = useCallback((e) => {
63
- extend(e.clientX, e.clientY);
64
- }, [extend]);
65
- const onScroll = useCallback(() => {
66
- const point = lastPointRef.current;
67
- if (point) {
68
- extend(point.x, point.y);
69
- }
70
- }, [extend]);
71
- const endDrag = useCallback(() => {
72
- var _a, _b, _c, _d;
73
- if (!isDraggingRef.current) {
74
- return;
75
- }
76
- isDraggingRef.current = false;
77
- if (movedRef.current) {
78
- suppressNextChangeRef.current = true;
79
- }
80
- (_a = zen.document) === null || _a === void 0 ? void 0 : _a.removeEventListener("mousemove", onMouseMove);
81
- (_b = zen.document) === null || _b === void 0 ? void 0 : _b.removeEventListener("mouseup", endDrag);
82
- (_c = attachedGridElementRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener("scroll", onScroll);
83
- (_d = attachedGridElementRef.current) === null || _d === void 0 ? void 0 : _d.classList.remove(DRAG_CLASS);
84
- attachedGridElementRef.current = null;
85
- }, [onMouseMove, onScroll]); // eslint-disable-line react-hooks/exhaustive-deps
86
- const onCheckboxMouseDown = useCallback((id, checked, e) => {
87
- var _a, _b, _c, _d, _e;
88
- // Right-click between drag-end and the trailing click must not clear suppression.
89
- if (e.button === 0) {
90
- suppressNextChangeRef.current = false;
91
- }
92
- if (!isEnabledRef.current || e.button !== 0) {
93
- return;
94
- }
95
- if (e.shiftKey && anchorIdRef.current !== null) {
96
- e.preventDefault();
97
- const anchorId = anchorIdRef.current;
98
- const anchorInList = rowsRef.current.some(row => row.id === anchorId);
99
- if (!anchorInList) {
100
- // The anchor is no longer rendered (e.g. its parent was collapsed, or the list was
101
- // re-filtered/paginated since). Drop the stale anchor and let the target row's own
102
- // onChange fire normally, rather than swallowing it as a silent no-op.
103
- anchorIdRef.current = null;
104
- return;
105
- }
106
- // Gmail-style: every shift-click re-applies the range to the selection captured when
107
- // the anchor was clicked, so moving the target closer to the anchor deselects the rows
108
- // that dropped out of the range. Shift-clicking the anchor itself collapses the range
109
- // to nothing, restoring that captured selection — the anchor included.
110
- const range = id === anchorId ? [] : getRangeIds(rowsRef.current, anchorId, id, isSelectableRef.current);
111
- // Suppress even when the range is empty to prevent the anchor from double-toggling
112
- // on a same-row shift-click.
113
- suppressNextChangeRef.current = true;
114
- onBatchSelectRef.current(range, anchorSelectRef.current, baseSelectedRef.current);
115
- return;
116
- }
117
- anchorIdRef.current = id;
118
- anchorSelectRef.current = !checked;
119
- baseSelectedRef.current = getBaseSelectionRef.current();
120
- isDraggingRef.current = true;
121
- movedRef.current = false;
122
- lastResultKeyRef.current = "";
123
- lastPointRef.current = { x: e.clientX, y: e.clientY };
124
- attachedGridElementRef.current = (_a = gridRef === null || gridRef === void 0 ? void 0 : gridRef.current) !== null && _a !== void 0 ? _a : null;
125
- (_b = attachedGridElementRef.current) === null || _b === void 0 ? void 0 : _b.classList.add(DRAG_CLASS);
126
- (_c = zen.document) === null || _c === void 0 ? void 0 : _c.addEventListener("mousemove", onMouseMove);
127
- (_d = zen.document) === null || _d === void 0 ? void 0 : _d.addEventListener("mouseup", endDrag);
128
- (_e = attachedGridElementRef.current) === null || _e === void 0 ? void 0 : _e.addEventListener("scroll", onScroll);
129
- }, [gridRef, onMouseMove, onScroll, endDrag]);
130
- useEffect(() => {
131
- anchorIdRef.current = null;
132
- }, [rows]);
133
- useEffect(() => endDrag, [endDrag]);
134
- return { onCheckboxMouseDown, suppressNextChangeRef };
135
- };
@@ -1,15 +0,0 @@
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>;
@@ -1,24 +0,0 @@
1
- /**
2
- * Flattens the entities into the rows the grid actually renders: each entity followed by its
3
- * children while it is expanded. Drag and shift-click ranges walk this list, so they cross
4
- * nesting levels the way the user sees them on screen.
5
- */
6
- export const getDragSelectionRows = (entities, expandedRows) => {
7
- const expanded = new Set(expandedRows);
8
- const rows = [];
9
- const entityById = new Map();
10
- entities.forEach(entity => {
11
- rows.push({ id: entity.id, isNested: false });
12
- entityById.set(entity.id, entity);
13
- // Children are always indexed — a collapsed row's children still need to resolve for
14
- // the selection predicates — but only an expanded row contributes them to the range.
15
- const isExpanded = expanded.has(entity.id);
16
- (entity.children || []).forEach(child => {
17
- entityById.set(child.id, child);
18
- if (isExpanded) {
19
- rows.push({ id: child.id, isNested: true });
20
- }
21
- });
22
- });
23
- return { rows, entityById };
24
- };
@@ -1,2 +0,0 @@
1
- import { IDragSelectionRow } from "../interfaces";
2
- export declare const getRangeIds: (rows: IDragSelectionRow[], fromId: string, toId: string, isSelectable: (row: IDragSelectionRow) => boolean) => string[];
@@ -1,17 +0,0 @@
1
- export const getRangeIds = (rows, fromId, toId, isSelectable) => {
2
- const fromIdx = rows.findIndex(row => row.id === fromId);
3
- const toIdx = rows.findIndex(row => row.id === toId);
4
- if (fromIdx === -1 || toIdx === -1) {
5
- return [];
6
- }
7
- const start = Math.min(fromIdx, toIdx);
8
- const end = Math.max(fromIdx, toIdx);
9
- const ids = [];
10
- for (let i = start; i <= end; i++) {
11
- const row = rows[i];
12
- if (isSelectable(row)) {
13
- ids.push(row.id);
14
- }
15
- }
16
- return ids;
17
- };