@geotab/zenith 3.16.0 → 3.17.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/README.md +67 -1
  2. package/README.md.baseline +1 -0
  3. package/dist/absolute/absolute.js +5 -1
  4. package/dist/button/button.d.ts +2 -1
  5. package/dist/button/button.js +22 -5
  6. package/dist/checkboxListWithAction/checkboxListWithAction.d.ts +2 -0
  7. package/dist/checkboxListWithAction/checkboxListWithAction.js +1 -1
  8. package/dist/commonHelpers/ShowMoreCell.d.ts +5 -0
  9. package/dist/commonHelpers/ShowMoreCell.js +66 -0
  10. package/dist/commonHelpers/getAriaAttributes.js +6 -9
  11. package/dist/commonHelpers/getNonAriaProps.d.ts +11 -0
  12. package/dist/commonHelpers/getNonAriaProps.js +19 -0
  13. package/dist/commonHelpers/hooks/useScroll.d.ts +1 -1
  14. package/dist/commonHelpers/hooks/useScroll.js +6 -6
  15. package/dist/commonHelpers/isAriaProp.d.ts +9 -0
  16. package/dist/commonHelpers/isAriaProp.js +13 -0
  17. package/dist/commonHelpers/showMoreRow.d.ts +28 -0
  18. package/dist/commonHelpers/showMoreRow.js +29 -0
  19. package/dist/commonHelpers/tabsKeyboard.d.ts +1 -1
  20. package/dist/commonHelpers/tabsKeyboard.js +15 -1
  21. package/dist/commonStyles/colors/colors.less +18 -0
  22. package/dist/dataFeed/dataFeedColumnsItems.js +3 -1
  23. package/dist/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +2 -1
  24. package/dist/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
  25. package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +4 -2
  26. package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +10 -1
  27. package/dist/dataGrid/dataGrid.d.ts +5 -1
  28. package/dist/dataGrid/dataGrid.js +39 -2
  29. package/dist/dataGrid/lazyLoadingEnd/lazyLoadingEnd.d.ts +3 -0
  30. package/dist/dataGrid/lazyLoadingEnd/lazyLoadingEnd.js +54 -0
  31. package/dist/dataGrid/row/row.js +20 -2
  32. package/dist/dataGrid/withSelectableRows/components/bulkActions/bulkActions.d.ts +3 -1
  33. package/dist/dataGrid/withSelectableRows/components/bulkActions/bulkActions.js +39 -4
  34. package/dist/dataGrid/withSelectableRows/withSelectableRows.js +73 -12
  35. package/dist/dropdown/dropdownTrigger.d.ts +1 -1
  36. package/dist/dropdownRaw/dropdownHelper.d.ts +12 -0
  37. package/dist/dropdownRaw/dropdownHelper.js +32 -11
  38. package/dist/dropdownRaw/dropdownRaw.js +36 -8
  39. package/dist/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
  40. package/dist/dropdownRaw/dropdownSearchableTrigger.js +13 -6
  41. package/dist/dropdownRaw/dropdownTrigger.d.ts +2 -1
  42. package/dist/dropdownRaw/dropdownTrigger.js +2 -2
  43. package/dist/dropdownRaw/stateReducer/stateReducer.d.ts +8 -0
  44. package/dist/dropdownRaw/stateReducer/stateReducer.js +5 -2
  45. package/dist/dropdownRaw/types.d.ts +36 -0
  46. package/dist/filterButton/filterButton.d.ts +1 -1
  47. package/dist/formGroup/hooks/rowHooks/useLabelClasses.js +8 -2
  48. package/dist/formLayout/utils/applyLayoutPosition/applyLayoutPosition.d.ts +2 -1
  49. package/dist/formLayout/utils/applyLayoutPosition/applyLayoutPosition.js +37 -90
  50. package/dist/header/components/collapsedItemsControl/collapsedItemsControl.d.ts +1 -1
  51. package/dist/header/components/collapsedItemsControl/collapsedItemsControl.js +6 -2
  52. package/dist/header/headerButton.d.ts +3 -1
  53. package/dist/header/headerButton.js +4 -2
  54. package/dist/header/headerMenu.d.ts +2 -0
  55. package/dist/header/headerMenu.js +1 -1
  56. package/dist/index.css +319 -68
  57. package/dist/index.d.ts +3 -1
  58. package/dist/index.js +9 -3
  59. package/dist/menu/components/menuButton.d.ts +3 -1
  60. package/dist/menu/components/menuButton.js +66 -47
  61. package/dist/menu/components/menuItem.js +4 -4
  62. package/dist/miniTabs/miniTabs.js +4 -2
  63. package/dist/pageHeader/pageHeaderButton.d.ts +1 -1
  64. package/dist/pageHeader/pageHeaderButton.js +4 -2
  65. package/dist/pagination/pagination.d.ts +19 -4
  66. package/dist/pagination/pagination.js +21 -1
  67. package/dist/pagination/paginationText/paginationText.d.ts +7 -1
  68. package/dist/pagination/paginationText/paginationText.js +6 -3
  69. package/dist/pillExpandable/pillContent.d.ts +3 -2
  70. package/dist/pillExpandable/pillContent.js +2 -2
  71. package/dist/pillExpandable/pillExpandable.js +20 -5
  72. package/dist/pillExpandable/pillExpandablePopoverContent.d.ts +3 -2
  73. package/dist/pillExpandable/pillExpandablePopoverContent.js +1 -1
  74. package/dist/pillExpandable/pillExpandableSimple.d.ts +3 -1
  75. package/dist/pillExpandable/pillExpandableSimple.js +19 -9
  76. package/dist/selectList/selectList.js +1 -0
  77. package/dist/selectList/selectListItem.d.ts +10 -1
  78. package/dist/selectList/selectListItem.js +12 -9
  79. package/dist/table/children/tablePagination.d.ts +1 -1
  80. package/dist/table/children/useTableChildren.d.ts +4 -2
  81. package/dist/table/children/useTableChildren.js +64 -16
  82. package/dist/table/nested/nestedData.d.ts +29 -1
  83. package/dist/table/nested/nestedData.js +45 -4
  84. package/dist/table/nested/useNestedRows.js +18 -22
  85. package/dist/table/nested/useShowMore.d.ts +41 -0
  86. package/dist/table/nested/useShowMore.js +56 -0
  87. package/dist/table/selectable/interfaces.d.ts +17 -0
  88. package/dist/table/selectable/useDragSelection.d.ts +10 -0
  89. package/dist/table/selectable/useDragSelection.js +145 -0
  90. package/dist/table/selectable/useSelectableRows.d.ts +5 -2
  91. package/dist/table/selectable/useSelectableRows.js +131 -36
  92. package/dist/table/selectable/utils/calculateSelectionState.d.ts +1 -1
  93. package/dist/table/selectable/utils/calculateSelectionState.js +43 -7
  94. package/dist/table/selectable/utils/checkRow.js +4 -2
  95. package/dist/table/selectable/utils/getCurrentPageSelection.js +9 -5
  96. package/dist/table/selectable/utils/getDragSelectionRows.d.ts +15 -0
  97. package/dist/table/selectable/utils/getDragSelectionRows.js +28 -0
  98. package/dist/table/selectable/utils/getRangeIds.d.ts +2 -0
  99. package/dist/table/selectable/utils/getRangeIds.js +21 -0
  100. package/dist/table/selectable/utils/isRowChecked.d.ts +1 -1
  101. package/dist/table/selectable/utils/isRowChecked.js +40 -7
  102. package/dist/table/table.d.ts +1 -2
  103. package/dist/table/table.js +58 -31
  104. package/dist/tabs/tabs.d.ts +1 -0
  105. package/dist/tabs/tabs.js +50 -17
  106. package/dist/textInputRaw/textInputRaw.js +3 -2
  107. package/dist/tooltip/tooltip.d.ts +2 -0
  108. package/dist/tooltip/tooltip.js +19 -7
  109. package/dist/utils/localization/translations/ar-001.json +1 -0
  110. package/dist/utils/localization/translations/bg-BG.json +1 -0
  111. package/dist/utils/localization/translations/cs.json +1 -0
  112. package/dist/utils/localization/translations/da-DK.json +1 -0
  113. package/dist/utils/localization/translations/de.json +1 -0
  114. package/dist/utils/localization/translations/el-GR.json +1 -0
  115. package/dist/utils/localization/translations/en.json +4 -0
  116. package/dist/utils/localization/translations/es.json +1 -0
  117. package/dist/utils/localization/translations/et-EE.json +1 -0
  118. package/dist/utils/localization/translations/fi-FI.json +1 -0
  119. package/dist/utils/localization/translations/fr-FR.json +1 -0
  120. package/dist/utils/localization/translations/fr.json +1 -0
  121. package/dist/utils/localization/translations/hu-HU.json +1 -0
  122. package/dist/utils/localization/translations/id.json +1 -0
  123. package/dist/utils/localization/translations/it.json +1 -0
  124. package/dist/utils/localization/translations/ja.json +1 -0
  125. package/dist/utils/localization/translations/ka-GE.json +1 -0
  126. package/dist/utils/localization/translations/ko-KR.json +1 -0
  127. package/dist/utils/localization/translations/lt-LT.json +1 -0
  128. package/dist/utils/localization/translations/lv-LV.json +1 -0
  129. package/dist/utils/localization/translations/ms.json +1 -0
  130. package/dist/utils/localization/translations/nb-NO.json +1 -0
  131. package/dist/utils/localization/translations/nl.json +1 -0
  132. package/dist/utils/localization/translations/pl.json +1 -0
  133. package/dist/utils/localization/translations/pt-BR.json +1 -0
  134. package/dist/utils/localization/translations/pt-PT.json +1 -0
  135. package/dist/utils/localization/translations/ro-RO.json +1 -0
  136. package/dist/utils/localization/translations/sk-SK.json +1 -0
  137. package/dist/utils/localization/translations/sv.json +1 -0
  138. package/dist/utils/localization/translations/th.json +1 -0
  139. package/dist/utils/localization/translations/tr.json +1 -0
  140. package/dist/utils/localization/translations/zh-Hans.json +1 -0
  141. package/dist/utils/localization/translations/zh-TW.json +1 -0
  142. package/dist/waiting/waiting.js +95 -1
  143. package/esm/absolute/absolute.js +5 -1
  144. package/esm/button/button.d.ts +2 -1
  145. package/esm/button/button.js +22 -5
  146. package/esm/checkboxListWithAction/checkboxListWithAction.d.ts +2 -0
  147. package/esm/checkboxListWithAction/checkboxListWithAction.js +1 -1
  148. package/esm/commonHelpers/ShowMoreCell.d.ts +5 -0
  149. package/esm/commonHelpers/ShowMoreCell.js +57 -0
  150. package/esm/commonHelpers/getAriaAttributes.js +6 -9
  151. package/esm/commonHelpers/getNonAriaProps.d.ts +11 -0
  152. package/esm/commonHelpers/getNonAriaProps.js +15 -0
  153. package/esm/commonHelpers/hooks/useScroll.d.ts +1 -1
  154. package/esm/commonHelpers/hooks/useScroll.js +6 -6
  155. package/esm/commonHelpers/isAriaProp.d.ts +9 -0
  156. package/esm/commonHelpers/isAriaProp.js +9 -0
  157. package/esm/commonHelpers/showMoreRow.d.ts +28 -0
  158. package/esm/commonHelpers/showMoreRow.js +22 -0
  159. package/esm/commonHelpers/tabsKeyboard.d.ts +1 -1
  160. package/esm/commonHelpers/tabsKeyboard.js +15 -1
  161. package/esm/commonStyles/colors/colorsConstant.js +11 -11
  162. package/esm/dataFeed/dataFeedColumnsItems.js +3 -1
  163. package/esm/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +2 -1
  164. package/esm/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
  165. package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +4 -2
  166. package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +10 -1
  167. package/esm/dataGrid/dataGrid.d.ts +5 -1
  168. package/esm/dataGrid/dataGrid.js +38 -2
  169. package/esm/dataGrid/lazyLoadingEnd/lazyLoadingEnd.d.ts +3 -0
  170. package/esm/dataGrid/lazyLoadingEnd/lazyLoadingEnd.js +45 -0
  171. package/esm/dataGrid/row/row.js +20 -2
  172. package/esm/dataGrid/withSelectableRows/components/bulkActions/bulkActions.d.ts +3 -1
  173. package/esm/dataGrid/withSelectableRows/components/bulkActions/bulkActions.js +39 -4
  174. package/esm/dataGrid/withSelectableRows/withSelectableRows.js +73 -12
  175. package/esm/dropdown/dropdownTrigger.d.ts +1 -1
  176. package/esm/dropdownRaw/dropdownHelper.d.ts +12 -0
  177. package/esm/dropdownRaw/dropdownHelper.js +30 -10
  178. package/esm/dropdownRaw/dropdownRaw.js +37 -9
  179. package/esm/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
  180. package/esm/dropdownRaw/dropdownSearchableTrigger.js +13 -6
  181. package/esm/dropdownRaw/dropdownTrigger.d.ts +2 -1
  182. package/esm/dropdownRaw/dropdownTrigger.js +2 -2
  183. package/esm/dropdownRaw/stateReducer/stateReducer.d.ts +8 -0
  184. package/esm/dropdownRaw/stateReducer/stateReducer.js +5 -2
  185. package/esm/dropdownRaw/types.d.ts +36 -0
  186. package/esm/filterButton/filterButton.d.ts +1 -1
  187. package/esm/formGroup/hooks/rowHooks/useLabelClasses.js +8 -2
  188. package/esm/formLayout/utils/applyLayoutPosition/applyLayoutPosition.d.ts +2 -1
  189. package/esm/formLayout/utils/applyLayoutPosition/applyLayoutPosition.js +37 -90
  190. package/esm/header/components/collapsedItemsControl/collapsedItemsControl.d.ts +1 -1
  191. package/esm/header/components/collapsedItemsControl/collapsedItemsControl.js +6 -2
  192. package/esm/header/headerButton.d.ts +3 -1
  193. package/esm/header/headerButton.js +4 -2
  194. package/esm/header/headerMenu.d.ts +2 -0
  195. package/esm/header/headerMenu.js +1 -1
  196. package/esm/index.d.ts +3 -1
  197. package/esm/index.js +3 -1
  198. package/esm/menu/components/menuButton.d.ts +3 -1
  199. package/esm/menu/components/menuButton.js +66 -47
  200. package/esm/menu/components/menuItem.js +4 -4
  201. package/esm/miniTabs/miniTabs.js +4 -2
  202. package/esm/pageHeader/pageHeaderButton.d.ts +1 -1
  203. package/esm/pageHeader/pageHeaderButton.js +4 -2
  204. package/esm/pagination/pagination.d.ts +19 -4
  205. package/esm/pagination/pagination.js +21 -1
  206. package/esm/pagination/paginationText/paginationText.d.ts +7 -1
  207. package/esm/pagination/paginationText/paginationText.js +6 -3
  208. package/esm/pillExpandable/pillContent.d.ts +3 -2
  209. package/esm/pillExpandable/pillContent.js +2 -2
  210. package/esm/pillExpandable/pillExpandable.js +20 -5
  211. package/esm/pillExpandable/pillExpandablePopoverContent.d.ts +3 -2
  212. package/esm/pillExpandable/pillExpandablePopoverContent.js +1 -1
  213. package/esm/pillExpandable/pillExpandableSimple.d.ts +3 -1
  214. package/esm/pillExpandable/pillExpandableSimple.js +20 -10
  215. package/esm/selectList/selectList.js +1 -0
  216. package/esm/selectList/selectListItem.d.ts +10 -1
  217. package/esm/selectList/selectListItem.js +12 -9
  218. package/esm/table/children/tablePagination.d.ts +1 -1
  219. package/esm/table/children/useTableChildren.d.ts +4 -2
  220. package/esm/table/children/useTableChildren.js +64 -16
  221. package/esm/table/nested/nestedData.d.ts +29 -1
  222. package/esm/table/nested/nestedData.js +44 -3
  223. package/esm/table/nested/useNestedRows.js +18 -22
  224. package/esm/table/nested/useShowMore.d.ts +41 -0
  225. package/esm/table/nested/useShowMore.js +52 -0
  226. package/esm/table/selectable/interfaces.d.ts +17 -0
  227. package/esm/table/selectable/useDragSelection.d.ts +10 -0
  228. package/esm/table/selectable/useDragSelection.js +141 -0
  229. package/esm/table/selectable/useSelectableRows.d.ts +5 -2
  230. package/esm/table/selectable/useSelectableRows.js +129 -35
  231. package/esm/table/selectable/utils/calculateSelectionState.d.ts +1 -1
  232. package/esm/table/selectable/utils/calculateSelectionState.js +43 -7
  233. package/esm/table/selectable/utils/checkRow.js +4 -2
  234. package/esm/table/selectable/utils/getCurrentPageSelection.js +9 -5
  235. package/esm/table/selectable/utils/getDragSelectionRows.d.ts +15 -0
  236. package/esm/table/selectable/utils/getDragSelectionRows.js +24 -0
  237. package/esm/table/selectable/utils/getRangeIds.d.ts +2 -0
  238. package/esm/table/selectable/utils/getRangeIds.js +17 -0
  239. package/esm/table/selectable/utils/isRowChecked.d.ts +1 -1
  240. package/esm/table/selectable/utils/isRowChecked.js +40 -7
  241. package/esm/table/table.d.ts +1 -2
  242. package/esm/table/table.js +43 -16
  243. package/esm/tabs/tabs.d.ts +1 -0
  244. package/esm/tabs/tabs.js +50 -17
  245. package/esm/textInputRaw/textInputRaw.js +3 -2
  246. package/esm/tooltip/tooltip.d.ts +2 -0
  247. package/esm/tooltip/tooltip.js +19 -7
  248. package/esm/utils/localization/translations/ar-001.json +1 -0
  249. package/esm/utils/localization/translations/bg-BG.json +1 -0
  250. package/esm/utils/localization/translations/cs.json +1 -0
  251. package/esm/utils/localization/translations/da-DK.json +1 -0
  252. package/esm/utils/localization/translations/de.json +1 -0
  253. package/esm/utils/localization/translations/el-GR.json +1 -0
  254. package/esm/utils/localization/translations/en.json +4 -0
  255. package/esm/utils/localization/translations/es.json +1 -0
  256. package/esm/utils/localization/translations/et-EE.json +1 -0
  257. package/esm/utils/localization/translations/fi-FI.json +1 -0
  258. package/esm/utils/localization/translations/fr-FR.json +1 -0
  259. package/esm/utils/localization/translations/fr.json +1 -0
  260. package/esm/utils/localization/translations/hu-HU.json +1 -0
  261. package/esm/utils/localization/translations/id.json +1 -0
  262. package/esm/utils/localization/translations/it.json +1 -0
  263. package/esm/utils/localization/translations/ja.json +1 -0
  264. package/esm/utils/localization/translations/ka-GE.json +1 -0
  265. package/esm/utils/localization/translations/ko-KR.json +1 -0
  266. package/esm/utils/localization/translations/lt-LT.json +1 -0
  267. package/esm/utils/localization/translations/lv-LV.json +1 -0
  268. package/esm/utils/localization/translations/ms.json +1 -0
  269. package/esm/utils/localization/translations/nb-NO.json +1 -0
  270. package/esm/utils/localization/translations/nl.json +1 -0
  271. package/esm/utils/localization/translations/pl.json +1 -0
  272. package/esm/utils/localization/translations/pt-BR.json +1 -0
  273. package/esm/utils/localization/translations/pt-PT.json +1 -0
  274. package/esm/utils/localization/translations/ro-RO.json +1 -0
  275. package/esm/utils/localization/translations/sk-SK.json +1 -0
  276. package/esm/utils/localization/translations/sv.json +1 -0
  277. package/esm/utils/localization/translations/th.json +1 -0
  278. package/esm/utils/localization/translations/tr.json +1 -0
  279. package/esm/utils/localization/translations/zh-Hans.json +1 -0
  280. package/esm/utils/localization/translations/zh-TW.json +1 -0
  281. package/esm/waiting/waiting.js +96 -2
  282. package/package.json +18 -6
