@geotab/zenith 3.10.0-beta.0 → 3.10.0-beta.2

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 (71) hide show
  1. package/README.md +9 -1
  2. package/dist/absolute/absolute.d.ts +7 -1
  3. package/dist/absolute/absolute.js +8 -4
  4. package/dist/betaPill/betaPill.d.ts +18 -2
  5. package/dist/betaPill/betaPill.js +11 -8
  6. package/dist/card/card.d.ts +2 -1
  7. package/dist/card/card.js +4 -2
  8. package/dist/card/components/title.d.ts +3 -1
  9. package/dist/card/components/title.js +5 -3
  10. package/dist/checkbox/checkbox.js +2 -2
  11. package/dist/checkboxListWithAction/checkboxListWithAction.js +2 -1
  12. package/dist/commonStyles/colors/colorsConstant.d.ts +44 -0
  13. package/dist/commonStyles/colors/colorsConstant.js +361 -0
  14. package/dist/commonStyles/typography/components/typographyItem.d.ts +8 -0
  15. package/dist/commonStyles/typography/components/typographyItem.js +45 -0
  16. package/dist/controlledPopup/controlledPopup.d.ts +2 -1
  17. package/dist/controlledPopup/controlledPopup.js +2 -2
  18. package/dist/dropdown/dropdown.js +1 -1
  19. package/dist/dropdownRaw/dropdownList.d.ts +4 -2
  20. package/dist/dropdownRaw/dropdownList.js +15 -36
  21. package/dist/dropdownRaw/dropdownRaw.js +9 -23
  22. package/dist/dropdownRaw/stateReducer/stateReducer.d.ts +1 -0
  23. package/dist/dropdownRaw/stateReducer/stateReducer.js +13 -14
  24. package/dist/dropdownRaw/stateReducer/stateReducerHelper.d.ts +1 -2
  25. package/dist/dropdownRaw/stateReducer/stateReducerHelper.js +5 -12
  26. package/dist/headerTitle/headerTitle.d.ts +9 -1
  27. package/dist/headerTitle/headerTitle.js +3 -2
  28. package/dist/index.css +52 -14
  29. package/dist/index.d.ts +3 -1
  30. package/dist/index.js +3 -1
  31. package/dist/menu/controlledMenu.d.ts +1 -0
  32. package/dist/menu/controlledMenu.js +2 -2
  33. package/dist/testHelpers/fakeFetch.d.ts +1 -0
  34. package/dist/testHelpers/fakeFetch.js +14 -0
  35. package/dist/testHelpers/geotab-axe/index.d.ts +2 -0
  36. package/dist/testHelpers/geotab-axe/index.js +81 -0
  37. package/dist/testHelpers/jestRetry.d.ts +0 -0
  38. package/dist/testHelpers/jestRetry.js +2 -0
  39. package/dist/testHelpers/renderAsync.d.ts +2 -0
  40. package/dist/testHelpers/renderAsync.js +12 -0
  41. package/dist/testHelpers/setReadonlyHtmlProperty.d.ts +1 -0
  42. package/dist/testHelpers/setReadonlyHtmlProperty.js +15 -0
  43. package/dist/testHelpers/styled-output.d.ts +30 -0
  44. package/dist/testHelpers/styled-output.js +42 -0
  45. package/esm/absolute/absolute.d.ts +7 -1
  46. package/esm/absolute/absolute.js +8 -4
  47. package/esm/betaPill/betaPill.d.ts +18 -2
  48. package/esm/betaPill/betaPill.js +11 -8
  49. package/esm/card/card.d.ts +2 -1
  50. package/esm/card/card.js +4 -2
  51. package/esm/card/components/title.d.ts +3 -1
  52. package/esm/card/components/title.js +5 -3
  53. package/esm/checkbox/checkbox.js +2 -2
  54. package/esm/checkboxListWithAction/checkboxListWithAction.js +2 -1
  55. package/esm/controlledPopup/controlledPopup.d.ts +2 -1
  56. package/esm/controlledPopup/controlledPopup.js +2 -2
  57. package/esm/dropdown/dropdown.js +1 -1
  58. package/esm/dropdownRaw/dropdownList.d.ts +4 -2
  59. package/esm/dropdownRaw/dropdownList.js +15 -36
  60. package/esm/dropdownRaw/dropdownRaw.js +10 -24
  61. package/esm/dropdownRaw/stateReducer/stateReducer.d.ts +1 -0
  62. package/esm/dropdownRaw/stateReducer/stateReducer.js +14 -15
  63. package/esm/dropdownRaw/stateReducer/stateReducerHelper.d.ts +1 -2
  64. package/esm/dropdownRaw/stateReducer/stateReducerHelper.js +3 -10
  65. package/esm/headerTitle/headerTitle.d.ts +9 -1
  66. package/esm/headerTitle/headerTitle.js +3 -2
  67. package/esm/index.d.ts +3 -1
  68. package/esm/index.js +1 -0
  69. package/esm/menu/controlledMenu.d.ts +1 -0
  70. package/esm/menu/controlledMenu.js +2 -2
  71. package/package.json +1 -1
@@ -148,33 +148,6 @@ injectString("zh-Hans", "Apply", "\u5E94\u7528");
148
148
  injectString("zh-TW", "Apply", "\u5957\u7528");
149
149
  injectString("ro-RO", "Apply", "Aplica\u021Bi");
