@geotab/zenith 3.16.0 → 3.17.0-beta.1

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 +97 -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 +98 -2
  282. package/package.json +15 -3
@@ -94,6 +94,20 @@ export const useNestedRows = (expandedRows, onExpand, columns, isMobile) => {
94
94
  }
95
95
  }, [intExpanded, onExpand]);
96
96
  const firstColumnId = useMemo(() => columns.length > 0 ? columns[0].id : null, [columns]);
97
+ // `announceState` adds aria-expanded to the button itself. Only the feed needs it: the desktop
98
+ // grid is a treegrid whose <tr> already carries aria-expanded (see dataGrid/row/row.tsx), and
99
+ // repeating it on the control inside that row would announce the state twice.
100
+ const renderExpandButton = useCallback((isExpanded, onExpandCallback, announceState = false) => _jsx("button", {
101
+ className: "zen-nested-button__button",
102
+ onClick: onExpandCallback,
103
+ "aria-expanded": announceState ? isExpanded : undefined,
104
+ "aria-label": isExpanded ? translate("Collapse") : translate("Expand"),
105
+ children: isExpanded ? _jsx(IconChevronTop, {
106
+ size: "large"
107
+ }) : _jsx(IconChevronBottom, {
108
+ size: "large"
109
+ })
110
+ }), [translate]);
97
111
  const wrapper = useMemo(() => ({
98
112
  name: NestedWrapperName,
99
113
  render(value, entity, isNested) {
@@ -113,16 +127,7 @@ export const useNestedRows = (expandedRows, onExpand, columns, isMobile) => {
113
127
  if ("children" in entity) {
114
128
  return _jsxs("div", {
115
129
  className: "zen-nested-button",
116
- children: [_jsx("button", {
117
- className: "zen-nested-button__button",
118
- onClick: onExpandCallback,
119
- "aria-label": isExpanded ? translate("Collapse") : translate("Expand"),
120
- children: isExpanded ? _jsx(IconChevronTop, {
121
- size: "large"
122
- }) : _jsx(IconChevronBottom, {
123
- size: "large"
124
- })
125
- }), _jsx("div", {
130
+ children: [renderExpandButton(isExpanded, onExpandCallback), _jsx("div", {
126
131
  className: "zen-nested-button__content",
127
132
  children: value
128
133
  })]
@@ -133,7 +138,7 @@ export const useNestedRows = (expandedRows, onExpand, columns, isMobile) => {
133
138
  renderHeader(title) {
134
139
  return title;
135
140
  }
136
- }), [expanded, onExpandedChange, isMobile, translate]);
141
+ }), [expanded, onExpandedChange, isMobile, renderExpandButton]);
137
142
  const nestedColumns = useMemo(() => {
138
143
  const newColumns = columns.map(c => Object.assign({}, c));
139
144
  // Add nested wrapper to the first column
@@ -159,16 +164,7 @@ export const useNestedRows = (expandedRows, onExpand, columns, isMobile) => {
159
164
  };
160
165
  return [_jsxs("div", {
161
166
  className: "zen-nested-button",
162
- children: [_jsx("button", {
163
- className: "zen-nested-button__button",
164
- onClick: onExpandCallback,
165
- "aria-label": isExpanded ? translate("Collapse") : translate("Expand"),
166
- children: isExpanded ? _jsx(IconChevronTop, {
167
- size: "large"
168
- }) : _jsx(IconChevronBottom, {
169
- size: "large"
170
- })
171
- }), _jsx("div", {
167
+ children: [renderExpandButton(isExpanded, onExpandCallback, true), _jsx("div", {
172
168
  className: "zen-nested-button__content",
173
169
  children: primaryData
174
170
  })]
@@ -176,7 +172,7 @@ export const useNestedRows = (expandedRows, onExpand, columns, isMobile) => {
176
172
  className: "zen-nested-button__padding",
177
173
  children: secondaryData
178
174
  }, "nested-value")];
179
- }, [expanded, onExpandedChange, isMobile, translate]);
175
+ }, [expanded, onExpandedChange, isMobile, renderExpandButton]);
180
176
  return {
181
177
  nestedColumns,
182
178
  nestedFeedWrapper,
@@ -0,0 +1,41 @@
1
+ import { ReactNode } from "react";
2
+ import { IEntityWithId } from "../../commonHelpers/entity";
3
+ import { IShowMoreOptions } from "./nestedData";
4
+ export type IUseShowMoreConfig<TParent> = {
5
+ /** Passed through to `IShowMoreOptions.cap`. Defaults to 10. */
6
+ cap?: number;
7
+ /** Passed through to `IShowMoreOptions.label`. */
8
+ label?: (remaining: number) => ReactNode;
9
+ } & ({
10
+ /**
11
+ * Runs in addition to the reveal, not instead of it - the hook marks the parent revealed
12
+ * either way. Use it for side effects such as analytics.
13
+ */
14
+ onClick?: (parent: TParent) => void;
15
+ href?: never;
16
+ } | {
17
+ /**
18
+ * Passed straight through to `IShowMoreOptions.href`. In this mode "+N more" navigates
19
+ * instead of revealing in place, so the hook keeps no reveal state and `onCollapse`
20
+ * does nothing.
21
+ */
22
+ href: (parent: TParent) => string;
23
+ onClick?: never;
24
+ });
25
+ /**
26
+ * Builds `NestedData`'s `showMore` option so consumers don't hand-roll the reveal state.
27
+ *
28
+ * Without `href`, this owns the "click +N more to reveal the rest in place" pattern: it tracks
29
+ * which parents have been revealed and derives `isUncapped` and `onClick` from that. Call the
30
+ * returned `onCollapse(parentId)` from your own `onExpand` when a parent collapses, so
31
+ * re-expanding it shows the capped view again instead of staying revealed.
32
+ *
33
+ * With `href`, the config is passed straight through and no reveal state exists.
34
+ *
35
+ * The returned `showMore` is referentially stable across renders - config callbacks are read
36
+ * through a ref, so passing an inline config object does not produce a new `showMore` each render.
37
+ */
38
+ export declare const useShowMore: <TParent extends IEntityWithId>(config?: IUseShowMoreConfig<TParent>) => {
39
+ showMore: IShowMoreOptions<TParent>;
40
+ onCollapse: (parentId: string) => void;
41
+ };
@@ -0,0 +1,52 @@
1
+ import { useCallback, useMemo, useRef, useState } from "react";
2
+ /**
3
+ * Builds `NestedData`'s `showMore` option so consumers don't hand-roll the reveal state.
4
+ *
5
+ * Without `href`, this owns the "click +N more to reveal the rest in place" pattern: it tracks
6
+ * which parents have been revealed and derives `isUncapped` and `onClick` from that. Call the
7
+ * returned `onCollapse(parentId)` from your own `onExpand` when a parent collapses, so
8
+ * re-expanding it shows the capped view again instead of staying revealed.
9
+ *
10
+ * With `href`, the config is passed straight through and no reveal state exists.
11
+ *
12
+ * The returned `showMore` is referentially stable across renders - config callbacks are read
13
+ * through a ref, so passing an inline config object does not produce a new `showMore` each render.
14
+ */
15
+ export const useShowMore = (config) => {
16
+ const [revealedParents, setRevealedParents] = useState(new Set());
17
+ // Latest-ref so an inline config object - the common call shape - doesn't change `showMore`'s
18
+ // identity every render. Written during render because `href` is read while NestedData
19
+ // renders, so an effect-updated ref would be a render stale on first paint.
20
+ const configRef = useRef(config);
21
+ configRef.current = config;
22
+ const cap = config === null || config === void 0 ? void 0 : config.cap;
23
+ const hasLabel = !!(config === null || config === void 0 ? void 0 : config.label);
24
+ const hasHref = !!(config && "href" in config && config.href);
25
+ const showMore = useMemo(() => {
26
+ const label = hasLabel ? (remaining) => { var _a, _b; return (_b = (_a = configRef.current) === null || _a === void 0 ? void 0 : _a.label) === null || _b === void 0 ? void 0 : _b.call(_a, remaining); } : undefined;
27
+ if (hasHref) {
28
+ return { cap, label, href: (parent) => configRef.current.href(parent) };
29
+ }
30
+ return {
31
+ cap,
32
+ label,
33
+ isUncapped: (parent) => revealedParents.has(parent.id),
34
+ onClick: (parent) => {
35
+ var _a, _b;
36
+ setRevealedParents(prev => (prev.has(parent.id) ? prev : new Set(prev).add(parent.id)));
37
+ (_b = (_a = configRef.current) === null || _a === void 0 ? void 0 : _a.onClick) === null || _b === void 0 ? void 0 : _b.call(_a, parent);
38
+ }
39
+ };
40
+ }, [revealedParents, cap, hasLabel, hasHref]);
41
+ const onCollapse = useCallback((parentId) => {
42
+ setRevealedParents(prev => {
43
+ if (!prev.has(parentId)) {
44
+ return prev;
45
+ }
46
+ const next = new Set(prev);
47
+ next.delete(parentId);
48
+ return next;
49
+ });
50
+ }, []);
51
+ return { showMore, onCollapse };
52
+ };
@@ -5,6 +5,23 @@ export declare enum SelectionState {
5
5
  None = "none"
6
6
  }
7
7
  export interface ISelectionValue {
8
+ /**
9
+ * Whether every selectable row across every page is selected.
10
+ */
8
11
  all: boolean;
12
+ /**
13
+ * Included IDs by default. With `ISelectableRowsOptions.allowExclusions: true`,
14
+ * these are excluded IDs while `all` is true, and included IDs while `all` is false.
15
+ * Consumers opting in must resolve the effective selection before running bulk actions.
16
+ */
9
17
  selected: string[];
10
18
  }
19
+ /**
20
+ * One checkbox row in the order it is rendered. Expanded nested rows are part of this list,
21
+ * directly after their parent, so a drag or shift-click range can span nesting levels the
22
+ * same way it spans sibling rows.
23
+ */
24
+ export interface IDragSelectionRow {
25
+ id: string;
26
+ isNested: boolean;
27
+ }
@@ -0,0 +1,10 @@
1
+ import { MouseEvent as ReactMouseEvent, RefObject } from "react";
2
+ import { IDragSelectionRow } from "./interfaces";
3
+ /**
4
+ * @param rows every checkbox row in render order, expanded nested rows included, so ranges can
5
+ * span nesting levels.
6
+ */
7
+ export declare const useDragSelection: (rows: IDragSelectionRow[], gridRef: RefObject<HTMLElement | null> | undefined, onBatchSelect: (rangeIds: string[], select: boolean, base: Set<string>) => void, getBaseSelection: () => Set<string>, isSelectable: (row: IDragSelectionRow) => boolean, isEnabled: boolean) => {
8
+ onCheckboxMouseDown: (id: string, checked: boolean, e: ReactMouseEvent) => void;
9
+ suppressNextChangeRef: RefObject<boolean>;
10
+ };
@@ -0,0 +1,141 @@
1
+ import { useCallback, useEffect, useRef } from "react";
2
+ import { zen } from "../../utils/zen";
3
+ import { getRangeIds } from "./utils/getRangeIds";
4
+ const DRAG_CLASS = "zen-not-selectable";
5
+ /**
6
+ * @param rows every checkbox row in render order, expanded nested rows included, so ranges can
7
+ * span nesting levels.
8
+ */
9
+ export const useDragSelection = (rows, gridRef, onBatchSelect, getBaseSelection, isSelectable, isEnabled) => {
10
+ const rowsRef = useRef(rows);
11
+ rowsRef.current = rows;
12
+ const getBaseSelectionRef = useRef(getBaseSelection);
13
+ getBaseSelectionRef.current = getBaseSelection;
14
+ const onBatchSelectRef = useRef(onBatchSelect);
15
+ onBatchSelectRef.current = onBatchSelect;
16
+ const isSelectableRef = useRef(isSelectable);
17
+ isSelectableRef.current = isSelectable;
18
+ const isEnabledRef = useRef(isEnabled);
19
+ isEnabledRef.current = isEnabled;
20
+ const anchorIdRef = useRef(null);
21
+ const anchorSelectRef = useRef(true);
22
+ const baseSelectedRef = useRef(new Set());
23
+ const isDraggingRef = useRef(false);
24
+ const movedRef = useRef(false);
25
+ const lastResultKeyRef = useRef("");
26
+ const lastPointRef = useRef(null);
27
+ const suppressNextChangeRef = useRef(false);
28
+ const attachedGridElementRef = useRef(null);
29
+ const emitRange = useCallback((currentId) => {
30
+ const anchorId = anchorIdRef.current;
31
+ if (anchorId === null) {
32
+ return;
33
+ }
34
+ const range = getRangeIds(rowsRef.current, anchorId, currentId, isSelectableRef.current);
35
+ if (range.length === 0) {
36
+ return;
37
+ }
38
+ const select = anchorSelectRef.current;
39
+ const key = `${select}|${range.join(",")}`;
40
+ if (key === lastResultKeyRef.current) {
41
+ return;
42
+ }
43
+ lastResultKeyRef.current = key;
44
+ onBatchSelectRef.current(range, select, baseSelectedRef.current);
45
+ }, []);
46
+ const extend = useCallback((x, y) => {
47
+ var _a, _b;
48
+ lastPointRef.current = { x, y };
49
+ const row = (_b = (_a = zen.document) === null || _a === void 0 ? void 0 : _a.elementFromPoint(x, y)) === null || _b === void 0 ? void 0 : _b.closest("[data-row-id]");
50
+ const currentId = row === null || row === void 0 ? void 0 : row.getAttribute("data-row-id");
51
+ if (!currentId) {
52
+ return;
53
+ }
54
+ if (currentId !== anchorIdRef.current) {
55
+ movedRef.current = true;
56
+ }
57
+ if (!movedRef.current) {
58
+ return;
59
+ }
60
+ emitRange(currentId);
61
+ }, [emitRange]);
62
+ const onMouseMove = useCallback((e) => {
63
+ extend(e.clientX, e.clientY);
64
+ }, [extend]);
65
+ const onScroll = useCallback(() => {
66
+ const point = lastPointRef.current;
67
+ if (point) {
68
+ extend(point.x, point.y);
69
+ }
70
+ }, [extend]);
71
+ const endDrag = useCallback(() => {
72
+ var _a, _b, _c, _d;
73
+ if (!isDraggingRef.current) {
74
+ return;
75
+ }
76
+ isDraggingRef.current = false;
77
+ if (movedRef.current) {
78
+ suppressNextChangeRef.current = true;
79
+ }
80
+ (_a = zen.document) === null || _a === void 0 ? void 0 : _a.removeEventListener("mousemove", onMouseMove);
81
+ (_b = zen.document) === null || _b === void 0 ? void 0 : _b.removeEventListener("mouseup", endDrag);
82
+ (_c = attachedGridElementRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener("scroll", onScroll);
83
+ (_d = attachedGridElementRef.current) === null || _d === void 0 ? void 0 : _d.classList.remove(DRAG_CLASS);
84
+ attachedGridElementRef.current = null;
85
+ }, [onMouseMove, onScroll]); // eslint-disable-line react-hooks/exhaustive-deps
86
+ const onCheckboxMouseDown = useCallback((id, checked, e) => {
87
+ var _a, _b, _c, _d, _e;
88
+ // Right-click between drag-end and the trailing click must not clear suppression.
89
+ if (e.button === 0) {
90
+ suppressNextChangeRef.current = false;
91
+ }
92
+ if (!isEnabledRef.current || e.button !== 0) {
93
+ return;
94
+ }
95
+ if (e.shiftKey && anchorIdRef.current !== null) {
96
+ e.preventDefault();
97
+ const anchorId = anchorIdRef.current;
98
+ const anchorInList = rowsRef.current.some(row => row.id === anchorId);
99
+ if (!anchorInList) {
100
+ // The anchor is no longer rendered (e.g. its parent was collapsed, or the list was
101
+ // re-filtered/paginated since). Drop the stale anchor and let the target row's own
102
+ // onChange fire normally, rather than swallowing it as a silent no-op.
103
+ anchorIdRef.current = null;
104
+ return;
105
+ }
106
+ // Gmail-style: every shift-click re-applies the range to the selection captured when
107
+ // the anchor was clicked, so moving the target closer to the anchor deselects the rows
108
+ // that dropped out of the range. Shift-clicking the anchor itself collapses the range
109
+ // to nothing, restoring that captured selection — the anchor included.
110
+ const range = id === anchorId ? [] : getRangeIds(rowsRef.current, anchorId, id, isSelectableRef.current);
111
+ // Suppress even when the range is empty to prevent the anchor from double-toggling
112
+ // on a same-row shift-click.
113
+ suppressNextChangeRef.current = true;
114
+ onBatchSelectRef.current(range, anchorSelectRef.current, baseSelectedRef.current);
115
+ return;
116
+ }
117
+ anchorIdRef.current = id;
118
+ anchorSelectRef.current = !checked;
119
+ baseSelectedRef.current = getBaseSelectionRef.current();
120
+ isDraggingRef.current = true;
121
+ movedRef.current = false;
122
+ lastResultKeyRef.current = "";
123
+ lastPointRef.current = { x: e.clientX, y: e.clientY };
124
+ attachedGridElementRef.current = (_a = gridRef === null || gridRef === void 0 ? void 0 : gridRef.current) !== null && _a !== void 0 ? _a : null;
125
+ (_b = attachedGridElementRef.current) === null || _b === void 0 ? void 0 : _b.classList.add(DRAG_CLASS);
126
+ (_c = zen.document) === null || _c === void 0 ? void 0 : _c.addEventListener("mousemove", onMouseMove);
127
+ (_d = zen.document) === null || _d === void 0 ? void 0 : _d.addEventListener("mouseup", endDrag);
128
+ (_e = attachedGridElementRef.current) === null || _e === void 0 ? void 0 : _e.addEventListener("scroll", onScroll);
129
+ }, [gridRef, onMouseMove, onScroll, endDrag]);
130
+ // Drop the anchor only once its row is actually gone (collapsed, filtered, paginated away).
131
+ // Keying this on the `rows` array identity instead would clear the anchor on every render for
132
+ // any caller that rebuilds its entity list each time - NestedData does exactly that - which
133
+ // silently turns every shift-click into a plain single-row toggle.
134
+ useEffect(() => {
135
+ if (anchorIdRef.current !== null && !rows.some(row => row.id === anchorIdRef.current)) {
136
+ anchorIdRef.current = null;
137
+ }
138
+ }, [rows]);
139
+ useEffect(() => endDrag, [endDrag]);
140
+ return { onCheckboxMouseDown, suppressNextChangeRef };
141
+ };
@@ -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
  };