@@ -0,0 +1,145 @@
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
+ // Drop the anchor only once its row is actually gone (collapsed, filtered, paginated away).
134
+ // Keying this on the `rows` array identity instead would clear the anchor on every render for
135
+ // any caller that rebuilds its entity list each time - NestedData does exactly that - which
136
+ // silently turns every shift-click into a plain single-row toggle.
137
+ (0, react_1.useEffect)(() => {
138
+ if (anchorIdRef.current !== null && !rows.some(row => row.id === anchorIdRef.current)) {
139
+ anchorIdRef.current = null;
140
+ }
141
+ }, [rows]);
142
+ (0, react_1.useEffect)(() => endDrag, [endDrag]);
143
+ return { onCheckboxMouseDown, suppressNextChangeRef };
144
+ };
145
+ 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";
@@ -8,6 +8,8 @@ export type TSelectionStrategy = "main" | "nested";
8
8
  export interface ISelectableRowsOptions<T extends IRowEntity<N>, N extends IEntityWithId> {
9
9
  selection: ISelectionValue | undefined;
10
10
  onSelect: (selection: ISelectionValue) => void;
11
+ /** Preserve cross-page Select All using excluded IDs. Consumers must resolve exclusions before running bulk actions. Defaults to false. */
12
+ allowExclusions?: boolean;
11
13
  checkboxDisabled?: (entity: T | N, isNested?: boolean) => boolean;
12
14
  checkboxVisible?: (entity: T | N, isNested?: boolean) => boolean;
13
15
  checkboxInHeader?: boolean;
@@ -32,8 +34,9 @@ export declare const getEmptySelection: () => {
32
34
  all: boolean;
33
35
  selected: string[];
34
36
  };
37
+ export declare const isAllSelection: (all: boolean | undefined, selectedCount: number | undefined, allowExclusions?: boolean) => boolean;
35
38
  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) => {
39
+ 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
40
  selectableColumns: IListColumn<T, N>[];
38
41
  selectableFeedWrapper: (primaryData: ReactNode, secondaryData: ReactNode, entity: T | N, isNested: boolean) => [ReactNode, ReactNode];
39
42
  };