150
150
  injectString("ar-SA", "Apply", "\u062A\u0637\u0628\u064A\u0642");
151
- injectString("cs", "Deselect all", "Zru\u0161it v\xFDb\u011Br v\u0161ech");
152
- injectString("da-DK", "Deselect all", "Frav\xE6lg alle");
153
- injectString("de", "Deselect all", "Auswahl f\xFCr alle aufheben");
154
- injectString("en", "Deselect all", "Deselect all");
155
- injectString("es", "Deselect all", "Deseleccionar todo");
156
- injectString("fi-FI", "Deselect all", "Poista kaikki valinnat");
157
- injectString("fr", "Deselect all", "D\xE9s\xE9lectionner tout");
158
- injectString("fr-FR", "Deselect all", "D\xE9s\xE9lectionner tout");
159
- injectString("hu-HU", "Deselect all", "Ne v\xE1lassz ki semmit.");
160
- injectString("id", "Deselect all", "Batalkan pilih semua");
161
- injectString("it", "Deselect all", "Deselezionare tutto");
162
- injectString("ja", "Deselect all", "\u3059\u3079\u3066\u3092\u9078\u629E\u89E3\u9664");
163
- injectString("ko-KR", "Deselect all", "\uBAA8\uB450 \uC120\uD0DD \uCDE8\uC18C");
164
- injectString("ms", "Deselect all", "Nyahpilih semua");
165
- injectString("nb-NO", "Deselect all", "Fjern alle valg");
166
- injectString("nl", "Deselect all", "Alles deselecteren");
167
- injectString("pl", "Deselect all", "Usu\u0144 wyb\xF3r wszystkich");
168
- injectString("pt-BR", "Deselect all", "Desmarcar tudo");
169
- injectString("pt-PT", "Deselect all", "Desmarcar tudo");
170
- injectString("sk-SK", "Deselect all", "Zru\u0161 v\xFDber v\u0161etk\xFDch.");
171
- injectString("sv", "Deselect all", "Avmarkera alla");
172
- injectString("th", "Deselect all", "\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01\u0E01\u0E32\u0E23\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14");
173
- injectString("tr", "Deselect all", "T\xFCm\xFCn\xFCn se\xE7imini iptal et");
174
- injectString("zh-Hans", "Deselect all", "\u53D6\u6D88\u5168\u9009");
175
- injectString("zh-TW", "Deselect all", "\u53D6\u6D88\u5168\u9078");
176
- injectString("ro-RO", "Deselect all", "Deselecta\u021Bi tot");
177
- injectString("ar-SA", "Deselect all", "\u0625\u0644\u063A\u0627\u0621 \u062A\u062D\u062F\u064A\u062F \u0627\u0644\u0643\u0644");
178
151
  injectString("cs", "Select all", "Vybrat v\u0161e");
179
152
  injectString("da-DK", "Select all", "V\xE6lg alle");
180
153
  injectString("de", "Select all", "Alle ausw\xE4hlen");
