@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
@@ -1,5 +1,6 @@
1
1
  import { injectString } from "../../utils/localization/translationsDictionary";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ /* eslint-disable complexity */
3
4
  import { useCallback, useEffect, useMemo, useState } from "react";
4
5
  import { SelectionState } from "./interfaces";
5
6
  import { CheckboxCell } from "../../dataGrid/columns/checkboxColumn/checkboxCell";
@@ -10,6 +11,9 @@ import { useLanguage } from "../../utils/localization/useLanguage";
10
11
  import { checkRow } from "./utils/checkRow";
11
12
  import { isRowChecked } from "./utils/isRowChecked";
12
13
  import { getCurrentPageSelection } from "./utils/getCurrentPageSelection";
14
+ import { useDragSelection } from "./useDragSelection";
15
+ import { getDragSelectionRows } from "./utils/getDragSelectionRows";
16
+ import { isShowMoreRow } from "../../commonHelpers/showMoreRow";
13
17
  injectString("cs", "Select all", "Vybrat v\u0161e");
14
18
  injectString("da-DK", "Select all", "V\xE6lg alle");
15
19
  injectString("de", "Select all", "Alle ausw\xE4hlen");
@@ -80,10 +84,12 @@ export const getEmptySelection = () => ({
80
84
  all: false,
81
85
  selected: []
82
86
  });
87
+ export const isAllSelection = (all, selectedCount, allowExclusions) => !!all && (!!allowExclusions || selectedCount === 0);
83
88
  export const SelectableWrapperName = "Selectable";
84
89
  // Infinite scroll has no pages, so the header checkbox always means "select all" (never current page).
85
90
  const resolveCheckboxEmitsCurrentPage = (isInfinite, checkboxSelectsCurrentPage, turnOffSelectAll) => isInfinite ? false : checkboxSelectsCurrentPage !== null && checkboxSelectsCurrentPage !== void 0 ? checkboxSelectsCurrentPage : turnOffSelectAll;