@@ -6,8 +6,9 @@ const {
6
6
  Object.defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
9
- exports.TRANSLATIONS = exports.useSelectableRows = exports.SelectableWrapperName = exports.getEmptySelection = void 0;
9
+ exports.TRANSLATIONS = exports.useSelectableRows = exports.SelectableWrapperName = exports.isAllSelection = exports.getEmptySelection = void 0;
10
10
  const jsx_runtime_1 = require("react/jsx-runtime");
11
+ /* eslint-disable complexity */
11
12
  const react_1 = require("react");
12
13
  const interfaces_1 = require("./interfaces");
13
14
  const checkboxCell_1 = require("../../dataGrid/columns/checkboxColumn/checkboxCell");
@@ -84,15 +85,21 @@ const useLanguage_1 = require("../../utils/localization/useLanguage");
84
85
  const checkRow_1 = require("./utils/checkRow");
85
86
  const isRowChecked_1 = require("./utils/isRowChecked");
86
87
  const getCurrentPageSelection_1 = require("./utils/getCurrentPageSelection");
88
+ const useDragSelection_1 = require("./useDragSelection");
89
+ const getDragSelectionRows_1 = require("./utils/getDragSelectionRows");
90
+ const showMoreRow_1 = require("../../commonHelpers/showMoreRow");
87
91
  const getEmptySelection = () => ({
88
92
  all: false,
89
93
  selected: []
90
94
  });
91
95
  exports.getEmptySelection = getEmptySelection;
96
+ const isAllSelection = (all, selectedCount, allowExclusions) => !!all && (!!allowExclusions || selectedCount === 0);
97
+ exports.isAllSelection = isAllSelection;
92
98
  exports.SelectableWrapperName = "Selectable";
93
99
  // Infinite scroll has no pages, so the header checkbox always means "select all" (never current page).
94
100
  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) => {
101
+ const getSelectionMenuState = (allSelected, selections, pageState) => allSelected ? selections.size === 0 ? interfaces_1.SelectionState.All : interfaces_1.SelectionState.Partial : pageState;
102
+ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false, gridRef, expandedRows) => {
96
103
  var _a;
97
104
  const {
98
105
  translate
@@ -100,13 +107,12 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
100
107
  const selections = (0, react_1.useMemo)(() => (0, getSelection_1.getSelections)(selectable === null || selectable === void 0 ? void 0 : selectable.selection), [selectable === null || selectable === void 0 ? void 0 : selectable.selection]);
101
108
  const [state, setState] = (0, react_1.useState)(interfaces_1.SelectionState.None);
102
109
  const checkboxVisible = (0, react_1.useMemo)(() => {
103
- if (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) {
104
- return selectable.checkboxVisible;
105
- }
106
- if ((selectable === null || selectable === void 0 ? void 0 : selectable.strategy) !== "nested") {
107
- return (_, isNested) => !isNested;
108
- }
109
- return () => true;
110
+ const base = (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) ? selectable.checkboxVisible : (selectable === null || selectable === void 0 ? void 0 : selectable.strategy) !== "nested" ? (_, isNested) => !isNested : () => true;
111
+ // Synthetic "+N more" and loading placeholder rows are never selectable.
112
+ return (entity, isNested) => {
113
+ if ((0, showMoreRow_1.isShowMoreRow)(entity) || entity.isLoading) return false;
114
+ return base(entity, isNested);
115
+ };
110
116
  }, [selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
111
117
  const checkboxDisabled = (0, react_1.useMemo)(() => {
112
118
  if (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxDisabled) {
@@ -118,6 +124,12 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
118
124
  }
119
125
  return () => false;
120
126
  }, [selectable, selections]);
127
+ // `checkRow` and `getCurrentPageSelection` read callbacks off `selectable`, so hand them the
128
+ // wrapped ones to apply the same exclusions.
129
+ const wrappedSelectable = (0, react_1.useMemo)(() => selectable ? Object.assign(Object.assign({}, selectable), {
130
+ checkboxVisible,
131
+ checkboxDisabled
132
+ }) : undefined, [selectable, checkboxVisible, checkboxDisabled]);
121
133
  const checkboxPlaceholder = (0, react_1.useMemo)(() => {
122
134
  if ((selectable === null || selectable === void 0 ? void 0 : selectable.checkboxPlaceholder) !== undefined) {
123
135
  return selectable.checkboxPlaceholder;
@@ -130,40 +142,96 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
130
142
  }, [selectable === null || selectable === void 0 ? void 0 : selectable.checkboxPlaceholder, selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
131
143
  const isAllSelected = (0, react_1.useMemo)(() => {
132
144
  var _a;
133
- return ((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all) || false;
134
- }, [(_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all]);
145
+ return (0, exports.isAllSelection)((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all, selections.size, selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions);
146
+ }, [(_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all, selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions, selections.size]);
135
147
  const selectableState = (0, react_1.useMemo)(() => (0, calculateSelectionState_1.calculateSelectionState)(entities, selections, isAllSelected, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy), [checkboxDisabled, checkboxVisible, entities, isAllSelected, selections, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
148
+ const selectionMenuState = getSelectionMenuState(isAllSelected, selections, selectableState);
136
149
  const firstColumnId = (0, react_1.useMemo)(() => columns.length > 0 ? columns[0].id : null, [columns]);
137
150
  (0, react_1.useEffect)(() => {
138
151
  if (selectable && selectable.selection) {
139
152
  const newSelections = new Set(selectable.selection.selected);
140
- const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, newSelections, selectable.selection.all || false, checkboxVisible, checkboxDisabled, selectable.strategy);
153
+ const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, newSelections, isAllSelected, checkboxVisible, checkboxDisabled, selectable.strategy);
141
154
  setState(newState);
142
155
  }
143
- }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
156
+ }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, selectable === null || selectable === void 0 ? void 0 : selectable.strategy, isAllSelected]);
144
157
  const getNewSelection = (0, react_1.useCallback)((id, checked) => {
145
- if (state === interfaces_1.SelectionState.All) {
146
- const newSelection = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable);
147
- (0, checkRow_1.checkRow)(newSelection, selectable, entities, id, false);
148
- return newSelection;
158
+ if (isAllSelected && !(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions)) {
159
+ const included = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, wrappedSelectable);
160
+ (0, checkRow_1.checkRow)(included, wrappedSelectable, entities, id, checked);
161
+ return included;
149
162
  }
150
- (0, checkRow_1.checkRow)(selections, selectable, entities, id, checked);
163
+ if (isAllSelected) {
164
+ // MYG-142234: `selections` holds the ids excluded from the "all" selection.
165
+ // Toggling a row here must only ever add/remove that single id from the
166
+ // exclusion set - it must never be rebuilt from `entities` (the current page),
167
+ // otherwise every other page's rows would silently fall out of the selection.
168
+ const excluded = new Set(selections);
169
+ (0, checkRow_1.checkRow)(excluded, wrappedSelectable, entities, id, !checked);
170
+ return excluded;
171
+ }
172
+ (0, checkRow_1.checkRow)(selections, wrappedSelectable, entities, id, checked);
151
173
  return selections;
152
- }, [state, entities, selectable, selections]);
174
+ }, [entities, selectable, wrappedSelectable, selections, isAllSelected]);
153
175
  const onSelectListener = (0, react_1.useCallback)((id, checked) => {
154
- var _a;
176
+ const wasAllSelected = !!(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) && isAllSelected;
155
177
  const newSelection = getNewSelection(id, checked);
156
- 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);
157
- const newValue = {
178
+ const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, newSelection, wasAllSelected, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy);
179
+ // MYG-142234: once selection spans "all" pages, unchecking a row must keep `all: true`
180
+ // and only record the exclusion - it must not collapse to the current page's ids.
181
+ const newValue = wasAllSelected ? {
182
+ selected: [...newSelection],
183
+ all: true
184
+ } : {
158
185
  selected: [...newSelection],
159
186
  all: newState === interfaces_1.SelectionState.All
160
187
  };
161
188
  setState(newState);
162
189
  selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
163
190
  setSelectMode(newValue.all || newValue.selected.length > 0);
164
- }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, setState, getNewSelection]);
191
+ }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, setState, getNewSelection, isAllSelected]);
192
+ const onBatchSelect = (0, react_1.useCallback)((rangeIds, select, base) => {
193
+ const result = new Set(base);
194
+ const limit = selectable === null || selectable === void 0 ? void 0 : selectable.selectionLimit;
195
+ const wasAllSelected = !!(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) && isAllSelected;
196
+ for (const id of rangeIds) {
197
+ if (!wasAllSelected && select && limit !== undefined && result.size >= limit) {
198
+ break;
199
+ }
200
+ (0, checkRow_1.checkRow)(result, wrappedSelectable, entities, id, wasAllSelected ? !select : select);
201
+ }
202
+ const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, result, wasAllSelected, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy);
203
+ const newValue = {
204
+ selected: [...result],
205
+ all: wasAllSelected || newState === interfaces_1.SelectionState.All
206
+ };
207
+ setState(newState);
208
+ selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
209
+ setSelectMode(newValue.all || newValue.selected.length > 0);
210
+ }, [entities, selectable, wrappedSelectable, checkboxVisible, checkboxDisabled, setSelectMode, isAllSelected]);
211
+ // Deliberately independent of the current selection, so the drag anchor survives the
212
+ // selection changes a drag itself produces.
213
+ const {
214
+ rows: dragRows,
215
+ entityById
216
+ } = (0, react_1.useMemo)(() => (0, getDragSelectionRows_1.getDragSelectionRows)(entities, expandedRows), [entities, expandedRows]);
217
+ const isSelectable = (0, react_1.useCallback)(row => {
218
+ const entity = entityById.get(row.id);
219
+ return !!entity && checkboxVisible(entity, row.isNested) && !checkboxDisabled(entity, row.isNested);
220
+ }, [entityById, checkboxVisible, checkboxDisabled]);
221
+ const getBaseSelection = (0, react_1.useCallback)(() => isAllSelected && !(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) ? (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, wrappedSelectable) : new Set(selections), [isAllSelected, selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions, entities, wrappedSelectable, selections]);
222
+ const {
223
+ onCheckboxMouseDown,
224
+ suppressNextChangeRef
225
+ } = (0, useDragSelection_1.useDragSelection)(dragRows, gridRef, onBatchSelect, getBaseSelection, isSelectable, !!selectable);
226
+ const onCheckboxChange = (0, react_1.useCallback)((id, checked) => {
227
+ if (suppressNextChangeRef.current) {
228
+ suppressNextChangeRef.current = false;
229
+ return;
230
+ }
231
+ onSelectListener(id, checked);
232
+ }, [onSelectListener, suppressNextChangeRef]);
165
233
  const onChangeSelectionState = (0, react_1.useCallback)(newState => {
166
- var _a, _b;
234
+ var _a, _b, _c;
167
235
  if (newState === interfaces_1.SelectionState.All) {
168
236
  (selectable === null || selectable === void 0 ? void 0 : selectable.onSelect) && selectable.onSelect({
169
237
  selected: [],
@@ -180,17 +248,19 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
180
248
  setSelectMode(false);
181
249
  return;
182
250
  }
183
- const newSelections = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable);
251
+ const newSelections = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, wrappedSelectable);
184
252
  setState(newState);
185
253
  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 : [];
186
- const mergedSelections = new Set([...previousSelections, ...newSelections]);
187
- const newValue = {
188
- selected: [...mergedSelections],
254
+ const newValue = (selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) && ((_c = selectable.selection) === null || _c === void 0 ? void 0 : _c.all) ? {
255
+ selected: previousSelections.filter(id => !newSelections.has(id)),
256
+ all: true
257
+ } : {
258
+ selected: [...new Set([...previousSelections, ...newSelections])],
189
259
  all: false
190
260
  };
191
261
  selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
192
262
  setSelectMode(newValue.all || newValue.selected.length > 0);
193
- }, [selectable, entities, setSelectMode]);
263
+ }, [selectable, wrappedSelectable, entities, setSelectMode]);
194
264
  const checkboxTitle = (0, react_1.useCallback)(entity => (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxTitle) ? selectable.checkboxTitle(entity) : firstColumnId ? entity[firstColumnId] || entity.id : entity.id, [firstColumnId, selectable]);