@@ -319,7 +292,8 @@ export const DropdownList = ({
319
292
  onSelect,
320
293
  onSingleSelect,
321
294
  listData,
322
- isAllSelected,
295
+ isSelectAllActive,
296
+ shouldBlockItems,
323
297
  backButtonName,
324
298
  width,
325
299
  minWidth,
@@ -348,7 +322,7 @@ export const DropdownList = ({
348
322
  const internalListId = useId();
349
323
  const selectListId = listId || internalListId;
350
324
  const handleSelectAllClick = () => {
351
- onSelectAllClick(isAllSelected);
325
+ onSelectAllClick(isSelectAllActive === true);
352
326
  };
353
327
  const handleBackButtonKeyDown = useCallback(event => {
354
328
  if (event.key === "ArrowLeft") {
@@ -376,13 +350,14 @@ export const DropdownList = ({
376
350
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
377
351
  forceSelection ? onSingleSelect(false, newActiveEl || activeValue) : onSingleSelect(false, newActiveEl);
378
352
  }, [activeValue, forceSelection, onSingleSelect]);
379
- const selectButtonLabel = isAllSelected ? translate("Deselect all") : translate("Select all");
380
- const getActionButton = (label, title, icon, isDisabled, clickHandler, size, onKeyDown) => _jsx("button", {
353
+ const selectButtonLabel = translate("Select all");
354
+ const getActionButton = (label, title, icon, isDisabled, clickHandler, size, onKeyDown, isSelected) => _jsx("button", {
381
355
  type: "button",
382
356
  disabled: isDisabled,
383
357
  onClick: clickHandler,
384
358
  onKeyDown: onKeyDown,
385
- className: "zen-dropdown-list__item zen-dropdown-list__item--interactive zen-dropdown-list__action-button zen-dropdown-list__action-button-back",
359
+ "aria-pressed": isSelected,
360
+ className: classNames(["zen-dropdown-list__item zen-dropdown-list__item--interactive zen-dropdown-list__action-button zen-dropdown-list__action-button-back", isSelected ? "zen-dropdown-list__action-button--selected" : ""]),
386
361
  title: title,
387
362
  children: _jsxs(_Fragment, {
388
363
  children: [React.createElement(icon, {
@@ -418,11 +393,15 @@ export const DropdownList = ({
418
393
  });
419
394
  return values;
420
395
  };
396
+ const multiselectOptions = shouldBlockItems ? listData.map(item => Object.assign(Object.assign({}, item), {
397
+ blocked: true,
398
+ checked: false
399
+ })) : listData;
421
400
  return _jsx("div", {
422
401
  className: "zen-dropdown-list__elements",
423
402
  ref: listElementRef,
424
403
  children: isMultiselect ? _jsx(CheckboxListWithAction, {
425
- options: listData,
404
+ options: multiselectOptions,
426
405
  label: "",
427
406
  onChange: handleChange,
428
407
  onClick: handleClick
@@ -438,7 +417,7 @@ export const DropdownList = ({
438
417
  value: createValue(listData, activeValue)
439
418
  })
440
419
  });
441
- }, [listElementRef, isMultiselect, listData, handleChange, handleClick, handleSingleChange, translate, selectListId, forceSelection, activeValue]);
420
+ }, [listElementRef, isMultiselect, shouldBlockItems, listData, handleChange, handleClick, handleSingleChange, translate, selectListId, forceSelection, activeValue]);
442
421
  return _jsxs("div", Object.assign({
443
422
  className: classNames(["zen-dropdown-list", driveComponentClass || ""])
444
423
  }, styleWidth, {
@@ -456,7 +435,7 @@ export const DropdownList = ({
456
435
  }) : null, backButtonName ? _jsx("div", {
457
436
  className: "zen-dropdown-list__item-wrapper",
458
437
  children: getActionButton(backButtonName, translate("Back"), IconBackArrow, false, onBackButtonClick, "large", handleBackButtonKeyDown)
459
- }) : null, hasSelectAllButton ? getActionButton(selectButtonLabel, selectButtonLabel, IconCheckRadio, !!isSelectAllButtonDisable, handleSelectAllClick, isDrive ? "huger" : "huge") : null, listDataComponent, isWithFooter ? _jsxs("div", {
438
+ }) : null, hasSelectAllButton ? getActionButton(selectButtonLabel, selectButtonLabel, IconCheckRadio, !!isSelectAllButtonDisable, handleSelectAllClick, isDrive ? "huger" : "huge", undefined, isSelectAllActive) : null, listDataComponent, isWithFooter ? _jsxs("div", {
460
439
  className: "zen-dropdown-list__footer",
461
440
  children: [_jsx(Button, {
462
441
  onClick: isMultiselect ? onClearClick : handleClearClick,
@@ -484,4 +463,4 @@ export const DropdownList = ({
484
463
  }) : null]
485
464
  }));
486
465
  };
487
- export const TRANSLATIONS = ["Select all", "Deselect all", "Clear", "Back", "No data"];
466
+ export const TRANSLATIONS = ["Select all", "Clear", "Back", "No data"];
@@ -8,7 +8,7 @@ import { getInitialState, stateReducer, ROOT_GROUP_ID } from "./stateReducer/sta
8
8
  import { StateActionType } from "./stateReducer/stateActionType";
9
9
  import { FOCUSABLE_SELECTOR } from "../utils/focusableSelector";
10
10
  import { useEscape } from "../commonHelpers/hooks/useEscape";
11
- import { checkIsDataProblem, compareObjectsArrays, compareStringsArrays, createListDataOptions, getDataForChange, getListDataWithDisabled, getSelectedCount, getStringFromAllSelected, getStringFromSelected, isAllChildrenSelected, isAllItemsHasOneParent, isEveryItemSelected, prepareSelectedIdsToItems, sortDropdownItemArray } from "./dropdownHelper";
11
+ import { checkIsDataProblem, compareObjectsArrays, compareStringsArrays, createListDataOptions, getListDataWithDisabled, getSelectedCount, getStringFromAllSelected, getStringFromSelected, isAllChildrenSelected, isAllItemsHasOneParent, isEveryItemSelected, prepareSelectedIdsToItems, sortDropdownItemArray } from "./dropdownHelper";
12
12
  import { DropdownTrigger } from "./dropdownTrigger";
13
13
  import { isFocusable } from "../dialog/dialogHelpers";
14
14
  import { useLanguage } from "../utils/localization/useLanguage";
@@ -391,23 +391,6 @@ export const DropdownRaw = props => {
391
391
  payload: state.currentId || state.rootId
392
392
  });
393
393
  }, [isFullSelectionMode, state.currentId, state.rootId]);
394
- const handleSelectAllInSearch = useCallback(isAllSelect => {
395
- if (isFullSelectionMode && state.isAllSelected) {
396
- dispatchState({
397
- type: StateActionType.DeselectItemsFromAllSelected,
398
- payload: undefined
399
- });
400
- return;
401
- }
402
- const dataForChange = getDataForChange(getListDataWithDisabled(state.listData, state.isNestedList), state.selectedIds, isAllSelect);
403
- dispatchState({
404
- type: StateActionType.ChangeBulkSelection,
405
- payload: {
406
- itemsIds: dataForChange,
407
- value: !isAllSelect
408
- }
409
- });
410
- }, [isFullSelectionMode, state.isAllSelected, state.listData, state.isNestedList, state.selectedIds]);
411
394
  const handleClearClick = useCallback(() => {
412
395
  var _a, _b;
413
396
  dispatchState({
@@ -854,13 +837,14 @@ export const DropdownRaw = props => {
854
837
  });
855
838
  }
856
839
  if (state.showList) {
857
- const isSearchMode = state.inputValue && !state.currentId;
840
+ const isSearchMode = Boolean(state.inputValue) && !state.currentId;
858
841
  const currentListData = createListDataOptions(state, translate, isSearchMode ? sortDropdownItemArray(state.listData, sortFn).slice(0, listLimit).filter(el => el.id !== state.rootId) :
859
842
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
860
843
  sortDropdownItemArray(((_b = state.groupsMap[state.currentId || state.rootId]) === null || _b === void 0 ? void 0 : _b.children) || [], sortFn).slice(0, listLimit) || [], multiselect, currentAllSelected);
844
+ const selectAllActiveForCurrentLevel = state.selectAllActiveForId === (state.currentId || state.rootId);
861
845
  return _jsx(DropdownList, {
862
846
  onBackButtonClick: handleBackButtonClick,
863
- onSelectAllClick: isSearchMode ? handleSelectAllInSearch : handleSelectAllClick,
847
+ onSelectAllClick: handleSelectAllClick,
864
848
  onClearClick: handleClearClick,
865
849
  onCancelClick: handleCancelClick,
866
850
  onApplyClick: handleApplyClick,
@@ -871,15 +855,17 @@ export const DropdownRaw = props => {
871
855
  backButtonName: state.currentId && state.groupsMap[state.currentId] ? getGroupDescription(state.groupsMap[state.currentId], translate) : undefined,
872
856
  filterName: isMobile ? undefined : filterName,
873
857
  isAllSelected: currentAllSelected ? currentAllSelected : isSearchMode ? isEveryItemSelected(getListDataWithDisabled(state.listData, state.isNestedList), state.selectedIds) : currentAllSelected === undefined ? isAllChildrenSelected(state, state.currentId || state.rootId) : false,
858
+ isSelectAllActive: isFullSelectionMode ? currentAllSelected : selectAllActiveForCurrentLevel,
859
+ shouldBlockItems: !state.inputValue && !isFullSelectionMode && selectAllActiveForCurrentLevel,
874
860
  isMultiselect: multiselect,
875
861
  forceSelection: forceSelection,
876
862
  listData: currentListData,
877
863
  width: width || currentWidth === 180 ? undefined : currentWidth,
878
864
  minWidth: currentWidth,
879
- hasSelectAllButton: selectAllButton && multiselect,
865
+ hasSelectAllButton: selectAllButton && multiselect && !state.inputValue,
880
866
  hasApplyButton: hasApplyButton,
881
867
  isApplyDisabled: memoizedIsApplyButtonDisabled,
882
- isSelectAllButtonDisable: currentListData.length === 0 || isSearchMode !== "" && state.isNestedList && isAllItemsHasOneParent(state.listData.filter(el => el.id !== state.rootId), (((_c = state.groupsMap[state.rootId]) === null || _c === void 0 ? void 0 : _c.children) || []).map(el => el.id)),
868
+ isSelectAllButtonDisable: currentListData.length === 0 || isSearchMode && state.isNestedList && isAllItemsHasOneParent(state.listData.filter(el => el.id !== state.rootId), (((_c = state.groupsMap[state.rootId]) === null || _c === void 0 ? void 0 : _c.children) || []).map(el => el.id)),
883
869
  isClearButtonDisabled: memoizedIsClearButtonDisabled,
884
870
  isWithFooter: memoizedWithFooter && !isMobile,
885
871
  isMobile: isMobile,
@@ -891,7 +877,7 @@ export const DropdownRaw = props => {
891
877
  });
892
878
  }
893
879
  return null;
894
- }, [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]);
880
+ }, [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, handleSelectAllClick, handleSelect, handleChangeCurrentId, handleSingleSelection, isMobile, filterName, forceSelection, width, selectAllButton, memoizedIsApplyButtonDisabled, memoizedIsClearButtonDisabled, isCheckboxMode, handleCheckboxChange, checkboxLabel, selectListId, isFullSelectionMode]);
895
881
  const currentStringFromSelected = isFullSelectionMode && hasApplyButton && state.globalIsAllSelected || isFullSelectionMode && !hasApplyButton && state.isAllSelected ? getStringFromAllSelected(state.groupsMap, translate, state.rootId) : getStringFromSelected(hasApplyButton ? state.globalSelectedIds : state.selectedIds, state.groupsMapSelected, translate, state.rootId);
896
882
  const memoizedCurrentSelection = useMemo(() => showSelection && !state.inputValue ? currentStringFromSelected : "", [showSelection, state.inputValue, currentStringFromSelected]);
897
883
  const parentTriggerWidth = ((_b = comboboxRef.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect().width) || 420;
@@ -988,4 +974,4 @@ export const DropdownRaw = props => {
988
974
  });
989
975
  };
990
976
  DropdownRaw.displayName = "DropdownRaw";
991
- export const TRANSLATIONS = ["Filter by group", "Open filter", "Clear search", "Select all", "Deselect all", "Clear", "Back", "No data"];
977
+ export const TRANSLATIONS = ["Filter by group", "Open filter", "Clear search", "Select all", "Clear", "Back", "No data"];
@@ -25,6 +25,7 @@ export interface IDropdownState {
25
25
  listLimit: number;
26
26
  resultsExceedListLimit?: boolean;
27
27
  isAllSelected?: boolean;
28
+ selectAllActiveForId?: string;
28
29
  globalIsAllSelected?: boolean;
29
30
  defaultValueIsAllSelected?: boolean;
30
31
  isChecked?: boolean;
@@ -1,5 +1,5 @@
1
1
  import { StateActionType } from "./stateActionType";
2
- import { getChildList, updateAllSelectedStateValueBasedOnTotalSelected, getRootId } from "./stateReducerHelper";
2
+ import { getChildList, getRootId, computeIsAllSelected } from "./stateReducerHelper";
3
3
  import { createGroupsMap } from "../../groupsFilterRaw/groupsFilterHelper";
4
4
  export const ROOT_GROUP_ID = "zen_dropdown_root_group_id";
5
5
  export const getInitialState = (isFullSelectionMode, comboItems, selection, listLimit, defaultValue, isAllSelected, defaultValueIsAllSelected, isChecked, defaultValueIsChecked, firstParentNodeIsVisible) => {
@@ -73,10 +73,12 @@ export function stateReducer(state, action) {
73
73
  }
74
74
  const isCurrentListNested = Object.keys(updatedGroupsMap).length > 0 &&
75
75
  (updatedGroupsMap[ROOT_GROUP_ID].children || []).some(el => el.children && el.children.length);
76
- state.groupsMap = updatedGroupsMap;
77
- const additionalStateUpdates = updateAllSelectedStateValueBasedOnTotalSelected(state, state.selectedIds.length - newNamelessIds.size);
76
+ const groupsMapLength = Object.keys(updatedGroupsMap).length - 1;
77
+ const newResultsExceedListLimit = groupsMapLength >= state.listLimit;
78
+ const selectedInNewMap = state.selectedIds.filter(id => id in updatedGroupsMap).length;
79
+ const newIsAllSelected = computeIsAllSelected(state.isAllSelected, state.isFullSelectionMode, newResultsExceedListLimit, groupsMapLength, selectedInNewMap);
78
80
  const rootId = getRootId(updatedGroupsMap, ROOT_GROUP_ID, state.firstParentNodeIsVisible);
79
- return Object.assign(Object.assign(Object.assign({}, state), { rootId: rootId || ROOT_GROUP_ID, namelessIds: newNamelessIds, isNestedList: state.isNestedList ? state.isNestedList : isCurrentListNested, resultsExceedListLimit: Object.keys(updatedGroupsMap).length - 1 >= state.listLimit }), additionalStateUpdates);
81
+ return Object.assign(Object.assign({}, state), { groupsMap: updatedGroupsMap, rootId: rootId || ROOT_GROUP_ID, namelessIds: newNamelessIds, isNestedList: state.isNestedList ? state.isNestedList : isCurrentListNested, resultsExceedListLimit: newResultsExceedListLimit, isAllSelected: newIsAllSelected });
80
82
  }
81
83
  case StateActionType.SetListData: {
82
84
  state.selectedIds.forEach(id => {
@@ -101,9 +103,9 @@ export function stateReducer(state, action) {
101
103
  case StateActionType.SetIsOpenCombo:
102
104
  return Object.assign(Object.assign({}, state), { isOpenCombo: payload });
103
105
  case StateActionType.ResetSelection:
104
- return Object.assign(Object.assign({}, state), { selectedIds: [...state.defaultValue], isAllSelected: state.defaultValueIsAllSelected, isChecked: typeof state.isChecked === "boolean" ? state.defaultValueIsChecked || false : undefined });
106
+ return Object.assign(Object.assign({}, state), { selectedIds: [...state.defaultValue], isAllSelected: state.defaultValueIsAllSelected, isChecked: typeof state.isChecked === "boolean" ? state.defaultValueIsChecked || false : undefined, selectAllActiveForId: undefined });
105
107
  case StateActionType.ResetStateToGlobal:
106
- return Object.assign(Object.assign({}, state), { selectedIds: [...state.globalSelectedIds], isAllSelected: state.globalIsAllSelected, isChecked: state.globalIsChecked });
108
+ return Object.assign(Object.assign({}, state), { selectedIds: [...state.globalSelectedIds], isAllSelected: state.globalIsAllSelected, isChecked: state.globalIsChecked, selectAllActiveForId: undefined });
107
109
  case StateActionType.NothingToShow:
108
110
  return Object.assign(Object.assign({}, state), { showWaiting: false, showEmptyList: false, showList: false });
109
111
  case StateActionType.Show:
@@ -219,8 +221,7 @@ export function stateReducer(state, action) {
219
221
  state.groupsMapSelected.set(id, Object.assign(Object.assign({ id }, (item.name ? { name: item.name } : {})), (item.color ? { color: item.color } : {})));
220
222
  }
221
223
  });
222
- const additionalStateUpdates = updateAllSelectedStateValueBasedOnTotalSelected(state, currentSelectedIds.size);
223
- return Object.assign(Object.assign(Object.assign({}, state), { selectedIds: Array.from(currentSelectedIds) }), additionalStateUpdates);
224
+ return Object.assign(Object.assign({}, state), { selectedIds: Array.from(currentSelectedIds), selectAllActiveForId: undefined, isAllSelected: state.isAllSelected });
224
225
  }
225
226
  case StateActionType.ChangeBulkSelection: {
226
227
  const { itemsIds, value } = payload;
@@ -253,8 +254,7 @@ export function stateReducer(state, action) {
253
254
  state.groupsMapSelected.set(id, Object.assign(Object.assign({ id }, (item.name ? { name: item.name } : {})), (item.color ? { color: item.color } : {})));
254
255
  }
255
256
  });
256
- const additionalStateUpdates = updateAllSelectedStateValueBasedOnTotalSelected(state, currentSelectedIds.size);
257
- return Object.assign(Object.assign(Object.assign({}, state), { selectedIds: Array.from(currentSelectedIds) }), additionalStateUpdates);
257
+ return Object.assign(Object.assign({}, state), { selectedIds: Array.from(currentSelectedIds), selectAllActiveForId: undefined });
258
258
  }
259
259
  case StateActionType.SelectAllChildren: {
260
260
  const currentEl = state.groupsMap[payload];
@@ -291,7 +291,7 @@ export function stateReducer(state, action) {
291
291
  state.groupsMapSelected.set(id, Object.assign(Object.assign({ id }, (item.name ? { name: item.name } : {})), (item.color ? { color: item.color } : {})));
292
292
  }
293
293
  });
294
- return Object.assign(Object.assign({}, state), { selectedIds: Array.from(newSelected) });
294
+ return Object.assign(Object.assign({}, state), { selectedIds: Array.from(newSelected), selectAllActiveForId: payload });
295
295
  }
296
296
  case StateActionType.DeselectItemsFromAllSelected: {
297
297
  const currentEl = state.groupsMap[state.rootId];
@@ -315,7 +315,7 @@ export function stateReducer(state, action) {
315
315
  state.groupsMapSelected.set(id, Object.assign(Object.assign({ id }, (item.name ? { name: item.name } : {})), (item.color ? { color: item.color } : {})));
316
316
  }
317
317
  });
318
- return Object.assign(Object.assign({}, state), { selectedIds: Array.from(newSelected), isAllSelected: state.isFullSelectionMode ? false : undefined });
318
+ return Object.assign(Object.assign({}, state), { selectedIds: Array.from(newSelected), isAllSelected: state.isFullSelectionMode ? false : undefined, selectAllActiveForId: undefined });
319
319
  }
320
320
  case StateActionType.ToggleValueForAllSelected: {
321
321
  const currentEl = state.groupsMap[state.rootId];
@@ -334,8 +334,7 @@ export function stateReducer(state, action) {
334
334
  }
335
335
  });
336
336
  const updatedIsAllSelectedValue = state.isFullSelectionMode ? !state.isAllSelected : undefined;
337
- const additionalStateUpdates = updateAllSelectedStateValueBasedOnTotalSelected(state, newSelected.size);
338
- return Object.assign(Object.assign(Object.assign({}, state), { selectedIds: state.isAllSelected ? Array.from(newSelected) : [], isAllSelected: updatedIsAllSelectedValue }), additionalStateUpdates);
337
+ return Object.assign(Object.assign({}, state), { selectedIds: state.isAllSelected ? Array.from(newSelected) : [], isAllSelected: updatedIsAllSelectedValue });
339
338
  }
340
339
  case StateActionType.DeselectAllChildren: {
341
340
  const childrenForDeselect = [];
@@ -347,7 +346,7 @@ export function stateReducer(state, action) {
347
346
  });
348
347
  const newSelected = new Set(state.selectedIds);
349
348
  childrenForDeselect.forEach(childId => newSelected.delete(childId));
350
- return Object.assign(Object.assign({}, state), { selectedIds: Array.from(newSelected) });
349
+ return Object.assign(Object.assign({}, state), { selectedIds: Array.from(newSelected), selectAllActiveForId: undefined });
351
350
  }
352
351
  case StateActionType.SetFirstParentNodeIsVisible: {
353
352
  if (state.firstParentNodeIsVisible === payload) {
@@ -1,6 +1,5 @@
1
- import { IDropdownState } from "./stateReducer";
2
1
  import { IDropdownRawItem } from "../types";
3
2
  import { IGroupTree, ITypedHash } from "../../groupsFilterRaw/groupsFilterInterfaces";
4
3
  export declare function getChildList(childArr: IDropdownRawItem[] | undefined): IDropdownRawItem[];
5
- export declare const updateAllSelectedStateValueBasedOnTotalSelected: (state: IDropdownState, totalSelected: number) => Partial<Pick<IDropdownState, "isAllSelected">>;
4
+ export declare const computeIsAllSelected: (currentIsAllSelected: boolean | undefined, isFullSelectionMode: boolean, resultsExceedListLimit: boolean | undefined, groupsMapLength: number, selectedCount: number) => boolean | undefined;
6
5
  export declare const getRootId: (groupsMap: ITypedHash<IGroupTree>, rootIdKey: string, firstParentNodeIsVisible?: boolean) => string | undefined;
@@ -13,16 +13,9 @@ export function getChildList(childArr) {
13
13
  });
14
14
  return list;
15
15
  }
16
- export const updateAllSelectedStateValueBasedOnTotalSelected = (state, totalSelected) => {
17
- const additionalStateUpdates = {};
18
- const groupsMapLength = Object.keys(state.groupsMap).length - 1;
19
- if (!state.resultsExceedListLimit && !state.isAllSelected && state.isFullSelectionMode && groupsMapLength > 0) {
20
- if (totalSelected >= groupsMapLength) {
21
- additionalStateUpdates.isAllSelected = true;
22
- }
23
- }
24
- return additionalStateUpdates;
25
- };
16
+ export const computeIsAllSelected = (currentIsAllSelected, isFullSelectionMode, resultsExceedListLimit, groupsMapLength, selectedCount) => !resultsExceedListLimit && currentIsAllSelected === false && isFullSelectionMode && groupsMapLength > 0 && selectedCount >= groupsMapLength
17
+ ? true
18
+ : currentIsAllSelected;
26
19
  export const getRootId = (groupsMap, rootIdKey, firstParentNodeIsVisible) => {
27
20
  var _a;
28
21
  if (Object.keys(groupsMap).length === 0) {
@@ -3,6 +3,14 @@ import "./headerTitle.less";
3
3
  import { IZenComponentProps } from "../commonHelpers/zenComponent";
4
4
  import { IBetaPillActions } from "../betaPill/betaPill";
5
5
  export declare const HeaderTitleDisplayName = "PageHeader";
6
+ /**
7
+ * @internal - temporary escape hatch
8
+ * @deprecated DO NOT USE in external consumers
9
+ */
10
+ export interface IHeaderTitleInternal {
11
+ betaPillName?: string;
12
+ betaPillDescription?: string;
13
+ }
6
14
  export interface IHeaderTitle extends IZenComponentProps {
7
15
  id?: string;
8
16
  pageName: string;
@@ -18,7 +26,7 @@ export interface IHeaderTitle extends IZenComponentProps {
18
26
  betaOptionAction?: IBetaPillActions;
19
27
  }
20
28
  export declare const HeaderTitle: {
21
- ({ id, children, className, pageName, subline, isBeta, isMobile: isMobileProp, allowBookmarkWithBack, feedBackAction, betaOptionAction }: IHeaderTitle): import("react/jsx-runtime").JSX.Element;
29
+ (props: IHeaderTitle): import("react/jsx-runtime").JSX.Element;
22
30
  displayName: string;
23
31
  };
24
32
  export declare const TRANSLATIONS: string[];
@@ -7,7 +7,8 @@ import { useDriveClassName } from "../utils/theme/useDriveClassName";
7
7
  import { HeaderBack } from "../header/headerBack";
8
8
  import { Bookmark } from "../bookmark/bookmark";
9
9
  export const HeaderTitleDisplayName = "PageHeader";
10
- export const HeaderTitle = ({ id, children, className, pageName, subline, isBeta, isMobile: isMobileProp, allowBookmarkWithBack, feedBackAction, betaOptionAction }) => {
10
+ export const HeaderTitle = (props) => {
11
+ const { id, children, className, pageName, subline, isBeta, isMobile: isMobileProp, allowBookmarkWithBack, feedBackAction, betaOptionAction, betaPillName, betaPillDescription } = props;
11
12
  const isMobile = useMobile();
12
13
  const driveMainLineClassName = useDriveClassName("zen-page-header__main-line");
13
14
  const drivePageNameClassName = useDriveClassName("zen-page-header__page-name");
@@ -30,7 +31,7 @@ export const HeaderTitle = ({ id, children, className, pageName, subline, isBeta
30
31
  });
31
32
  return [b, b.length && !allowBookmarkWithBack ? o.filter(el => el.type !== Bookmark) : o];
32
33
  }, [children, allowBookmarkWithBack]);
33
- return (_jsxs("header", { id: id, className: clsNames, children: [_jsxs("div", { className: classNames(["zen-page-header__main-line", driveMainLineClassName || ""]), children: [back.length ? back : null, pageName ? _jsx("h1", { className: classNames(["zen-page-header__page-name", drivePageNameClassName || ""]), children: pageName }) : null, isBeta ? _jsx(BetaPill, { feedbackAction: feedBackAction, betaOptionAction: betaOptionAction, className: "zen-page-header__beta" }) : null, other.length ? other : null] }), subline || ""] }));
34
+ return (_jsxs("header", { id: id, className: clsNames, children: [_jsxs("div", { className: classNames(["zen-page-header__main-line", driveMainLineClassName || ""]), children: [back.length ? back : null, pageName ? _jsx("h1", { className: classNames(["zen-page-header__page-name", drivePageNameClassName || ""]), children: pageName }) : null, isBeta ? (_jsx(BetaPill, Object.assign({ feedbackAction: feedBackAction, betaOptionAction: betaOptionAction, className: "zen-page-header__beta" }, { name: betaPillName, description: betaPillDescription }))) : null, other.length ? other : null] }), subline || ""] }));
34
35
  };
35
36
  HeaderTitle.displayName = HeaderTitleDisplayName;
36
37
  export const TRANSLATIONS = [...BetaPillTranslations];
package/esm/index.d.ts CHANGED
@@ -20,7 +20,7 @@ export { type ICardButton, CardButton } from "./card/components/cardButton/cardB
20
20
  export { type ICardToggle, CardToggle } from "./card/components/cardToggle/cardToggle";
21
21
  export { type IContent, Content } from "./card/components/content";
22
22
  export { type TCardStatus, Status } from "./card/components/status";
23
- export { Title } from "./card/components/title";
23
+ export { type THeadingTag, Title } from "./card/components/title";
24
24
  export { TitleLink } from "./card/components/titleLink";
25
25
  export { getDefaultFullWidthValue } from "./card/helpers/getDefaultFullWidthValue";
26
26
  export { getIconFromStatus } from "./card/helpers/getIconFromStatus";
@@ -774,6 +774,8 @@ export { HeaderButtonsProvider } from "./utils/headerButtons/headerButtonsProvid
774
774
  export { getNewFocusableItem, getFirstFocusableItem } from "./utils/keyboardHelpers";
775
775
  export { LanguageProvider } from "./utils/localization/languageProvider";
776
776
  export { dictionaries, injectString } from "./utils/localization/translationsDictionary";
777
+ export { directionContext } from "./utils/localization/directionContext";
778
+ export type { TTextDirection } from "./utils/localization/getTextDirection";
777
779
  export { useDirection } from "./utils/localization/useDirection";
778
780
  export { useLanguage } from "./utils/localization/useLanguage";
779
781
  export { ThemeDark } from "./utils/theme/themeDark";
package/esm/index.js CHANGED
@@ -758,6 +758,7 @@ export { HeaderButtonsProvider } from "./utils/headerButtons/headerButtonsProvid
758
758
  export { getNewFocusableItem, getFirstFocusableItem } from "./utils/keyboardHelpers";
759
759
  export { LanguageProvider } from "./utils/localization/languageProvider";
760
760
  export { dictionaries, injectString } from "./utils/localization/translationsDictionary";
761
+ export { directionContext } from "./utils/localization/directionContext";
761
762
  export { useDirection } from "./utils/localization/useDirection";
762
763
  export { useLanguage } from "./utils/localization/useLanguage";
763
764
  export { ThemeDark } from "./utils/theme/themeDark";
@@ -17,6 +17,7 @@ export interface IControlledMenu extends IZenComponentProps {
17
17
  ariaLabel?: string;
18
18
  ariaLabelledby?: string;
19
19
  listClassName?: string;
20
+ closeOnScroll?: boolean;
20
21
  }
21
22
  type TControlledMenu = FC<IControlledMenu> & {
22
23
  Item: FC<IMenuControlledItem>;
@@ -20,7 +20,7 @@ import { generateId } from "../commonHelpers/generateId";
20
20
  import { PathProvider } from "./contexts/pathProvider";
21
21
  import { isSeparator, MenuSeparator } from "./components/menuSeparator";
22
22
  import { FOCUSABLE_SELECTOR } from "../utils/focusableSelector";
23
- export const ControlledMenu = ({ children, isOpen, setIsOpen, triggerRef, ariaLabel, ariaLabelledby, id, title, className = "", listClassName = "", paddingX = 0, paddingY = 0, alignment }) => {
23
+ export const ControlledMenu = ({ children, isOpen, setIsOpen, triggerRef, ariaLabel, ariaLabelledby, id, title, className = "", listClassName = "", paddingX = 0, paddingY = 0, alignment, closeOnScroll = true }) => {
24
24
  const [deviceType, setDeviceType] = useState(DeviceType.Desktop);
25
25
  const isMobile = deviceType === DeviceType.Mobile;
26
26
  const memoizedOnChange = useCallback(setIsOpen, [setIsOpen]);
@@ -215,7 +215,7 @@ export const ControlledMenu = ({ children, isOpen, setIsOpen, triggerRef, ariaLa
215
215
  if (isMobile) {
216
216
  return (_jsx(_Fragment, { children: _jsx(PathProvider, { path: path, onOpenBranch: onOpenBranch, closeBranch: closeBranch, navigatedViaKeyboardRef: navigatedViaKeyboardRef, keyboardActiveRef: keyboardActiveRef, children: _jsxs(MobileSheet, { label: title, isOpen: isOpen, triggerRef: triggerRef, onHidePanel: hideMenu, onCloseClick: hideMenu, children: [_jsx(MobileSheet.Title, { children: title }), _jsx(MobileSheet.Content, { children: renderMenuList() })] }) }) }));
217
217
  }
218
- return (_jsx(_Fragment, { children: _jsx(PathProvider, { path: path, onOpenBranch: onOpenBranch, closeBranch: closeBranch, navigatedViaKeyboardRef: navigatedViaKeyboardRef, keyboardActiveRef: keyboardActiveRef, children: _jsx(ControlledPopup, { id: id, useTrapFocusWithTrigger: "on", className: classNames(["zen-controlled-menu", className]), onOpenChange: memoizedOnChange, isOpen: isOpen, triggerRef: triggerRef, paddingX: paddingX, paddingY: paddingY, alignment: alignment, ariaLabelledby: ariaLabelledby, ariaLabel: ariaLabel || title, recalculateOnScroll: true,
218
+ return (_jsx(_Fragment, { children: _jsx(PathProvider, { path: path, onOpenBranch: onOpenBranch, closeBranch: closeBranch, navigatedViaKeyboardRef: navigatedViaKeyboardRef, keyboardActiveRef: keyboardActiveRef, children: _jsx(ControlledPopup, { id: id, useTrapFocusWithTrigger: "on", className: classNames(["zen-controlled-menu", className]), onOpenChange: memoizedOnChange, isOpen: isOpen, triggerRef: triggerRef, paddingX: paddingX, paddingY: paddingY, alignment: alignment, ariaLabelledby: ariaLabelledby, ariaLabel: ariaLabel || title, closeOnScroll: closeOnScroll,
219
219
  // focusOnOpen is false - ControlledMenu handles focus based on input method
220
220
  // (keyboard vs mouse) in its own useEffect
221
221
  focusOnOpen: false, children: renderMenuList() }) }) }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geotab/zenith",
3
- "version": "3.10.0-beta.0",
3
+ "version": "3.10.0-beta.2",
4
4
  "description": "Zenith components library on React",
5
5
  "main": "dist/index.js",
6
6
  "types": "esm/index.d.ts",