86
- export const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false) => {
91
+ const getSelectionMenuState = (allSelected, selections, pageState) => allSelected ? selections.size === 0 ? SelectionState.All : SelectionState.Partial : pageState;
92
+ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSelectMode, selectable, isInfinite = false, gridRef, expandedRows) => {
87
93
  var _a;
88
94
  const {
89
95
  translate
@@ -91,13 +97,12 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
91
97
  const selections = useMemo(() => getSelections(selectable === null || selectable === void 0 ? void 0 : selectable.selection), [selectable === null || selectable === void 0 ? void 0 : selectable.selection]);
92
98
  const [state, setState] = useState(SelectionState.None);
93
99
  const checkboxVisible = useMemo(() => {
94
- if (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) {
95
- return selectable.checkboxVisible;
96
- }
97
- if ((selectable === null || selectable === void 0 ? void 0 : selectable.strategy) !== "nested") {
98
- return (_, isNested) => !isNested;
99
- }
100
- return () => true;
100
+ 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;
101
+ // Synthetic "+N more" and loading placeholder rows are never selectable.
102
+ return (entity, isNested) => {
103
+ if (isShowMoreRow(entity) || entity.isLoading) return false;
104
+ return base(entity, isNested);
105
+ };
101
106
  }, [selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
102
107
  const checkboxDisabled = useMemo(() => {
103
108
  if (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxDisabled) {
@@ -109,6 +114,12 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
109
114
  }
110
115
  return () => false;
111
116
  }, [selectable, selections]);
117
+ // `checkRow` and `getCurrentPageSelection` read callbacks off `selectable`, so hand them the
118
+ // wrapped ones to apply the same exclusions.
119
+ const wrappedSelectable = useMemo(() => selectable ? Object.assign(Object.assign({}, selectable), {
120
+ checkboxVisible,
121
+ checkboxDisabled
122
+ }) : undefined, [selectable, checkboxVisible, checkboxDisabled]);
112
123
  const checkboxPlaceholder = useMemo(() => {
113
124
  if ((selectable === null || selectable === void 0 ? void 0 : selectable.checkboxPlaceholder) !== undefined) {
114
125
  return selectable.checkboxPlaceholder;
@@ -121,40 +132,96 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
121
132
  }, [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]);
122
133
  const isAllSelected = useMemo(() => {
123
134
  var _a;
124
- return ((_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all) || false;
125
- }, [(_a = selectable === null || selectable === void 0 ? void 0 : selectable.selection) === null || _a === void 0 ? void 0 : _a.all]);
135
+ return 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);
136
+ }, [(_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]);
126
137
  const selectableState = useMemo(() => 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]);
138
+ const selectionMenuState = getSelectionMenuState(isAllSelected, selections, selectableState);
127
139
  const firstColumnId = useMemo(() => columns.length > 0 ? columns[0].id : null, [columns]);
128
140
  useEffect(() => {
129
141
  if (selectable && selectable.selection) {
130
142
  const newSelections = new Set(selectable.selection.selected);
131
- const newState = calculateSelectionState(entities, newSelections, selectable.selection.all || false, checkboxVisible, checkboxDisabled, selectable.strategy);
143
+ const newState = calculateSelectionState(entities, newSelections, isAllSelected, checkboxVisible, checkboxDisabled, selectable.strategy);
132
144
  setState(newState);
133
145
  }
134
- }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, selectable === null || selectable === void 0 ? void 0 : selectable.strategy]);
146
+ }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, selectable === null || selectable === void 0 ? void 0 : selectable.strategy, isAllSelected]);
135
147
  const getNewSelection = useCallback((id, checked) => {
136
- if (state === SelectionState.All) {
137
- const newSelection = getCurrentPageSelection(entities, selectable);
138
- checkRow(newSelection, selectable, entities, id, false);
139
- return newSelection;
148
+ if (isAllSelected && !(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions)) {
149
+ const included = getCurrentPageSelection(entities, wrappedSelectable);
150
+ checkRow(included, wrappedSelectable, entities, id, checked);
151
+ return included;
140
152
  }
141
- checkRow(selections, selectable, entities, id, checked);
153
+ if (isAllSelected) {
154
+ // MYG-142234: `selections` holds the ids excluded from the "all" selection.
155
+ // Toggling a row here must only ever add/remove that single id from the
156
+ // exclusion set - it must never be rebuilt from `entities` (the current page),
157
+ // otherwise every other page's rows would silently fall out of the selection.
158
+ const excluded = new Set(selections);
159
+ checkRow(excluded, wrappedSelectable, entities, id, !checked);
160
+ return excluded;
161
+ }
162
+ checkRow(selections, wrappedSelectable, entities, id, checked);
142
163
  return selections;
143
- }, [state, entities, selectable, selections]);
164
+ }, [entities, selectable, wrappedSelectable, selections, isAllSelected]);
144
165
  const onSelectListener = useCallback((id, checked) => {
145
- var _a;
166
+ const wasAllSelected = !!(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) && isAllSelected;
146
167
  const newSelection = getNewSelection(id, checked);
147
- const newState = 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);
148
- const newValue = {
168
+ const newState = calculateSelectionState(entities, newSelection, wasAllSelected, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy);
169
+ // MYG-142234: once selection spans "all" pages, unchecking a row must keep `all: true`
170
+ // and only record the exclusion - it must not collapse to the current page's ids.
171
+ const newValue = wasAllSelected ? {
172
+ selected: [...newSelection],
173
+ all: true
174
+ } : {
149
175
  selected: [...newSelection],
150
176
  all: newState === SelectionState.All
151
177
  };
152
178
  setState(newState);
153
179
  selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
154
180
  setSelectMode(newValue.all || newValue.selected.length > 0);
155
- }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, setState, getNewSelection]);
181
+ }, [checkboxDisabled, checkboxVisible, entities, selectable, setSelectMode, setState, getNewSelection, isAllSelected]);
182
+ const onBatchSelect = useCallback((rangeIds, select, base) => {
183
+ const result = new Set(base);
184
+ const limit = selectable === null || selectable === void 0 ? void 0 : selectable.selectionLimit;
185
+ const wasAllSelected = !!(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) && isAllSelected;
186
+ for (const id of rangeIds) {
187
+ if (!wasAllSelected && select && limit !== undefined && result.size >= limit) {
188
+ break;
189
+ }
190
+ checkRow(result, wrappedSelectable, entities, id, wasAllSelected ? !select : select);
191
+ }
192
+ const newState = calculateSelectionState(entities, result, wasAllSelected, checkboxVisible, checkboxDisabled, selectable === null || selectable === void 0 ? void 0 : selectable.strategy);
193
+ const newValue = {
194
+ selected: [...result],
195
+ all: wasAllSelected || newState === SelectionState.All
196
+ };
197
+ setState(newState);
198
+ selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
199
+ setSelectMode(newValue.all || newValue.selected.length > 0);
200
+ }, [entities, selectable, wrappedSelectable, checkboxVisible, checkboxDisabled, setSelectMode, isAllSelected]);
201
+ // Deliberately independent of the current selection, so the drag anchor survives the
202
+ // selection changes a drag itself produces.
203
+ const {
204
+ rows: dragRows,
205
+ entityById
206
+ } = useMemo(() => getDragSelectionRows(entities, expandedRows), [entities, expandedRows]);
207
+ const isSelectable = useCallback(row => {
208
+ const entity = entityById.get(row.id);
209
+ return !!entity && checkboxVisible(entity, row.isNested) && !checkboxDisabled(entity, row.isNested);
210
+ }, [entityById, checkboxVisible, checkboxDisabled]);
211
+ const getBaseSelection = useCallback(() => isAllSelected && !(selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) ? getCurrentPageSelection(entities, wrappedSelectable) : new Set(selections), [isAllSelected, selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions, entities, wrappedSelectable, selections]);
212
+ const {
213
+ onCheckboxMouseDown,
214
+ suppressNextChangeRef
215
+ } = useDragSelection(dragRows, gridRef, onBatchSelect, getBaseSelection, isSelectable, !!selectable);
216
+ const onCheckboxChange = useCallback((id, checked) => {
217
+ if (suppressNextChangeRef.current) {
218
+ suppressNextChangeRef.current = false;
219
+ return;
220
+ }
221
+ onSelectListener(id, checked);
222
+ }, [onSelectListener, suppressNextChangeRef]);
156
223
  const onChangeSelectionState = useCallback(newState => {
157
- var _a, _b;
224
+ var _a, _b, _c;
158
225
  if (newState === SelectionState.All) {
159
226
  (selectable === null || selectable === void 0 ? void 0 : selectable.onSelect) && selectable.onSelect({
160
227
  selected: [],
@@ -171,17 +238,19 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
171
238
  setSelectMode(false);
172
239
  return;
173
240
  }
174
- const newSelections = getCurrentPageSelection(entities, selectable);
241
+ const newSelections = getCurrentPageSelection(entities, wrappedSelectable);
175
242
  setState(newState);
176
243
  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 : [];
177
- const mergedSelections = new Set([...previousSelections, ...newSelections]);
178
- const newValue = {
179
- selected: [...mergedSelections],
244
+ const newValue = (selectable === null || selectable === void 0 ? void 0 : selectable.allowExclusions) && ((_c = selectable.selection) === null || _c === void 0 ? void 0 : _c.all) ? {
245
+ selected: previousSelections.filter(id => !newSelections.has(id)),
246
+ all: true
247
+ } : {
248
+ selected: [...new Set([...previousSelections, ...newSelections])],
180
249
  all: false
181
250
  };
182
251
  selectable === null || selectable === void 0 ? void 0 : selectable.onSelect(newValue);
183
252
  setSelectMode(newValue.all || newValue.selected.length > 0);
184
- }, [selectable, entities, setSelectMode]);
253
+ }, [selectable, wrappedSelectable, entities, setSelectMode]);
185
254
  const checkboxTitle = useCallback(entity => (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxTitle) ? selectable.checkboxTitle(entity) : firstColumnId ? entity[firstColumnId] || entity.id : entity.id, [firstColumnId, selectable]);
186
255
  const headerTitle = useCallback(() => {
187
256
  if (selectable === null || selectable === void 0 ? void 0 : selectable.headerTitle) {
@@ -192,7 +261,12 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
192
261
  }
193
262
  return translate("Deselect all");
194
263
  }, [selectable, selectableState, state, translate]);
195
- const isEntityChecked = useCallback((entity, isNested) => 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]);
264
+ const isEntityChecked = useCallback(
265
+ // MYG-142234: while `selection.all` is true, `selections` holds excluded ids, and every
266
+ // row must be evaluated through the SelectionState.All (exclusion-aware) branch of
267
+ // isRowChecked - not the per-page `state`, which can be Partial/None for a page that
268
+ // contains some of those exclusions.
269
+ (entity, isNested) => isRowChecked(selections, isAllSelected ? 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]);
196
270
  const hasSelectable = !!selectable;