195
265
  const headerTitle = (0, react_1.useCallback)(() => {
196
266
  if (selectable === null || selectable === void 0 ? void 0 : selectable.headerTitle) {
@@ -201,7 +271,12 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
201
271
  }
202
272
  return translate("Deselect all");
203
273
  }, [selectable, selectableState, state, translate]);
204
- 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]);
274
+ const isEntityChecked = (0, react_1.useCallback)(
275
+ // MYG-142234: while `selection.all` is true, `selections` holds excluded ids, and every
276
+ // row must be evaluated through the SelectionState.All (exclusion-aware) branch of
277
+ // isRowChecked - not the per-page `state`, which can be Partial/None for a page that
278
+ // contains some of those exclusions.
279
+ (entity, isNested) => (0, isRowChecked_1.isRowChecked)(selections, isAllSelected ? interfaces_1.SelectionState.All : state, selectable === null || selectable === void 0 ? void 0 : selectable.strategy, entity, isNested, checkboxVisible, checkboxDisabled), [selections, isAllSelected, state, selectable === null || selectable === void 0 ? void 0 : selectable.strategy, checkboxVisible, checkboxDisabled]);
205
280
  const hasSelectable = !!selectable;
206
281
  const selectableCheckboxSelectsCurrentPage = selectable === null || selectable === void 0 ? void 0 : selectable.checkboxSelectsCurrentPage;
