@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
@@ -135,7 +135,8 @@ const DropdownRaw = props => {
135
135
  mobileSheetStackingClassName,
136
136
  isError,
137
137
  firstParentNodeIsVisible,
138
- dataAnalyticsId
138
+ dataAnalyticsId,
139
+ sortSelectedToTop = false
139
140
  } = props;
140
141
  const {
141
142
  isFormSection
@@ -945,7 +946,7 @@ const DropdownRaw = props => {
945
946
  const currentAbort = abortToken.current;
946
947
  controlData(currentAbort.signal, newValue, state.isChecked);
947
948
  }, [controlData, state.isChecked]);
948
- const containerClassName = (0, classNames_1.classNames)(["zen-dropdown", isFormSection ? "zen-dropdown--form-item" : "", "zen-dropdown__container", className || ""]);
949
+ const containerClassName = (0, classNames_1.classNames)(["zen-dropdown", isFormSection || isFormItemVal ? "zen-dropdown--form-item" : "", "zen-dropdown__container", className || ""]);
949
950
  const handleCheckboxChange = (0, react_1.useCallback)(e => {
950
951
  const isChecked = e.target.checked;
951
952
  dispatchState({
@@ -1139,9 +1140,35 @@ const DropdownRaw = props => {
1139
1140
  }
1140
1141
  if (state.showList) {
1141
1142
  const isSearchMode = state.inputValue && !state.currentId;
1142
- const currentListData = (0, dropdownHelper_1.createListDataOptions)(state, translate, isSearchMode ? (0, dropdownHelper_1.sortDropdownItemArray)(state.listData, sortFn).slice(0, listLimit).filter(el => el.id !== state.rootId) :
1143
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1144
- (0, dropdownHelper_1.sortDropdownItemArray)(((_b = state.groupsMap[state.currentId || state.rootId]) === null || _b === void 0 ? void 0 : _b.children) || [], sortFn).slice(0, listLimit) || [], multiselect, currentAllSelected);
1143
+ // For the non-search path, applySortSelectedToTop must run BEFORE .slice(0, listLimit)
1144
+ // so that selected items located beyond listLimit in sort order are floated into the
1145
+ // visible window rather than being discarded by the clip.
1146
+ // In search mode sort-to-top is suspended (results appear in natural/sortFn order).
1147
+ let rawItems;
1148
+ let pinnedCount = 0;
1149
+ if (isSearchMode) {
1150
+ rawItems = (0, dropdownHelper_1.sortDropdownItemArray)(state.listData, sortFn).slice(0, listLimit).filter(el => el.id !== state.rootId);
1151
+ } else {
1152
+ const children = (0, dropdownHelper_1.sortDropdownItemArray)(((_b = state.groupsMap[state.currentId || state.rootId]) === null || _b === void 0 ? void 0 : _b.children) || [], sortFn);
1153
+ // hasApplyButton=false (default): uses the open-time snapshot — items don't jump
1154
+ // while the dropdown is open; sort applies on the next open (confirmed design intent).
1155
+ // hasApplyButton=true: uses globalSelectedIds (committed selection) — reordering
1156
+ // only takes effect after the user clicks "Apply".
1157
+ const idsForSort = hasApplyButton ? state.globalSelectedIds : state.sortedTopSnapshot;
1158
+ const floated = sortSelectedToTop ? (0, dropdownHelper_1.applySortSelectedToTop)(children, idsForSort) : children;
1159
+ rawItems = floated.slice(0, listLimit);
1160
+ if (sortSelectedToTop) {
1161
+ const selectedSet = new Set(idsForSort);
1162
+ pinnedCount = rawItems.filter(item => selectedSet.has(item.id)).length;
1163
+ }
1164
+ }
1165
+ const listData = (0, dropdownHelper_1.createListDataOptions)(state, translate, rawItems, multiselect, currentAllSelected);
1166
+ // Explicit bounds check (rather than relying on CheckboxListWithAction's own
1167
+ // `ind < optionsArr.length - 1` guard) keeps the "don't draw a trailing divider"
1168
+ // intent local to where the boundary is computed.
1169
+ const currentListData = multiselect && sortSelectedToTop && pinnedCount > 0 && pinnedCount < listData.length ? listData.map((opt, ind) => ind === pinnedCount - 1 ? Object.assign(Object.assign({}, opt), {
1170
+ divider: true
1171
+ }) : opt) : listData;
1145
1172
  return (0, jsx_runtime_1.jsx)(dropdownList_1.DropdownList, {
1146
1173
  onBackButtonClick: handleBackButtonClick,
1147
1174
  onSelectAllClick: isSearchMode ? handleSelectAllInSearch : handleSelectAllClick,
@@ -1175,7 +1202,7 @@ const DropdownRaw = props => {
1175
1202
  });
1176
1203
  }
1177
1204
  return null;
1178
- }, [state, isLoading, isQueryMode, fetchState === null || fetchState === void 0 ? void 0 : fetchState.isLoading, fetchState === null || fetchState === void 0 ? void 0 : fetchState.error, handleClearClick, handleCancelClick, handleApplyClick, hasApplyButton, memoizedWithFooter, translate, sortFn, listLimit, multiselect, currentAllSelected, handleBackButtonClick, handleSelectAllInSearch, handleSelectAllClick, handleSelect, handleChangeCurrentId, handleSingleSelection, isMobile, filterName, forceSelection, width, selectAllButton, memoizedIsApplyButtonDisabled, memoizedIsClearButtonDisabled, isCheckboxMode, handleCheckboxChange, checkboxLabel, selectListId]);
1205
+ }, [state, isLoading, isQueryMode, fetchState === null || fetchState === void 0 ? void 0 : fetchState.isLoading, fetchState === null || fetchState === void 0 ? void 0 : fetchState.error, handleClearClick, handleCancelClick, handleApplyClick, hasApplyButton, memoizedWithFooter, translate, sortFn, listLimit, multiselect, currentAllSelected, handleBackButtonClick, handleSelectAllInSearch, handleSelectAllClick, handleSelect, handleChangeCurrentId, handleSingleSelection, isMobile, filterName, forceSelection, width, selectAllButton, memoizedIsApplyButtonDisabled, memoizedIsClearButtonDisabled, isCheckboxMode, handleCheckboxChange, checkboxLabel, selectListId, sortSelectedToTop]);
1179
1206
  const currentStringFromSelected = isFullSelectionMode && hasApplyButton && state.globalIsAllSelected || isFullSelectionMode && !hasApplyButton && state.isAllSelected ? (0, dropdownHelper_1.getStringFromAllSelected)(state.groupsMap, translate, state.rootId) : (0, dropdownHelper_1.getStringFromSelected)(hasApplyButton ? state.globalSelectedIds : state.selectedIds, state.groupsMapSelected, translate, state.rootId);
1180
1207
  const memoizedCurrentSelection = (0, react_1.useMemo)(() => showSelection && !state.inputValue ? currentStringFromSelected : "", [showSelection, state.inputValue, currentStringFromSelected]);
1181
1208
  const parentTriggerWidth = ((_b = comboboxRef.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect().width) || 420;
@@ -1219,7 +1246,7 @@ const DropdownRaw = props => {
1219
1246
  isError: isError,
1220
1247
  disabled: disabled,
1221
1248
  count: showCounterPill ? countSelected : 0,
1222
- fullWidth: fullWidthTriggerButton,
1249
+ fullWidth: isFormItemVal && !searchField ? true : fullWidthTriggerButton,
1223
1250
  inputValue: state.inputValue,
1224
1251
  placeholder: placeholder || translate("Filter by group"),
1225
1252
  searchField: searchField && !isMobile ? searchField : false,
@@ -1235,7 +1262,8 @@ const DropdownRaw = props => {
1235
1262
  handleFocusOnPopup: handleFocusOnPopup,
1236
1263
  popupId: memoizedAllyPattern === "selectOnlyCombobox" ? selectListId : popupId,
1237
1264
  allyPattern: memoizedAllyPattern,
1238
- dataAnalyticsId: dataAnalyticsId
1265
+ dataAnalyticsId: dataAnalyticsId,
1266
+ isFormItem: isFormItemVal
1239
1267
  }, accessibilityProps)), (0, jsx_runtime_1.jsx)(dropdownPopup_1.DropdownPopup, {
1240
1268
  alignment: alignment,
1241
1269
  triggerRef: triggerRef,
@@ -23,9 +23,10 @@ interface IDropdownSearchableTrigger {
23
23
  autocomplete?: string;
24
24
  handleFocusOnPopup?: () => void;
25
25
  dataAnalyticsId?: string;
26
+ isFormItem?: boolean;
26
27
  }
27
28
  export declare const DropdownSearchableTrigger: {
28
- ({ value, className, onChange, placeholder, isOpenPopup, inputRef, handleClick, width, title, id, disabled, count, currentSelection, isError, fullWidth, ref, name, onBlur, popupId, autocomplete, handleFocusOnPopup, dataAnalyticsId, ...otherProps }: IDropdownSearchableTrigger): import("react/jsx-runtime").JSX.Element;
29
+ ({ value, className, onChange, placeholder, isOpenPopup, inputRef, handleClick, width, title, id, disabled, count, currentSelection, isError, fullWidth, ref, name, onBlur, popupId, autocomplete, handleFocusOnPopup, dataAnalyticsId, isFormItem, ...otherProps }: IDropdownSearchableTrigger): import("react/jsx-runtime").JSX.Element;
29
30
  displayName: string;
30
31
  };
31
32
  export declare const TRANSLATIONS: string[];
@@ -157,6 +157,8 @@ const useLanguage_1 = require("../utils/localization/useLanguage");
157
157
  const useDriveClassName_1 = require("../utils/theme/useDriveClassName");
158
158
  const useDrive_1 = require("../utils/theme/useDrive");
159
159
  const formSectionProvider_1 = require("../formSection/utils/formSectionProvider");
160
+ const getAriaAttributes_1 = require("../commonHelpers/getAriaAttributes");
161
+ const getNonAriaProps_1 = require("../commonHelpers/getNonAriaProps");
160
162
  const DropdownSearchableTrigger = _a => {
161
163
  var {
162
164
  value,
@@ -180,9 +182,10 @@ const DropdownSearchableTrigger = _a => {
180
182
  popupId,
181
183
  autocomplete,
182
184
  handleFocusOnPopup,
183
- dataAnalyticsId
185
+ dataAnalyticsId,
186
+ isFormItem
184
187
  } = _a,
185
- otherProps = __rest(_a, ["value", "className", "onChange", "placeholder", "isOpenPopup", "inputRef", "handleClick", "width", "title", "id", "disabled", "count", "currentSelection", "isError", "fullWidth", "ref", "name", "onBlur", "popupId", "autocomplete", "handleFocusOnPopup", "dataAnalyticsId"])
188
+ otherProps = __rest(_a, ["value", "className", "onChange", "placeholder", "isOpenPopup", "inputRef", "handleClick", "width", "title", "id", "disabled", "count", "currentSelection", "isError", "fullWidth", "ref", "name", "onBlur", "popupId", "autocomplete", "handleFocusOnPopup", "dataAnalyticsId", "isFormItem"])
186
189
  // eslint-disable-next-line complexity
187
190
  ;
188
191
  const {
@@ -201,6 +204,10 @@ const DropdownSearchableTrigger = _a => {
201
204
  } : {};
202
205
  const isLargeNumber = count && count > 99;
203
206
  const clearRef = (0, react_1.useRef)(null);
207
+ // The element with role="combobox" is the inner TextInputRaw, not the wrapper, so aria-* props
208
+ // have to reach the input. Everything else stays on the wrapper.
209
+ const accessibilityProps = (0, getAriaAttributes_1.getAriaAttributes)(otherProps);
210
+ const restProps = (0, getNonAriaProps_1.getNonAriaProps)(otherProps);
204
211
  const handleKeydown = e => {
205
212
  if (e.key === "Enter" && !isOpenPopup) {
206
213
  handleClick(true);
@@ -230,10 +237,10 @@ const DropdownSearchableTrigger = _a => {
230
237
  onChange(undefined);
231
238
  };
232
239
  return (0, jsx_runtime_1.jsxs)("div", Object.assign({
233
- className: (0, classNames_1.classNames)(["zen-dropdown-searchable-trigger", isError ? "zen-dropdown-searchable-trigger--error" : "", driveComponentClass || "", isFormSection ? "zen-dropdown-searchable-trigger--form-item" : "", disabled ? "zen-dropdown-searchable-trigger--disabled" : ""])
240
+ className: (0, classNames_1.classNames)(["zen-dropdown-searchable-trigger", isError ? "zen-dropdown-searchable-trigger--error" : "", driveComponentClass || "", isFormSection || isFormItem ? "zen-dropdown-searchable-trigger--form-item" : "", disabled ? "zen-dropdown-searchable-trigger--disabled" : ""])
234
241
  }, inputStyle, {
235
242
  ref: ref
236
- }, otherProps, {
243
+ }, restProps, {
237
244
  onClick: disabled ? () => {} : clickHandler,
238
245
  "data-analytics-id": dataAnalyticsId,
239
246
  children: [(0, jsx_runtime_1.jsxs)("div", {
@@ -242,7 +249,7 @@ const DropdownSearchableTrigger = _a => {
242
249
  children: [(0, jsx_runtime_1.jsx)("div", {
243
250
  className: "zen-dropdown-searchable-trigger__input-container",
244
251
  onKeyDown: handleKeydown,
245
- children: (0, jsx_runtime_1.jsx)(textInputRaw_1.TextInputRaw, {
252
+ children: (0, jsx_runtime_1.jsx)(textInputRaw_1.TextInputRaw, Object.assign({
246
253
  value: value,
247
254
  placeholder: currentSelection ? currentSelection : placeholder || translate("Filter by group"),
248
255
  className: (0, classNames_1.classNames)(["zen-dropdown-searchable-trigger__input", "zen-ellipsis", currentSelection ? "zen-dropdown-searchable-trigger__input--selected" : ""]),
@@ -258,7 +265,7 @@ const DropdownSearchableTrigger = _a => {
258
265
  ariaHaspopup: "dialog",
259
266
  role: "combobox",
260
267
  autocomplete: autocomplete
261
- })
268
+ }, accessibilityProps))
262
269
  }), count ? (0, jsx_runtime_1.jsx)("div", {
263
270
  className: "zen-dropdown-searchable-trigger__label-element",
264
271
  children: (0, jsx_runtime_1.jsx)("div", {
@@ -27,6 +27,7 @@ export interface IDropdownTrigger extends IZenComponentProps {
27
27
  handleFocusOnPopup?: () => void;
28
28
  allyPattern?: "selectOnlyCombobox" | "comboboxWithDialog" | "buttonWithDialog" | "buttonWithMenu";
29
29
  dataAnalyticsId?: string;
30
+ isFormItem?: boolean;
30
31
  }
31
- export declare const DropdownTrigger: ({ name, onBlur, isActive, id, triggerRef, searchField, placeholder, disabled, fullWidth, currentSelection, handleClick, inputValue, className, onSearchChange, width, title, triggerAriaLabel, count, inputRef, autocomplete, buttonType, isError, popupId, handleFocusOnPopup, allyPattern, dataAnalyticsId, ...otherProps }: IDropdownTrigger) => import("react/jsx-runtime").JSX.Element;
32
+ export declare const DropdownTrigger: ({ name, onBlur, isActive, id, triggerRef, searchField, placeholder, disabled, fullWidth, currentSelection, handleClick, inputValue, className, onSearchChange, width, title, triggerAriaLabel, count, inputRef, autocomplete, buttonType, isError, popupId, handleFocusOnPopup, allyPattern, dataAnalyticsId, isFormItem, ...otherProps }: IDropdownTrigger) => import("react/jsx-runtime").JSX.Element;
32
33
  export declare const TRANSLATIONS: string[];
@@ -19,13 +19,13 @@ const react_1 = require("react");
19
19
  const classNames_1 = require("../commonHelpers/classNames/classNames");
20
20
  const dropdownHelper_1 = require("./dropdownHelper");
21
21
  const DropdownTrigger = (_a) => {
22
- var { name, onBlur, isActive, id, triggerRef, searchField, placeholder, disabled, fullWidth, currentSelection, handleClick, inputValue, className, onSearchChange = () => { }, width, title, triggerAriaLabel, count, inputRef, autocomplete, buttonType, isError, popupId, handleFocusOnPopup, allyPattern = "buttonWithDialog", dataAnalyticsId } = _a, otherProps = __rest(_a, ["name", "onBlur", "isActive", "id", "triggerRef", "searchField", "placeholder", "disabled", "fullWidth", "currentSelection", "handleClick", "inputValue", "className", "onSearchChange", "width", "title", "triggerAriaLabel", "count", "inputRef", "autocomplete", "buttonType", "isError", "popupId", "handleFocusOnPopup", "allyPattern", "dataAnalyticsId"]);
22
+ var { name, onBlur, isActive, id, triggerRef, searchField, placeholder, disabled, fullWidth, currentSelection, handleClick, inputValue, className, onSearchChange = () => { }, width, title, triggerAriaLabel, count, inputRef, autocomplete, buttonType, isError, popupId, handleFocusOnPopup, allyPattern = "buttonWithDialog", dataAnalyticsId, isFormItem } = _a, otherProps = __rest(_a, ["name", "onBlur", "isActive", "id", "triggerRef", "searchField", "placeholder", "disabled", "fullWidth", "currentSelection", "handleClick", "inputValue", "className", "onSearchChange", "width", "title", "triggerAriaLabel", "count", "inputRef", "autocomplete", "buttonType", "isError", "popupId", "handleFocusOnPopup", "allyPattern", "dataAnalyticsId", "isFormItem"]);
23
23
  const elInpRef = (0, react_1.useRef)(null);
24
24
  const handleButtonClick = () => {
25
25
  handleClick(!isActive);
26
26
  };
27
27
  const allyTriggerProps = (0, react_1.useMemo)(() => (0, dropdownHelper_1.getAllyTriggerProps)(allyPattern), [allyPattern]);
28
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: searchField ? ((0, jsx_runtime_1.jsx)(dropdownSearchableTrigger_1.DropdownSearchableTrigger, Object.assign({ value: inputValue || "", name: name, onChange: onSearchChange, isOpenPopup: isActive, inputRef: inputRef || elInpRef, handleClick: handleClick, handleFocusOnPopup: handleFocusOnPopup, ref: triggerRef, width: width, placeholder: placeholder, disabled: disabled, id: id, title: title, count: count, currentSelection: currentSelection, className: className, isError: isError, fullWidth: fullWidth, popupId: popupId, autocomplete: autocomplete, dataAnalyticsId: dataAnalyticsId }, otherProps))) : ((0, jsx_runtime_1.jsx)(filterButton_1.FilterButton, Object.assign({ ref: triggerRef, id: id, name: name, onBlur: onBlur, className: (0, classNames_1.classNames)(["zen-dropdown__trigger-button", isError ? "zen-dropdown__trigger-button--error" : "", className || ""]), onClick: handleButtonClick, disabled: disabled, isActive: isActive, fullWidth: width ? true : fullWidth, maxWidth: width, minWidth: width, quantity: count || undefined, type: buttonType, title: title, ariaLabel: triggerAriaLabel || currentSelection || placeholder, "aria-expanded": isActive, "aria-controls": popupId }, allyTriggerProps, { dataAnalyticsId: dataAnalyticsId }, otherProps, { children: currentSelection ? ((0, jsx_runtime_1.jsx)("span", { className: (0, classNames_1.classNames)([
28
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: searchField ? ((0, jsx_runtime_1.jsx)(dropdownSearchableTrigger_1.DropdownSearchableTrigger, Object.assign({ value: inputValue || "", name: name, onChange: onSearchChange, isOpenPopup: isActive, inputRef: inputRef || elInpRef, handleClick: handleClick, handleFocusOnPopup: handleFocusOnPopup, ref: triggerRef, width: width, placeholder: placeholder, disabled: disabled, id: id, title: title, count: count, currentSelection: currentSelection, className: className, isError: isError, fullWidth: fullWidth, popupId: popupId, autocomplete: autocomplete, dataAnalyticsId: dataAnalyticsId, isFormItem: isFormItem }, otherProps))) : ((0, jsx_runtime_1.jsx)(filterButton_1.FilterButton, Object.assign({ ref: triggerRef, id: id, name: name, onBlur: onBlur, className: (0, classNames_1.classNames)(["zen-dropdown__trigger-button", isError ? "zen-dropdown__trigger-button--error" : "", className || ""]), onClick: handleButtonClick, disabled: disabled, isActive: isActive, fullWidth: width ? true : fullWidth, maxWidth: width, minWidth: width, quantity: count || undefined, type: buttonType, title: title, ariaLabel: triggerAriaLabel || currentSelection || placeholder, "aria-expanded": isActive, "aria-controls": popupId }, allyTriggerProps, { dataAnalyticsId: dataAnalyticsId }, otherProps, { children: currentSelection ? ((0, jsx_runtime_1.jsx)("span", { className: (0, classNames_1.classNames)([
29
29
  "zen-dropdown__trigger-button-text",
30
30
  buttonType ? `zen-dropdown__trigger-button-text--${buttonType.toString()}` : ""
31
31
  ]), children: currentSelection })) : (placeholder) }))) }));
@@ -31,6 +31,13 @@ export interface IDropdownState {
31
31
  defaultValueIsChecked?: boolean;
32
32
  globalIsChecked?: boolean;
33
33
  firstParentNodeIsVisible?: boolean;
34
+ /**
35
+ * Snapshot of `selectedIds` captured when the dropdown transitions from closed to open
36
+ * (sortSelectedToTop, hasApplyButton=false path). Captured in the reducer — rather than via a
37
+ * ref mutated during render — so it is safe under concurrent rendering (an interrupted/discarded
38
+ * render can't cause a stale snapshot to be reused) and is directly testable via dispatch.
39
+ */
40
+ sortedTopSnapshot: string[];
34
41
  }
35
42
  export interface IStateReducer extends Reducer<IDropdownState, TStateAction> {
36
43
  }
@@ -62,5 +69,6 @@ export declare const getInitialState: (isFullSelectionMode: boolean, comboItems:
62
69
  listLimit: number;
63
70
  resultsExceedListLimit: boolean;
64
71
  firstParentNodeIsVisible: boolean | undefined;
72
+ sortedTopSnapshot: string[];
65
73
  };
66
74
  export declare function stateReducer(state: IDropdownState, action: TStateAction): IDropdownState;
@@ -51,7 +51,8 @@ const getInitialState = (isFullSelectionMode, comboItems, selection, listLimit,
51
51
  globalIsChecked: isChecked,
52
52
  listLimit,
53
53
  resultsExceedListLimit: false,
54
- firstParentNodeIsVisible: firstParentNodeIsVisible
54
+ firstParentNodeIsVisible: firstParentNodeIsVisible,
55
+ sortedTopSnapshot: selection
55
56
  };
56
57
  };
57
58
  exports.getInitialState = getInitialState;
@@ -104,7 +105,9 @@ function stateReducer(state, action) {
104
105
  case stateActionType_1.StateActionType.SetCurrentId:
105
106
  return Object.assign(Object.assign({}, state), { currentId: payload || undefined });
106
107
  case stateActionType_1.StateActionType.SetIsOpenCombo:
107
- return Object.assign(Object.assign({}, state), { isOpenCombo: payload });
108
+ return Object.assign(Object.assign({}, state), { isOpenCombo: payload,
109
+ // Capture the sortSelectedToTop snapshot exactly on the closed→open transition.
110
+ sortedTopSnapshot: payload && !state.isOpenCombo ? [...state.selectedIds] : state.sortedTopSnapshot });
108
111
  case stateActionType_1.StateActionType.ResetSelection:
109
112
  return Object.assign(Object.assign({}, state), { selectedIds: [...state.defaultValue], isAllSelected: state.defaultValueIsAllSelected, isChecked: typeof state.isChecked === "boolean" ? state.defaultValueIsChecked || false : undefined });
110
113
  case stateActionType_1.StateActionType.ResetStateToGlobal:
@@ -15,6 +15,14 @@ export interface IDropdownRawItem extends IEntityWithId {
15
15
  children?: IEntityWithId[];
16
16
  color?: IColor;
17
17
  disabled?: boolean;
18
+ /** When true, renders a 1px separator line below this item. Purely visual — does not affect selection or keyboard navigation. */
19
+ divider?: boolean;
20
+ /**
21
+ * When true, renders the item label in `--text-error-message` red. Visual signal only — does not prevent selection.
22
+ * Only applies in single-select (SelectList) mode; ignored in multiselect (CheckboxListWithAction).
23
+ * Disabled+destructive renders with `--accents-error--main` (#ffeceb) on a transparent background, no hover feedback.
24
+ */
25
+ destructive?: boolean;
18
26
  }
19
27
  interface IFetchState<T> {
20
28
  data: T | undefined;
@@ -69,6 +77,34 @@ interface IDropdownBase extends IChipsParent {
69
77
  mobileSheetStackingClassName?: string;
70
78
  firstParentNodeIsVisible?: boolean;
71
79
  dataAnalyticsId?: string;
80
+ /**
81
+ * When `true`, floats currently-selected items to the top of the list when the dropdown opens.
82
+ * Selected items maintain their relative order among themselves; unselected items maintain
83
+ * their relative order below.
84
+ *
85
+ * **Reactivity — sort applies on open, not live:**
86
+ * - `hasApplyButton=false` (default): the sort is snapshotted at open-time. Checking or
87
+ * unchecking items while the dropdown is open does **not** reorder the list immediately;
88
+ * the user closes and reopens the dropdown to see the updated order.
89
+ * - `hasApplyButton=true`: order reflects the last committed selection (`globalSelectedIds`),
90
+ * so reordering only takes effect after the user clicks "Apply" and then reopens.
91
+ *
92
+ * In search mode the sort is suspended so results appear in natural/sortFn order.
93
+ * Compatible with `sortFn`: `sortFn` is applied within each group before concatenation.
94
+ * The float is applied before `listLimit` clipping, so selected items beyond the limit are
95
+ * still surfaced into the visible window.
96
+ * In nested lists the sort applies per-level: when the user drills into a sub-group, selected
97
+ * children of that group float to the top of that group's view, independent of other levels.
98
+ *
99
+ * **Known limitation — full-selection mode (`isAllSelected: true`):** when the value uses the
100
+ * `{ selected, isAllSelected: true }` form and `hasApplyButton=false`, `state.selectedIds`
101
+ * may be empty (all items are implicitly selected rather than enumerated). In this combination
102
+ * `sortSelectedToTop` silently does nothing — all items are already selected so the visual
103
+ * result is equivalent. If you need explicit float ordering, use the enumerated `selected`
104
+ * array form instead.
105
+ * @default false
106
+ */
107
+ sortSelectedToTop?: boolean;
72
108
  }
73
109
  interface IDropdownBaseDefault {
74
110
  disabled?: boolean;
@@ -2,7 +2,7 @@ import React, { RefObject } from "react";
2
2
  import "./filterButton.less";
3
3
  import { IZenComponentProps } from "../commonHelpers/zenComponent";
4
4
  import { ButtonType } from "../button/buttonType";
5
- export type TFilterButton = typeof ButtonType.Secondary | typeof ButtonType.Tertiary | typeof ButtonType.TertiaryBlack;
5
+ export type TFilterButton = typeof ButtonType.Primary | typeof ButtonType.Destructive | typeof ButtonType.Secondary | typeof ButtonType.Tertiary | typeof ButtonType.TertiaryBlack | typeof ButtonType.TertiaryDestructive;
6
6
  export interface IFilterButton extends IZenComponentProps {
7
7
  id?: string;
8
8
  name?: string;
@@ -8,7 +8,9 @@ const getOneLabelOneControlClasses_1 = require("../../utils/getLabelClasses/getO
8
8
  const useLabelAlign_1 = require("../useLabelAlign");
9
9
  const useMode_1 = require("../useMode");
10
10
  const useSectionType_1 = require("../useSectionType");
11
+ const TOP_ALIGN_CLASS = "zen-form-field-label--top";
11
12
  const useLabelClasses = (state) => {
13
+ var _a, _b;
12
14
  const type = (0, useSectionType_1.useSectionType)();
13
15
  const mode = (0, useMode_1.useMode)();
14
16
  const columns = (0, useColumns_1.useColumns)();
@@ -18,11 +20,15 @@ const useLabelClasses = (state) => {
18
20
  return;
19
21
  }
20
22
  const { labelClasses1, labelClasses2 } = (0, getLabelClasses_1.getLabelClasses)(state, columns, labelAlign, mode, type);
23
+ const effectiveLabelAlign1 = ((_a = state.elements.label1) === null || _a === void 0 ? void 0 : _a.labelAlign) || labelAlign;
24
+ const effectiveLabelAlign2 = ((_b = state.elements.label2) === null || _b === void 0 ? void 0 : _b.labelAlign) || labelAlign;
25
+ const topAlignClass1 = effectiveLabelAlign1 === "top" ? ` ${TOP_ALIGN_CLASS}` : "";
26
+ const topAlignClass2 = effectiveLabelAlign2 === "top" ? ` ${TOP_ALIGN_CLASS}` : "";
21
27
  if (state.elements.label1 && labelClasses1) {
22
- state.elements.label1.className = `${labelClasses1} ${state.elements.label1.className || ""}`;
28
+ state.elements.label1.className = `${labelClasses1}${topAlignClass1} ${state.elements.label1.className || ""}`;
23
29
  }
24
30
  if (state.elements.label2 && labelClasses2) {
25
- state.elements.label2.className = `${labelClasses2} ${state.elements.label2.className || ""}`;
31
+ state.elements.label2.className = `${labelClasses2}${topAlignClass2} ${state.elements.label2.className || ""}`;
26
32
  }
27
33
  };
28
34
  exports.useLabelClasses = useLabelClasses;
@@ -1 +1,2 @@
1
- export declare const applyLayoutPosition: (components: any, result: any) => void;
1
+ import { ReactElement } from "react";
2
+ export declare const applyLayoutPosition: (components: ReactElement[], result: ReactElement[]) => void;
@@ -7,108 +7,55 @@ const banner_1 = require("../../../banner/banner");
7
7
  const formLayoutTitle_1 = require("../../components/formLayoutTitle");
8
8
  const formLayoutColumnTitle_1 = require("../../components/columnTitle/formLayoutColumnTitle");
9
9
  const STATIC_COMPONENTS = [formStepper_1.FormStepper, formStepperButtons_1.FormStepperButtons, banner_1.Banner, formLayoutTitle_1.FormLayoutTitle, formLayoutColumnTitle_1.FormLayoutColumnTitle];
10
- const transform = components => {
11
- const state = {};
12
- // eslint-disable-next-line
13
- // @ts-ignore
14
- const movableComponents = components.filter((child) => !STATIC_COMPONENTS.includes(child.type));
15
- // 1. Initialize state
16
- components.forEach((child, index) => {
17
- // eslint-disable-next-line
18
- // @ts-ignore
19
- if (STATIC_COMPONENTS.includes(child.type)) {
20
- state[index] = {
21
- value: child,
22
- realPos: index,
23
- oldPos: null,
24
- newPos: null,
25
- newRealPos: index
26
- };
27
- return;
10
+ const isStaticComponent = (child) => STATIC_COMPONENTS.includes(child.type);
11
+ const getLayoutPosition = (child) => child.props.layoutPosition;
12
+ const findNextFreeIndex = (fields, startIndex) => {
13
+ for (let offset = 0; offset < fields.length; offset++) {
14
+ const candidateIndex = (startIndex + offset) % fields.length;
15
+ if (fields[candidateIndex] === null) {
16
+ return candidateIndex;
28
17
  }
29
- // eslint-disable-next-line
30
- // @ts-ignore
31
- const layoutPosition = child.props.layoutPosition;
32
- const newPositions = Object.values(state).map(field => field.newPos);
33
- let newPos;
34
- if (layoutPosition !== undefined) {
35
- newPos = layoutPosition < 0 ? 0 : layoutPosition > movableComponents.length - 1 ? movableComponents.length - 1 : layoutPosition;
36
- // eslint-disable-next-line
37
- if (newPositions.indexOf(newPos) !== -1) {
38
- if (layoutPosition >= movableComponents.length - 1) {
39
- newPos = 0;
40
- }
41
- // eslint-disable-next-line
42
- while (newPositions.indexOf(newPos) !== -1) {
43
- newPos++;
44
- }
45
- }
18
+ }
19
+ return -1;
20
+ };
21
+ const clampLayoutPosition = (layoutPosition, maxPosition) => Math.max(0, Math.min(Math.trunc(layoutPosition), maxPosition));
22
+ const transform = (components) => {
23
+ const movableComponents = components.filter(child => !isStaticComponent(child));
24
+ const positionedComponents = new Array(movableComponents.length).fill(null);
25
+ movableComponents.forEach(child => {
26
+ const layoutPosition = getLayoutPosition(child);
27
+ if (layoutPosition === undefined || !Number.isFinite(layoutPosition)) {
28
+ return;
46
29
  }
47
- else {
48
- newPos = null;
30
+ const clampedLayoutPosition = clampLayoutPosition(layoutPosition, movableComponents.length - 1);
31
+ const targetIndex = findNextFreeIndex(positionedComponents, clampedLayoutPosition);
32
+ if (targetIndex !== -1) {
33
+ positionedComponents[targetIndex] = child;
49
34
  }
50
- state[index] = {
51
- value: child,
52
- realPos: index,
53
- oldPos: movableComponents.indexOf(child),
54
- newPos: newPos,
55
- newRealPos: null
56
- };
57
35
  });
58
- // 2. Adjust positions
59
- components
60
- .sort((a, b) => a.props.layoutPosition - b.props.layoutPosition)
61
- .forEach((child, index) => {
62
- // eslint-disable-next-line
63
- // @ts-ignore
64
- if (STATIC_COMPONENTS.includes(child.type)) {
36
+ const placedComponents = new Set(positionedComponents);
37
+ movableComponents.forEach(child => {
38
+ if (placedComponents.has(child)) {
65
39
  return;
66
40
  }
67
- if (state[index].newPos !== null) {
68
- return;
69
- }
70
- // eslint-disable-next-line
71
- // @ts-ignore
72
- const layoutPosition = child.props.layoutPosition;
73
- const newPositions = Object.values(state)
74
- .map(field => field.newPos)
75
- .filter(pos => pos !== null);
76
- let newPos = 0;
77
- if (newPositions.indexOf(newPos) !== -1) {
78
- if (layoutPosition >= movableComponents.length - 1) {
79
- newPos = 0;
80
- }
81
- while (newPositions.indexOf(newPos) !== -1) {
82
- newPos++;
83
- }
41
+ const targetIndex = findNextFreeIndex(positionedComponents, 0);
42
+ if (targetIndex !== -1) {
43
+ positionedComponents[targetIndex] = child;
84
44
  }
85
- state[index] = {
86
- value: child,
87
- realPos: index,
88
- oldPos: movableComponents.indexOf(child),
89
- newPos: newPos,
90
- newRealPos: null
91
- };
92
45
  });
93
- // 3. Update newRealPos
94
- components.forEach((child) => {
95
- // eslint-disable-next-line
96
- // @ts-ignore
97
- if (STATIC_COMPONENTS.includes(child.type)) {
46
+ const reorderedMovableComponents = positionedComponents.filter((child) => child !== null);
47
+ const reorderedComponents = [...components];
48
+ let movableIndex = 0;
49
+ components.forEach((child, index) => {
50
+ if (isStaticComponent(child)) {
51
+ reorderedComponents[index] = child;
98
52
  return;
99
53
  }
100
- const index = components.indexOf(child);
101
- const newPos = state[index].newPos;
102
- const withOldPos = Object.values(state).find(field => field.oldPos === newPos);
103
- if (withOldPos) {
104
- state[index].newRealPos = withOldPos.realPos;
105
- }
54
+ reorderedComponents[index] = reorderedMovableComponents[movableIndex];
55
+ movableIndex++;
106
56
  });
107
- return Object.values(state)
108
- .sort((a, b) => a.newRealPos - b.newRealPos)
109
- .map(el => el.value);
57
+ return reorderedComponents;
110
58
  };
111
- // TODO: test with titles
112
59
  const applyLayoutPosition = (components, result) => {
113
60
  const state = transform(components);
114
61
  result.length = 0;
@@ -5,7 +5,7 @@ import { IMenuItem } from "../../../menu/components/menuItem";
5
5
  export interface ICustomContent {
6
6
  [key: string]: React.ReactElement<PropsWithChildren> | undefined;
7
7
  }
8
- export interface IHeaderCustomMenuComponent extends Pick<IMenuItem, "id" | "name" | "disabled" | "link" | "target" | "rel" | "icon"> {
8
+ export interface IHeaderCustomMenuComponent extends Pick<IMenuItem, "id" | "name" | "disabled" | "link" | "target" | "rel" | "icon" | "iconOpen" | "destructive"> {
9
9
  }
10
10
  export interface IHeaderCustomContent {
11
11
  content: ICustomContent | null;
@@ -109,7 +109,9 @@ const PageToolbarCollapsedItemsControl = ({
109
109
  link: child.props.link,
110
110
  target: child.props.target,
111
111
  rel: child.props.rel,
112
- icon: child.props.icon
112
+ icon: child.props.icon,
113
+ iconOpen: child.props.iconOpen,
114
+ destructive: child.props.destructive
113
115
  });
114
116
  items.push(el);
115
117
  }
@@ -122,7 +124,9 @@ const PageToolbarCollapsedItemsControl = ({
122
124
  link: child.props.link,
123
125
  target: child.props.target,
124
126
  rel: child.props.rel,
125
- icon: child.props.icon
127
+ icon: child.props.icon,
128
+ iconOpen: child.props.iconOpen,
129
+ destructive: child.props.destructive
126
130
  }, child.props.children);
127
131
  items.push(el);
128
132
  }
@@ -7,6 +7,8 @@ export interface IHeaderButton extends Omit<IButton, "onClick"> {
7
7
  important?: boolean;
8
8
  inContextMenu?: boolean;
9
9
  icon?: React.FC<IIcon>;
10
+ iconOpen?: boolean;
11
+ destructive?: boolean;
10
12
  iconPosition?: TButtonIconPosition;
11
13
  iconClasses?: string;
12
14
  iconSize?: TSvgIconSize;
@@ -14,6 +16,6 @@ export interface IHeaderButton extends Omit<IButton, "onClick"> {
14
16
  }
15
17
  export declare const HeaderButtonDisplayName = "HeaderButton";
16
18
  export declare const HeaderButton: {
17
- ({ id, children, icon, iconPosition, className, important, onClick, inContextMenu, ...restProps }: IHeaderButton): import("react/jsx-runtime").JSX.Element;
19
+ ({ id, children, icon, iconOpen, destructive, iconPosition, className, important, onClick, inContextMenu, disabled, focusableWhenDisabled, ...restProps }: IHeaderButton): import("react/jsx-runtime").JSX.Element;
18
20
  displayName: string;
19
21
  };
@@ -18,9 +18,11 @@ const textIconButton_1 = require("../textIconButton/textIconButton");
18
18
  const classNames_1 = require("../commonHelpers/classNames/classNames");
19
19
  exports.HeaderButtonDisplayName = "HeaderButton";
20
20
  const HeaderButton = (_a) => {
21
- var { id, children, icon, iconPosition = textIconButton_1.ButtonIconPosition.Start, className = "", important, onClick, inContextMenu } = _a, restProps = __rest(_a, ["id", "children", "icon", "iconPosition", "className", "important", "onClick", "inContextMenu"]);
21
+ var { id, children, icon, iconOpen, destructive, iconPosition = textIconButton_1.ButtonIconPosition.Start, className = "", important, onClick, inContextMenu, disabled, focusableWhenDisabled } = _a, restProps = __rest(_a, ["id", "children", "icon", "iconOpen", "destructive", "iconPosition", "className", "important", "onClick", "inContextMenu", "disabled", "focusableWhenDisabled"]);
22
22
  const fullClassName = (0, classNames_1.classNames)(["zen-header-button", className]);
23
- const props = Object.assign(Object.assign({}, restProps), { "data-important": important ? "1" : "0" });
23
+ const props = Object.assign(Object.assign({}, restProps), { disabled, "data-important": important ? "1" : "0",
24
+ // Defaults on when disabled; pass `focusableWhenDisabled={false}` to opt back into native `disabled`.
25
+ focusableWhenDisabled: focusableWhenDisabled !== null && focusableWhenDisabled !== void 0 ? focusableWhenDisabled : Boolean(disabled) });
24
26
  return icon ? ((0, jsx_runtime_1.jsx)(textIconButton_1.TextIconButton, Object.assign({ id: id, icon: icon, iconPosition: iconPosition, className: fullClassName, onClick: onClick ? e => onClick(id, e) : undefined }, props, { children: children }))) : ((0, jsx_runtime_1.jsx)(button_1.Button, Object.assign({ id: id, className: fullClassName, onClick: onClick ? e => onClick(id, e) : undefined }, props, { children: children })));
25
27
  };
26
28
  exports.HeaderButton = HeaderButton;
@@ -10,6 +10,8 @@ export interface IHeaderMenu extends Omit<IButton, "onClick"> {
10
10
  important?: boolean;
11
11
  inContextMenu?: boolean;
12
12
  icon?: FC<IIcon>;
13
+ iconOpen?: boolean;
14
+ destructive?: boolean;
13
15
  iconSize?: TSvgIconSize;
14
16
  alignment?: TAlignment;
15
17
  onlyIcon?: boolean;
@@ -24,7 +24,7 @@ const useDrive_1 = require("../utils/theme/useDrive");
24
24
  const useDriveClassName_1 = require("../utils/theme/useDriveClassName");
25
25
  exports.HeaderMenuDisplayName = "HeaderMenu";
26
26
  const HeaderMenu = (_a) => {
27
- var { name, children, icon, iconSize = "large", className = "", important, alignment = "bottom-end", inContextMenu, onlyIcon } = _a, restProps = __rest(_a, ["name", "children", "icon", "iconSize", "className", "important", "alignment", "inContextMenu", "onlyIcon"]);
27
+ var { name, children, icon, iconOpen, destructive, iconSize = "large", className = "", important, alignment = "bottom-end", inContextMenu, onlyIcon } = _a, restProps = __rest(_a, ["name", "children", "icon", "iconOpen", "destructive", "iconSize", "className", "important", "alignment", "inContextMenu", "onlyIcon"]);
28
28
  const isMobile = (0, useMobile_1.useMobile)();
29
29
  const isDrive = (0, useDrive_1.useDrive)();
30
30
  const driveClassName = (0, useDriveClassName_1.useDriveClassName)("zen-header-button-with-dropdown");