197
271
  const selectableCheckboxSelectsCurrentPage = selectable === null || selectable === void 0 ? void 0 : selectable.checkboxSelectsCurrentPage;
198
272
  const selectableTurnOffSelectAll = selectable === null || selectable === void 0 ? void 0 : selectable.turnOffSelectAll;
@@ -230,7 +304,8 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
230
304
  indeterminate: checked.indeterminate,
231
305
  disabled: isDisable,
232
306
  label: checkboxTitle(entity),
233
- onChange: onSelectListener,
307
+ onChange: onCheckboxChange,
308
+ onMouseDown: isDisable ? undefined : onCheckboxMouseDown,
234
309
  children: _jsx(CheckboxCell.Content, {
235
310
  children: value
236
311
  })
@@ -244,16 +319,32 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
244
319
  checked: state === SelectionState.CurrentPage || state === SelectionState.All,
245
320
  indeterminate: state === SelectionState.Partial,
246
321
  onChange: newValue => {
247
- var _a, _b;
322
+ var _a, _b, _c;
248
323
  if (newValue) {
249
324
  const newState = checkboxEmitsCurrentPage ? SelectionState.CurrentPage : SelectionState.All;
250
325
  setState(newState);
251
326
  onChangeSelectionState(newState);
327
+ } else if (isInfinite) {
328
+ onChangeSelectionState(SelectionState.None);
329
+ } else if (selectable.allowExclusions && ((_a = selectable.selection) === null || _a === void 0 ? void 0 : _a.all)) {
330
+ // MYG-142234: in exclusion mode, `selected` holds excluded ids. Unchecking
331
+ // the header must add the current page's ids to that exclusion set and
332
+ // keep `all: true` - it must never be treated as an inclusion list, or
333
+ // every other page's selection would be silently wiped out.
334
+ const currentPageIds = getCurrentPageSelection(entities, wrappedSelectable);
335
+ const newExcluded = new Set([...selectable.selection.selected, ...currentPageIds]);
336
+ const newState = calculateSelectionState(entities, newExcluded, true, checkboxVisible, checkboxDisabled, selectable.strategy);
337
+ setState(newState);
338
+ selectable.onSelect({
339
+ selected: [...newExcluded],
340
+ all: true
341
+ });
342
+ setSelectMode(true);
252
343
  } else {
253
344
  // Intentionally different from onSelect(None) ("Deselect all" menu item, which clears everything).
254
345
  // Unchecking the header checkbox only removes the current page from the selection, preserving other pages.
255
- const currentPageIds = getCurrentPageSelection(entities, selectable);
256
- const remaining = ((_b = (_a = selectable.selection) === null || _a === void 0 ? void 0 : _a.selected) !== null && _b !== void 0 ? _b : []).filter(id => !currentPageIds.has(id));
346
+ const currentPageIds = getCurrentPageSelection(entities, wrappedSelectable);
347
+ const remaining = ((_c = (_b = selectable.selection) === null || _b === void 0 ? void 0 : _b.selected) !== null && _c !== void 0 ? _c : []).filter(id => !currentPageIds.has(id));
257
348
  const newState = remaining.length > 0 ? SelectionState.Partial : SelectionState.None;
258
349
  setState(newState);
259
350
  selectable.onSelect({
@@ -263,7 +354,7 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
263
354
  setSelectMode(remaining.length > 0);
264
355
  }
265
356
  },
266
- calculateSelectionState: () => selectableState,
357
+ calculateSelectionState: () => selectionMenuState,
267
358
  checkboxInHeader: checkboxInHeaderValue,
268
359
  header: selectableHeader,
269
360
  onSelect: newState => {
@@ -276,7 +367,7 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
276
367
  return cell;
277
368
  }
278
369
  };
279
- }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onSelectListener, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, selectableState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
370
+ }, [checkboxDisabled, checkboxTitle, checkboxVisible, headerTitle, onChangeSelectionState, onCheckboxChange, onCheckboxMouseDown, hasSelectable, checkboxEmitsCurrentPage, checkboxInHeaderValue, selectableHeader, selectableTurnOffSelectAll, isInfinite, selectable, wrappedSelectable, selectionMenuState, state, isMobile, checkboxPlaceholder, isEntityChecked, entities, setSelectMode]);
280
371
  const selectableFeedWrapper = useCallback((primaryData, secondaryData, entity, isNested) => {
281
372
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
282
373
  if (!entity) {
@@ -285,6 +376,9 @@ export const useSelectableRows = (columns, entities, isMobile, selectMode, setSe
285
376
  if (!isMobile) {
286
377
  return [primaryData, secondaryData];
287
378
  }
379
+ if (entity.isLoading) {
380
+ return [primaryData, secondaryData];
381
+ }
288
382
  if (!selectMode) {
289
383
  return [primaryData, secondaryData];
290
384
  }
@@ -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,28 +1,64 @@
1
+ import { getChildrenForSelection } from "../../../commonHelpers/showMoreRow";
1
2
  import { SelectionState } from "../interfaces";
2
3
  export const calculateSelectionState = (entities, selections, all, checkboxVisible, checkboxDisabled, strategy) => {
3
4
  if (selections.size === 0) {
4
5
  return all ? SelectionState.All : SelectionState.None;
5
6
  }
7
+ if (all) {
8
+ // When `all` is true, `selections` holds the ids explicitly excluded from the
9
+ // otherwise-fully-selected set (see ISelectionValue), rather than included ids.
10
+ const isExcluded = (entity) => {
11
+ const children = strategy === "nested" ? getChildrenForSelection(entity) : undefined;
12
+ if (children && children.length > 0) {
13
+ return children.every(child => {
14
+ if (!checkboxVisible(child, true)) {
15
+ return true;
16
+ }
17
+ if (checkboxDisabled(child, true)) {
18
+ return true;
19
+ }
20
+ return selections.has(child.id);
21
+ });
22
+ }
23
+ return selections.has(entity.id);
24
+ };
25
+ const isPartiallyExcluded = (entity) => {
26
+ const children = strategy === "nested" ? getChildrenForSelection(entity) : undefined;
27
+ if (children && children.length > 0) {
28
+ return children.some(child => selections.has(child.id));
29
+ }
30
+ return selections.has(entity.id);
31
+ };
32
+ const relevantEntities = entities.filter(entity => checkboxVisible(entity, false) && !checkboxDisabled(entity, false));
33
+ if (relevantEntities.length === 0) {
34
+ return SelectionState.All;
35
+ }
36
+ if (relevantEntities.every(entity => !isPartiallyExcluded(entity))) {
37
+ return SelectionState.All;
38
+ }
39
+ return relevantEntities.every(entity => isExcluded(entity)) ? SelectionState.None : SelectionState.Partial;
40
+ }
6
41
  return entities.every(entity => {
7
- if (!checkboxVisible(entity)) {
42
+ if (!checkboxVisible(entity, false)) {
8
43
  return true;
9
44
  }
10
- if (checkboxDisabled(entity)) {
45
+ if (checkboxDisabled(entity, false)) {
11
46
  return true;
12
47
  }
13
48
  if (strategy === "nested") {
14
- if (entity.children) {
15
- return entity.children.every(child => {
16
- if (!checkboxVisible(child)) {
49
+ const children = getChildrenForSelection(entity);
50
+ if (children && children.length > 0) {
51
+ return children.every(child => {
52
+ if (!checkboxVisible(child, true)) {
17
53
  return true;
18
54
  }
19
- if (checkboxDisabled(child)) {
55
+ if (checkboxDisabled(child, true)) {
20
56
  return true;
21
57
  }
22
58
  return selections.has(child.id);
23
59
  });
24
60
  }
25
- return false;
61
+ return selections.has(entity.id);
26
62
  }
27
63
  return selections.has(entity.id);
28
64
  })
@@ -1,9 +1,11 @@
1
+ import { getChildrenForSelection } from "../../../commonHelpers/showMoreRow";
1
2
  export const checkRow = (selectionSet, selectable, entities, id, checked) => {
2
3
  const setValue = (rowId) => (checked ? selectionSet.add(rowId) : selectionSet.delete(rowId));
3
4
  if ((selectable === null || selectable === void 0 ? void 0 : selectable.strategy) === "nested") {
4
5
  const entity = entities.find(e => e.id === id);
5
- if (entity && entity.children && entity.children.length > 0) {
6
- entity.children.forEach(child => {
6
+ const children = entity ? getChildrenForSelection(entity) : undefined;
7
+ if (entity && children && children.length > 0) {
8
+ children.forEach(child => {
7
9
  const isChildVisible = selectable.checkboxVisible ? selectable.checkboxVisible(child, true) : true;
8
10
  const isChildEnabled = !selectable.checkboxDisabled || !selectable.checkboxDisabled(child, true);
9
11
  if (isChildVisible && isChildEnabled) {
@@ -1,12 +1,16 @@
1
+ import { getChildrenForSelection, isShowMoreRow } from "../../../commonHelpers/showMoreRow";
1
2
  export const getCurrentPageSelection = (entities, selectable) => {
2
3
  const newSelections = new Set();
3
4
  entities.forEach(entity => {
4
- const isVisible = (selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) ? selectable.checkboxVisible(entity) : true;
5
+ const isVisible = !entity.isLoading && !isShowMoreRow(entity) && ((selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) ? selectable.checkboxVisible(entity) : true);
5
6
  const isEnabled = !(selectable === null || selectable === void 0 ? void 0 : selectable.checkboxDisabled) || !selectable.checkboxDisabled(entity);
6
- if ((selectable === null || selectable === void 0 ? void 0 : selectable.strategy) === "nested") {
7
- (entity.children || []).forEach(child => {
8
- const isChildVisible = selectable.checkboxVisible ? selectable.checkboxVisible(child, true) : true;
9
- const isChildEnabled = !selectable.checkboxDisabled || !selectable.checkboxDisabled(child, true);
7
+ const children = (selectable === null || selectable === void 0 ? void 0 : selectable.strategy) === "nested" ? getChildrenForSelection(entity) : undefined;
8
+ if (children && children.length > 0) {
9
+ children.forEach(child => {
10
+ const isChildVisible = !child.isLoading &&
11
+ !isShowMoreRow(child) &&
12
+ ((selectable === null || selectable === void 0 ? void 0 : selectable.checkboxVisible) ? selectable.checkboxVisible(child, true) : true);
13
+ const isChildEnabled = !(selectable === null || selectable === void 0 ? void 0 : selectable.checkboxDisabled) || !selectable.checkboxDisabled(child, true);
10
14
  if (isChildVisible && isChildEnabled) {
11
15
  newSelections.add(child.id);
12
16
  }
@@ -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,24 @@
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
+ };
@@ -0,0 +1,2 @@
1
+ import { IDragSelectionRow } from "../interfaces";
2
+ export declare const getRangeIds: (rows: IDragSelectionRow[], fromId: string, toId: string, isSelectable: (row: IDragSelectionRow) => boolean) => string[];
@@ -0,0 +1,17 @@
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
+ };
@@ -2,7 +2,7 @@ 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 isRowChecked: <T extends IRowEntity<N>, N extends IEntityWithId>(selections: Set<string>, state: SelectionState, strategy: TSelectionStrategy | undefined, entity: T | N, isNested: boolean) => {
5
+ export declare const isRowChecked: <T extends IRowEntity<N>, N extends IEntityWithId>(selections: Set<string>, state: SelectionState, strategy: TSelectionStrategy | undefined, entity: T | N, isNested: boolean, checkboxVisible?: (e: T | N, isNested?: boolean) => boolean, checkboxDisabled?: (e: T | N, isNested?: boolean) => boolean) => {
6
6
  indeterminate: boolean;
7
7
  checked: boolean;
8
8
  };
@@ -1,16 +1,49 @@
1
+ import { getChildrenForSelection } from "../../../commonHelpers/showMoreRow";
1
2
  import { SelectionState } from "../interfaces";
2
- export const isRowChecked = (selections, state, strategy, entity, isNested) => {
3
+ // The full, un-capped children list, so children hidden behind a "+N more" row still count
4
+ // towards the parent checkbox state.
5
+ const getNestedChildren = (entity, strategy) => strategy === "nested" ? getChildrenForSelection(entity) : undefined;
6
+ // Children the parent checkbox can actually act on - the consumer may hide or disable some.
7
+ const filterSelectable = (children, checkboxVisible, checkboxDisabled) => children.filter(child => {
8
+ if (checkboxVisible && !checkboxVisible(child, true)) {
9
+ return false;
10
+ }
11
+ if (checkboxDisabled && checkboxDisabled(child, true)) {
12
+ return false;
13
+ }
14
+ return true;
15
+ });
16
+ export const isRowChecked = (selections, state, strategy, entity, isNested, checkboxVisible, checkboxDisabled) => {
3
17
  if (state === SelectionState.All) {
4
- return { indeterminate: false, checked: true };
18
+ // When the overall selection is "all", `selections` holds the ids that have been
19
+ // explicitly excluded from that selection (see ISelectionValue), not included ids.
20
+ if (isNested) {
21
+ return { indeterminate: false, checked: !selections.has(entity.id) };
22
+ }
23
+ const children = getNestedChildren(entity, strategy);
24
+ if (children && children.length > 0) {
25
+ const selectableChildren = filterSelectable(children, checkboxVisible, checkboxDisabled);
26
+ if (selectableChildren.length === 0) {
27
+ return { indeterminate: false, checked: true };
28
+ }
29
+ const allChildrenChecked = selectableChildren.every(child => !selections.has(child.id));
30
+ const someChildrenChecked = selectableChildren.some(child => !selections.has(child.id));
31
+ return { indeterminate: someChildrenChecked && !allChildrenChecked, checked: allChildrenChecked };
32
+ }
33
+ return { indeterminate: false, checked: !selections.has(entity.id) };
5
34
  }
6
35
  if (isNested) {
7
36
  return { indeterminate: false, checked: selections.has(entity.id) };
8
37
  }
9
- const mainEntity = entity;
10
- if (strategy === "nested" && mainEntity.children && mainEntity.children.length > 0) {
11
- const allChildrenSelected = mainEntity.children.every(child => selections.has(child.id));
12
- const someChildrenSelected = mainEntity.children.some(child => selections.has(child.id));
13
- return { indeterminate: someChildrenSelected, checked: allChildrenSelected };
38
+ const children = getNestedChildren(entity, strategy);
39
+ if (children && children.length > 0) {
40
+ const selectableChildren = filterSelectable(children, checkboxVisible, checkboxDisabled);
41
+ if (selectableChildren.length === 0) {
42
+ return { indeterminate: false, checked: false };
43
+ }
44
+ const allChildrenSelected = selectableChildren.every(child => selections.has(child.id));
45
+ const someChildrenSelected = selectableChildren.some(child => selections.has(child.id));
46
+ return { indeterminate: someChildrenSelected && !allChildrenSelected, checked: allChildrenSelected };
14
47
  }
15
48
  return { indeterminate: false, checked: selections.has(entity.id) };
16
49
  };
@@ -1,6 +1,6 @@
1
1
  import { IZenComponentProps, IZenGridItem } from "../commonHelpers/zenComponent";
2
2
  import { ReactNode } from "react";
3
- import { ISelectableRowsOptions } from "./selectable/useSelectableRows";
3
+ import { getEmptySelection, ISelectableRowsOptions } from "./selectable/useSelectableRows";
4
4
  import { ISortableOptions } from "./sortable/useSortableColumns";
5
5
  import { IFlexibleColumnsOptions } from "./flexible/useFlexibleColumns";
6
6
  import { IColumnComponent, IListColumnWrapper } from "../dataGrid/listColumn";
@@ -11,7 +11,6 @@ import { ITablePagination, TablePagination } from "./children/tablePagination";
11
11
  import { ITableEmpty, TableEmpty } from "./children/tableEmpty";
12
12
  import { ITableFooter, TableFooter } from "./children/tableFooter";
13
13
  import "./table.less";
14
- import { getEmptySelection } from "./selectable/useSelectableRows";
15
14
  import { ColumnSortDirection } from "./sortable/interfaces";
16
15
  import { getSortableValue } from "./sortable/useSortableColumns";
17
16
  import { ActionsColumn } from "../dataGrid/columns/actionsColumn/actionsColumn";