207
282
  const selectableTurnOffSelectAll = selectable === null || selectable === void 0 ? void 0 : selectable.turnOffSelectAll;
@@ -239,7 +314,8 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
239
314
  indeterminate: checked.indeterminate,
240
315
  disabled: isDisable,
241
316
  label: checkboxTitle(entity),
242
- onChange: onSelectListener,
317
+ onChange: onCheckboxChange,
318
+ onMouseDown: isDisable ? undefined : onCheckboxMouseDown,
243
319
  children: (0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell.Content, {
244
320
  children: value
245
321
  })
@@ -253,16 +329,32 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
253
329
  checked: state === interfaces_1.SelectionState.CurrentPage || state === interfaces_1.SelectionState.All,
254
330
  indeterminate: state === interfaces_1.SelectionState.Partial,
255
331
  onChange: newValue => {
256
- var _a, _b;
332
+ var _a, _b, _c;
257
333
  if (newValue) {
258
334
  const newState = checkboxEmitsCurrentPage ? interfaces_1.SelectionState.CurrentPage : interfaces_1.SelectionState.All;
259
335
  setState(newState);
260
336
  onChangeSelectionState(newState);
337
+ } else if (isInfinite) {
338
+ onChangeSelectionState(interfaces_1.SelectionState.None);
339
+ } else if (selectable.allowExclusions && ((_a = selectable.selection) === null || _a === void 0 ? void 0 : _a.all)) {
340
+ // MYG-142234: in exclusion mode, `selected` holds excluded ids. Unchecking
341
+ // the header must add the current page's ids to that exclusion set and
342
+ // keep `all: true` - it must never be treated as an inclusion list, or
343
+ // every other page's selection would be silently wiped out.
344
+ const currentPageIds = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, wrappedSelectable);
345
+ const newExcluded = new Set([...selectable.selection.selected, ...currentPageIds]);
346
+ const newState = (0, calculateSelectionState_1.calculateSelectionState)(entities, newExcluded, true, checkboxVisible, checkboxDisabled, selectable.strategy);
347
+ setState(newState);
348
+ selectable.onSelect({
349
+ selected: [...newExcluded],
350
+ all: true
351
+ });
352
+ setSelectMode(true);
261
353
  } else {
262
354
  // Intentionally different from onSelect(None) ("Deselect all" menu item, which clears everything).
263
355
  // Unchecking the header checkbox only removes the current page from the selection, preserving other pages.
264
- const currentPageIds = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, selectable);
265
- const remaining = ((_b = (_a = selectable.selection) === null || _a === void 0 ? void 0 : _a.selected) !== null && _b !== void 0 ? _b : []).filter(id => !currentPageIds.has(id));
356
+ const currentPageIds = (0, getCurrentPageSelection_1.getCurrentPageSelection)(entities, wrappedSelectable);
357
+ const remaining = ((_c = (_b = selectable.selection) === null || _b === void 0 ? void 0 : _b.selected) !== null && _c !== void 0 ? _c : []).filter(id => !currentPageIds.has(id));
266
358
  const newState = remaining.length > 0 ? interfaces_1.SelectionState.Partial : interfaces_1.SelectionState.None;
267
359
  setState(newState);
268
360
  selectable.onSelect({
@@ -272,7 +364,7 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
272
364
  setSelectMode(remaining.length > 0);
273
365
  }
274
366
  },
275
- calculateSelectionState: () => selectableState,
367
+ calculateSelectionState: () => selectionMenuState,
276
368
  checkboxInHeader: checkboxInHeaderValue,
277
369
  header: selectableHeader,
278
370
  onSelect: newState => {
@@ -285,7 +377,7 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
285
377
  return cell;
286
378
  }
287
379
  };
288
- }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onSelectListener, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
380
+ }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onCheckboxChange, onCheckboxMouseDown, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, wrappedSelectable, selectionMenuState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
289
381
  const selectableFeedWrapper = (0, react_1.useCallback)((primaryData, secondaryData, entity, isNested) => {
290
382
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
291
383
  if (!entity) {
@@ -294,6 +386,9 @@ const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMod
294
386
  if (!isMobile) {
295
387
  return [primaryData, secondaryData];
296
388
  }
389
+ if (entity.isLoading) {
390
+ return [primaryData, secondaryData];
391
+ }
297
392
  if (!selectMode) {
298
393
  return [primaryData, secondaryData];
299
394
  }
@@ -2,4 +2,4 @@ import { IEntityWithId } from "../../../commonHelpers/entity";
2
2
  import { IRowEntity } from "../../../dataGrid/row/row";
3
3
  import { SelectionState } from "../interfaces";
4
4
  import { TSelectionStrategy } from "../useSelectableRows";
5
- export declare const calculateSelectionState: <T extends IRowEntity<N>, N extends IEntityWithId>(entities: T[], selections: Set<string>, all: boolean, checkboxVisible: (e: T | N) => boolean, checkboxDisabled: (e: T | N) => boolean, strategy?: TSelectionStrategy) => SelectionState;
5
+ export declare const calculateSelectionState: <T extends IRowEntity<N>, N extends IEntityWithId>(entities: T[], selections: Set<string>, all: boolean, checkboxVisible: (e: T | N, isNested?: boolean) => boolean, checkboxDisabled: (e: T | N, isNested?: boolean) => boolean, strategy?: TSelectionStrategy) => SelectionState;
@@ -1,31 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.calculateSelectionState = void 0;
4
+ const showMoreRow_1 = require("../../../commonHelpers/showMoreRow");
4
5
  const interfaces_1 = require("../interfaces");
5
6
  const calculateSelectionState = (entities, selections, all, checkboxVisible, checkboxDisabled, strategy) => {
6
7
  if (selections.size === 0) {
7
8
  return all ? interfaces_1.SelectionState.All : interfaces_1.SelectionState.None;
8
9
  }
10
+ if (all) {
11
+ // When `all` is true, `selections` holds the ids explicitly excluded from the
12
+ // otherwise-fully-selected set (see ISelectionValue), rather than included ids.
13
+ const isExcluded = (entity) => {
14
+ const children = strategy === "nested" ? (0, showMoreRow_1.getChildrenForSelection)(entity) : undefined;
15
+ if (children && children.length > 0) {
16
+ return children.every(child => {
17
+ if (!checkboxVisible(child, true)) {
18
+ return true;
19
+ }
20
+ if (checkboxDisabled(child, true)) {
21
+ return true;
22
+ }
23
+ return selections.has(child.id);
24
+ });
25
+ }
26
+ return selections.has(entity.id);
27
+ };
28
+ const isPartiallyExcluded = (entity) => {
29
+ const children = strategy === "nested" ? (0, showMoreRow_1.getChildrenForSelection)(entity) : undefined;
30
+ if (children && children.length > 0) {
31
+ return children.some(child => selections.has(child.id));
32
+ }
33
+ return selections.has(entity.id);
34
+ };
35
+ const relevantEntities = entities.filter(entity => checkboxVisible(entity, false) && !checkboxDisabled(entity, false));
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
+ }
9
44
  return entities.every(entity => {
10
- if (!checkboxVisible(entity)) {
45
+ if (!checkboxVisible(entity, false)) {
11
46
  return true;
12
47
  }
13
- if (checkboxDisabled(entity)) {
48
+ if (checkboxDisabled(entity, false)) {
14
49
  return true;
15
50
  }
16
51
  if (strategy === "nested") {
17
- if (entity.children) {
18
- return entity.children.every(child => {
19
- if (!checkboxVisible(child)) {
52
+ const children = (0, showMoreRow_1.getChildrenForSelection)(entity);
53
+ if (children && children.length > 0) {
54
+ return children.every(child => {
55
+ if (!checkboxVisible(child, true)) {
20
56
  return true;
21
57
  }
22
- if (checkboxDisabled(child)) {
58
+ if (checkboxDisabled(child, true)) {
23
59
  return true;
24
60
  }
25
61
  return selections.has(child.id);
26
62
  });
27
63
  }
28
- return false;
64
+ return selections.has(entity.id);
29
65
  }
30
66
  return selections.has(entity.id);
31
67
  })
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.checkRow = void 0;
4
+ const showMoreRow_1 = require("../../../commonHelpers/showMoreRow");
4
5
  const checkRow = (selectionSet, selectable, entities, id, checked) => {
5
6
  const setValue = (rowId) => (checked ? selectionSet.add(rowId) : selectionSet.delete(rowId));
6
7
  if ((selectable === null || selectable === void 0 ? void 0 : selectable.strategy) === "nested") {
7
8
  const entity = entities.find(e => e.id === id);
8
- if (entity && entity.children && entity.children.length > 0) {
9
- entity.children.forEach(child => {
9
+ const children = entity ? (0, showMoreRow_1.getChildrenForSelection)(entity) : undefined;
10
+ if (entity && children && children.length > 0) {
11
+ children.forEach(child => {
10
12
  const isChildVisible = selectable.checkboxVisible ? selectable.checkboxVisible(child, true) : true;
11
13
  const isChildEnabled = !selectable.checkboxDisabled || !selectable.checkboxDisabled(child, true);
12
14
  if (isChildVisible && isChildEnabled) {
@@ -1,15 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCurrentPageSelection = void 0;
4
+ const showMoreRow_1 = require("../../../commonHelpers/showMoreRow");
4
5
  const getCurrentPageSelection = (entities, selectable) => {
5
6
  const newSelections = new Set();
6
7
  entities.forEach(entity => {
7
- const isVisible = (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) ? selectable.checkboxVisible(entity) : true;
8
+ const isVisible = !entity.isLoading && !(0, showMoreRow_1.isShowMoreRow)(entity) && ((selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) ? selectable.checkboxVisible(entity) : true);
8
9
  const isEnabled = !(selectable === null || selectable === void 0 ? void 0 : selectable.checkboxDisabled) || !selectable.checkboxDisabled(entity);
9
- if ((selectable === null || selectable === void 0 ? void 0 : selectable.strategy) === "nested") {
10
- (entity.children || []).forEach(child => {
11
- const isChildVisible = selectable.checkboxVisible ? selectable.checkboxVisible(child, true) : true;
12
- const isChildEnabled = !selectable.checkboxDisabled || !selectable.checkboxDisabled(child, true);
10
+ const children = (selectable === null || selectable === void 0 ? void 0 : selectable.strategy) === "nested" ? (0, showMoreRow_1.getChildrenForSelection)(entity) : undefined;
11
+ if (children && children.length > 0) {
12
+ children.forEach(child => {
13
+ const isChildVisible = !child.isLoading &&
14
+ !(0, showMoreRow_1.isShowMoreRow)(child) &&
15
+ ((selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) ? selectable.checkboxVisible(child, true) : true);
16
+ const isChildEnabled = !(selectable === null || selectable === void 0 ? void 0 : selectable.checkboxDisabled) || !selectable.checkboxDisabled(child, true);
13
17
  if (isChildVisible && isChildEnabled) {
14
18
  newSelections.add(child.id);
15
19
  }
@@ -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;