@geotab/zenith 3.6.3-beta.0 → 3.7.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 (75) hide show
  1. package/README.md +15 -1
  2. package/dist/absolute/absolute.d.ts +3 -1
  3. package/dist/absolute/absolute.js +4 -4
  4. package/dist/controlledPopup/controlledPopup.d.ts +3 -1
  5. package/dist/controlledPopup/controlledPopup.js +2 -2
  6. package/dist/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +8 -2
  7. package/dist/groupsFilterRaw/groupsFilterRaw.js +43 -9
  8. package/dist/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
  9. package/dist/groupsFilterRaw/groupsFilterTrigger.js +9 -2
  10. package/dist/index.css +208 -18
  11. package/dist/index.d.ts +1 -1
  12. package/dist/list/hooks/useDragAndDrop.d.ts +3 -1
  13. package/dist/list/hooks/useDragAndDrop.js +11 -4
  14. package/dist/menu/components/menuItem.js +12 -2
  15. package/dist/menu/contexts/pathContext.d.ts +3 -1
  16. package/dist/menu/contexts/pathProvider.d.ts +1 -1
  17. package/dist/menu/contexts/pathProvider.js +1 -1
  18. package/dist/menu/controlledMenu.js +97 -29
  19. package/dist/nav/nav.d.ts +2 -1
  20. package/dist/nav/nav.js +3 -2
  21. package/dist/nav/navEditList/navEditList.js +2 -1
  22. package/dist/pillExpandable/pillContent.d.ts +2 -1
  23. package/dist/pillExpandable/pillContent.js +8 -3
  24. package/dist/pillExpandable/pillExpandable.d.ts +27 -4
  25. package/dist/pillExpandable/pillExpandable.js +426 -196
  26. package/dist/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
  27. package/dist/pillExpandable/pillExpandablePopoverContent.js +7 -0
  28. package/dist/pillExpandable/pillExpandableSimple.d.ts +5 -3
  29. package/dist/pillExpandable/pillExpandableSimple.js +12 -5
  30. package/dist/summary/summary.js +29 -1
  31. package/dist/summaryTile/summaryTile.d.ts +2 -1
  32. package/dist/summaryTile/summaryTile.js +175 -65
  33. package/dist/summaryTile/summaryTileTrigger.d.ts +1 -1
  34. package/dist/summaryTile/summaryTileTrigger.js +1 -1
  35. package/dist/toggleButtonRaw/toggleButtonRaw.js +2 -1
  36. package/dist/utils/localization/getSupportedLanguage.d.ts +2 -2
  37. package/dist/utils/localization/getSupportedLanguage.js +28 -8
  38. package/dist/utils/localization/languageContext.d.ts +1 -1
  39. package/esm/absolute/absolute.d.ts +3 -1
  40. package/esm/absolute/absolute.js +4 -4
  41. package/esm/controlledPopup/controlledPopup.d.ts +3 -1
  42. package/esm/controlledPopup/controlledPopup.js +2 -2
  43. package/esm/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +9 -3
  44. package/esm/groupsFilterRaw/groupsFilterRaw.js +43 -9
  45. package/esm/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
  46. package/esm/groupsFilterRaw/groupsFilterTrigger.js +9 -2
  47. package/esm/index.d.ts +1 -1
  48. package/esm/list/hooks/useDragAndDrop.d.ts +3 -1
  49. package/esm/list/hooks/useDragAndDrop.js +11 -4
  50. package/esm/menu/components/menuItem.js +12 -2
  51. package/esm/menu/contexts/pathContext.d.ts +3 -1
  52. package/esm/menu/contexts/pathProvider.d.ts +1 -1
  53. package/esm/menu/contexts/pathProvider.js +1 -1
  54. package/esm/menu/controlledMenu.js +98 -30
  55. package/esm/nav/nav.d.ts +2 -1
  56. package/esm/nav/nav.js +3 -2
  57. package/esm/nav/navEditList/navEditList.js +2 -1
  58. package/esm/pillExpandable/pillContent.d.ts +2 -1
  59. package/esm/pillExpandable/pillContent.js +8 -3
  60. package/esm/pillExpandable/pillExpandable.d.ts +27 -4
  61. package/esm/pillExpandable/pillExpandable.js +427 -197
  62. package/esm/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
  63. package/esm/pillExpandable/pillExpandablePopoverContent.js +3 -0
  64. package/esm/pillExpandable/pillExpandableSimple.d.ts +5 -3
  65. package/esm/pillExpandable/pillExpandableSimple.js +12 -5
  66. package/esm/summary/summary.js +29 -1
  67. package/esm/summaryTile/summaryTile.d.ts +2 -1
  68. package/esm/summaryTile/summaryTile.js +140 -43
  69. package/esm/summaryTile/summaryTileTrigger.d.ts +1 -1
  70. package/esm/summaryTile/summaryTileTrigger.js +1 -1
  71. package/esm/toggleButtonRaw/toggleButtonRaw.js +2 -1
  72. package/esm/utils/localization/getSupportedLanguage.d.ts +2 -2
  73. package/esm/utils/localization/getSupportedLanguage.js +28 -8
  74. package/esm/utils/localization/languageContext.d.ts +1 -1
  75. package/package.json +4 -4
package/README.md CHANGED
@@ -54,7 +54,21 @@ Zenith library provides components defined in Zenith Design System. It includes
54
54
 
55
55
  ## Change log
56
56
 
57
- ### 3.6.2
57
+ ## 3.7.0
58
+
59
+ - Improve `GroupsFilter` keyboard navigation: return focus to currently selected button after back navigation
60
+ - Add loading state to `SummaryTile` component
61
+ - Update `ToggleButton` accessibility role
62
+ - Update React `Nav` component to emit event on Edit mode toggle
63
+ - Improve Storybook documentation for `PillBox`, `FavoriteButton`, and `LineChartMini` components
64
+ - Make `PillExpandable` less restrictive
65
+ - Improve focused state in `Menu`
66
+ - Add `PageHeader` documentation for new `Filters` component
67
+ - Ensure keyboard accessibility for `Tooltip` in `SummaryCard` component
68
+ - Fix drag & drop in the `Nav` component
69
+ - Fix `NavEditSection` component issues
70
+
71
+ ### 3.6.3
58
72
 
59
73
  Patch for the `Nav` component.
60
74
 
@@ -23,5 +23,7 @@ export interface IAbsolute extends IZenComponentProps {
23
23
  alignmentsFn?: IAlignment;
24
24
  recalculateOnScroll?: boolean;
25
25
  recalculateTrigger?: boolean;
26
+ /** Whether to focus the first focusable element when popup opens. Default: true */
27
+ focusOnOpen?: boolean;
26
28
  }
27
- export declare const Absolute: ({ isOpen, id, paddingX, paddingY, className, children, triggerRef, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, stateFullChilds, role, ariaLabel, ariaLabelledby, alignmentsFn, recalculateOnScroll, recalculateTrigger }: IAbsolute) => import("react/jsx-runtime").JSX.Element | "" | null;
29
+ export declare const Absolute: ({ isOpen, id, paddingX, paddingY, className, children, triggerRef, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, stateFullChilds, role, ariaLabel, ariaLabelledby, alignmentsFn, recalculateOnScroll, recalculateTrigger, focusOnOpen }: IAbsolute) => import("react/jsx-runtime").JSX.Element | "" | null;
@@ -19,7 +19,7 @@ const useScroll_1 = require("../commonHelpers/hooks/useScroll");
19
19
  const getScrollableParent_1 = require("../utils/getScrollableParent");
20
20
  const useClientReady_1 = require("../commonHelpers/hooks/useClientReady");
21
21
  const zen_1 = require("../utils/zen");
22
- const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, triggerRef, alignment, inline, onOpenChange, useTrapFocusWithTrigger = "off", shouldHoldScroll, stateFullChilds, role, ariaLabel, ariaLabelledby, alignmentsFn, recalculateOnScroll, recalculateTrigger = true }) => {
22
+ const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, triggerRef, alignment, inline, onOpenChange, useTrapFocusWithTrigger = "off", shouldHoldScroll, stateFullChilds, role, ariaLabel, ariaLabelledby, alignmentsFn, recalculateOnScroll, recalculateTrigger = true, focusOnOpen = true }) => {
23
23
  const popupRef = (0, react_1.useRef)(null);
24
24
  const prevScroll = (0, react_1.useRef)(0);
25
25
  const { dark } = (0, react_1.useContext)(themeContext_1.themeContext);
@@ -38,7 +38,7 @@ const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, trigger
38
38
  const renderPopup = () => {
39
39
  var _a, _b;
40
40
  if (isOpen) {
41
- const result = ((0, jsx_runtime_1.jsx)("div", Object.assign({}, accessibleAttr, { ref: popupRef, id: id, onScroll: shouldHoldScroll ? onScrollHandler : undefined, className: (0, classNames_1.classNames)(["zen-absolute", darkClassName, className || ""]), children: children })));
41
+ const result = ((0, jsx_runtime_1.jsx)("div", Object.assign({}, accessibleAttr, { ref: popupRef, id: id, tabIndex: -1, onScroll: shouldHoldScroll ? onScrollHandler : undefined, className: (0, classNames_1.classNames)(["zen-absolute", darkClassName, className || ""]), children: children })));
42
42
  if (inline) {
43
43
  return result;
44
44
  }
@@ -94,7 +94,7 @@ const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, trigger
94
94
  if (useTrapFocusWithTrigger === "none") {
95
95
  return undefined;
96
96
  }
97
- if (useTrapFocusWithTrigger !== "withTrigger") {
97
+ if (useTrapFocusWithTrigger !== "withTrigger" && focusOnOpen) {
98
98
  if (firstFocusable) {
99
99
  firstFocusable.focus();
100
100
  }
@@ -108,7 +108,7 @@ const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, trigger
108
108
  };
109
109
  }
110
110
  return () => { };
111
- }, [isOpen, onOpenChange, triggerRef, useTrapFocusWithTrigger, stateFullChilds]);
111
+ }, [isOpen, onOpenChange, triggerRef, useTrapFocusWithTrigger, stateFullChilds, focusOnOpen]);
112
112
  (0, react_1.useEffect)(() => {
113
113
  var _a;
114
114
  if (isOpen) {
@@ -27,5 +27,7 @@ export interface IControlledPopup extends IZenComponentProps {
27
27
  ariaLabelledby?: string;
28
28
  recalculateOnScroll?: boolean;
29
29
  preventAttributesAutoSet?: boolean;
30
+ /** Whether to focus the first focusable element when popup opens. Default: true */
31
+ focusOnOpen?: boolean;
30
32
  }
31
- export declare const ControlledPopup: ({ isOpen, id, paddingX, paddingY, triggerRef, className, children, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, ariaLabel, ariaLabelledby, recalculateOnScroll, preventAttributesAutoSet }: IControlledPopup) => import("react/jsx-runtime").JSX.Element;
33
+ export declare const ControlledPopup: ({ isOpen, id, paddingX, paddingY, triggerRef, className, children, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, ariaLabel, ariaLabelledby, recalculateOnScroll, preventAttributesAutoSet, focusOnOpen }: IControlledPopup) => import("react/jsx-runtime").JSX.Element;
@@ -6,7 +6,7 @@ const react_1 = require("react");
6
6
  const absolute_1 = require("../absolute/absolute");
7
7
  const classNames_1 = require("../commonHelpers/classNames/classNames");
8
8
  const useClientReady_1 = require("../commonHelpers/hooks/useClientReady");
9
- const ControlledPopup = ({ isOpen, id, paddingX, paddingY, triggerRef, className, children, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, ariaLabel, ariaLabelledby, recalculateOnScroll, preventAttributesAutoSet }) => {
9
+ const ControlledPopup = ({ isOpen, id, paddingX, paddingY, triggerRef, className, children, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, ariaLabel, ariaLabelledby, recalculateOnScroll, preventAttributesAutoSet, focusOnOpen }) => {
10
10
  const autoId = (0, react_1.useId)();
11
11
  const popupId = id || autoId;
12
12
  const isClientReady = (0, useClientReady_1.useClientReady)();
@@ -24,6 +24,6 @@ const ControlledPopup = ({ isOpen, id, paddingX, paddingY, triggerRef, className
24
24
  triggerRef.current.setAttribute("aria-expanded", isOpen ? "true" : "false");
25
25
  triggerRef.current.setAttribute("aria-controls", popupId);
26
26
  }, [triggerRef, isOpen, popupId, preventAttributesAutoSet, isClientReady]);
27
- return ((0, jsx_runtime_1.jsx)(absolute_1.Absolute, { triggerRef: triggerRef, alignment: alignment, id: popupId, isOpen: isOpen, className: (0, classNames_1.classNames)(["zen-popup", className ? className : ""]), paddingX: paddingX, paddingY: paddingY, inline: inline, onOpenChange: onOpenChange, useTrapFocusWithTrigger: useTrapFocusWithTrigger, shouldHoldScroll: shouldHoldScroll, role: "dialog", ariaLabel: ariaLabel, ariaLabelledby: ariaLabelledby, recalculateOnScroll: recalculateOnScroll, children: children }));
27
+ return ((0, jsx_runtime_1.jsx)(absolute_1.Absolute, { triggerRef: triggerRef, alignment: alignment, id: popupId, isOpen: isOpen, className: (0, classNames_1.classNames)(["zen-popup", className ? className : ""]), paddingX: paddingX, paddingY: paddingY, inline: inline, onOpenChange: onOpenChange, useTrapFocusWithTrigger: useTrapFocusWithTrigger, shouldHoldScroll: shouldHoldScroll, role: "dialog", ariaLabel: ariaLabel, ariaLabelledby: ariaLabelledby, recalculateOnScroll: recalculateOnScroll, focusOnOpen: focusOnOpen, children: children }));
28
28
  };
29
29
  exports.ControlledPopup = ControlledPopup;
@@ -134,9 +134,15 @@ const GroupsFilterCurrentlySelectedState = ({
134
134
  translate
135
135
  } = (0, useLanguage_1.useLanguage)();
136
136
  const togglerId = (0, react_1.useId)();
137
- const getActionButton = (label, title, icon, handleClick) => (0, jsx_runtime_1.jsx)("button", {
137
+ const handleBackButtonKeyDown = (0, react_1.useCallback)(event => {
138
+ if (event.key === "ArrowLeft") {
139
+ onBackButtonClick();
140
+ }
141
+ }, [onBackButtonClick]);
142
+ const getActionButton = (label, title, icon, handleClick, handleKeyDown) => (0, jsx_runtime_1.jsx)("button", {
138
143
  type: "button",
139
144
  onClick: handleClick,
145
+ onKeyDown: handleKeyDown,
140
146
  className: "zen-groups-filter-menu__item zen-groups-filter-menu__item--interactive zen-groups-filter-menu__action-button zen-groups-filter-menu__action-button-back",
141
147
  title: title,
142
148
  children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, {
@@ -156,7 +162,7 @@ const GroupsFilterCurrentlySelectedState = ({
156
162
  };
157
163
  return (0, jsx_runtime_1.jsxs)("div", {
158
164
  className: "zen-groups-filter-menu__content-selected",
159
- children: [getActionButton(translate("Back"), translate("Back"), iconBackArrow_1.IconBackArrow, onBackButtonClick), (0, jsx_runtime_1.jsx)("div", {
165
+ children: [getActionButton(translate("Back"), translate("Back"), iconBackArrow_1.IconBackArrow, onBackButtonClick, handleBackButtonKeyDown), (0, jsx_runtime_1.jsx)("div", {
160
166
  className: "zen-groups-filter-menu__item-wrapper",
161
167
  children: (0, jsx_runtime_1.jsx)(toggleButtonRaw_1.ToggleButtonRaw, {
162
168
  onChange: handleTogglerChange,
@@ -298,6 +298,7 @@ const GroupsFilterRaw = props => {
298
298
  const inputRef = (0, react_1.useRef)(null);
299
299
  const emptyInputRef = (0, react_1.useRef)(null);
300
300
  const triggerRef = (0, react_1.useRef)(null);
301
+ const nextFocusableItemRef = (0, react_1.useRef)(false);
301
302
  const menuRef = (0, react_1.useRef)(null);
302
303
  const prevInitialState = (0, react_1.useRef)(initialFilterStateInner);
303
304
  const prevSearchField = (0, react_1.useRef)("");
@@ -320,6 +321,7 @@ const GroupsFilterRaw = props => {
320
321
  type: uiStateActionType_1.UiStateActionType.SetStep,
321
322
  payload: newStep
322
323
  });
324
+ nextFocusableItemRef.current = true;
323
325
  if (((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) && newStep !== groupsFilterInterfaces_1.FilterMenuStep.Initial) {
324
326
  inputRef.current.value = "";
325
327
  dispatchUiState({
@@ -461,6 +463,7 @@ const GroupsFilterRaw = props => {
461
463
  payload: id
462
464
  });
463
465
  handleSetStep(id ? groupsFilterInterfaces_1.FilterMenuStep.Adjustment : groupsFilterInterfaces_1.FilterMenuStep.Initial);
466
+ nextFocusableItemRef.current = true;
464
467
  }, [dispatchUiState, handleSetStep]);
465
468
  const handleCheckboxItemAdjustmentClick = (0, react_1.useCallback)(value => {
466
469
  if (value.id === groupsFilterBox_1.ADVANCED_FILTER_ID) {
@@ -493,6 +496,7 @@ const GroupsFilterRaw = props => {
493
496
  }, [dispatchState, dispatchUiState, state.advancedFilterState, state.frozenState.advancedFilterState, uiState.uncheckedAdvancedState, uiState.uncheckedAdjustmentIds]);
494
497
  const basicHandleBackButtonClick = (0, react_1.useCallback)(() => {
495
498
  handleSetStep(groupsFilterInterfaces_1.FilterMenuStep.Initial);
499
+ nextFocusableItemRef.current = "button.zen-groups-filter-menu__currently-selected-button";
496
500
  }, [handleSetStep]);
497
501
  const handleBackButtonClick = (0, react_1.useCallback)(() => {
498
502
  const currentEl = uiState.currentAdjustmentId ? (0, stateReducerHelper_1.getGroupsTreeItem)(state, uiState.currentAdjustmentId) : undefined;
@@ -506,6 +510,11 @@ const GroupsFilterRaw = props => {
506
510
  payload: isNotRoot ? currentEl.parent.id : undefined
507
511
  });
508
512
  handleSetStep(isNotRoot ? groupsFilterInterfaces_1.FilterMenuStep.Adjustment : groupsFilterInterfaces_1.FilterMenuStep.Initial);
513
+ if (!isNotRoot) {
514
+ nextFocusableItemRef.current = `button[data-btn=${uiState.currentAdjustmentId}]`;
515
+ return;
516
+ }
517
+ nextFocusableItemRef.current = true;
509
518
  }, [basicHandleBackButtonClick, handleSetStep, state, uiState.currentAdjustmentId]);
510
519
  const handleHomeButtonClick = (0, react_1.useCallback)(() => {
511
520
  handleSetStep(groupsFilterInterfaces_1.FilterMenuStep.Initial);
@@ -513,6 +522,7 @@ const GroupsFilterRaw = props => {
513
522
  type: uiStateActionType_1.UiStateActionType.SetCurrentAdjustmentId,
514
523
  payload: undefined
515
524
  });
525
+ nextFocusableItemRef.current = true;
516
526
  }, [handleSetStep, uiState.currentAdjustmentId, dispatchUiState]);
517
527
  const handleCurrentlySelectedClick = (0, react_1.useCallback)(() => {
518
528
  handleSetStep(groupsFilterInterfaces_1.FilterMenuStep.CurrentlySelected);
@@ -714,6 +724,23 @@ const GroupsFilterRaw = props => {
714
724
  }
715
725
  (_c = inputRef.current) === null || _c === void 0 ? void 0 : _c.focus();
716
726
  }, [inputRef]);
727
+ const handleFocusOnPopup = (0, react_1.useCallback)(() => {
728
+ var _a;
729
+ const firstFocusable = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(focusableSelector_1.FOCUSABLE_SELECTOR);
730
+ firstFocusable === null || firstFocusable === void 0 ? void 0 : firstFocusable.focus();
731
+ }, [menuRef]);
732
+ (0, react_1.useEffect)(() => {
733
+ var _a, _b, _c;
734
+ if (nextFocusableItemRef.current) {
735
+ const firstFocusable = chip || isMobile ? (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR)[1] : (_b = menuRef.current) === null || _b === void 0 ? void 0 : _b.querySelector(focusableSelector_1.FOCUSABLE_SELECTOR);
736
+ const nextFocusable = typeof nextFocusableItemRef.current === "string" ? (_c = menuRef.current) === null || _c === void 0 ? void 0 : _c.querySelector(nextFocusableItemRef.current) : firstFocusable;
737
+ if (nextFocusable) {
738
+ nextFocusable.focus();
739
+ nextFocusableItemRef.current = false;
740
+ return;
741
+ }
742
+ }
743
+ }, [uiState.currentAdjustmentId, chip, menuRef, nextFocusableItemRef, isMobile]);
717
744
  (0, react_1.useEffect)(() => {
718
745
  var _a, _b, _c, _d;
719
746
  if (!uiState.isOpen) {
@@ -723,13 +750,18 @@ const GroupsFilterRaw = props => {
723
750
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
724
751
  prevSearchField.current = uiState.searchValue;
725
752
  } else {
726
- const firstFocusable = chip ? (_b = menuRef.current) === null || _b === void 0 ? void 0 : _b.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR)[1] : (_c = menuRef.current) === null || _c === void 0 ? void 0 : _c.querySelector(focusableSelector_1.FOCUSABLE_SELECTOR);
753
+ const firstFocusable = chip || isMobile ? (_b = menuRef.current) === null || _b === void 0 ? void 0 : _b.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR)[1] : (_c = menuRef.current) === null || _c === void 0 ? void 0 : _c.querySelector(focusableSelector_1.FOCUSABLE_SELECTOR);
727
754
  prevSearchField.current = "";
728
- if (firstFocusable && !((_d = inputRef.current) === null || _d === void 0 ? void 0 : _d.value)) {
729
- firstFocusable.focus();
755
+ if (nextFocusableItemRef.current) {
756
+ const nextFocusable = typeof nextFocusableItemRef.current === "string" ? (_d = menuRef.current) === null || _d === void 0 ? void 0 : _d.querySelector(nextFocusableItemRef.current) : firstFocusable;
757
+ if (nextFocusable) {
758
+ nextFocusable.focus();
759
+ nextFocusableItemRef.current = false;
760
+ return;
761
+ }
730
762
  }
731
763
  }
732
- }, [uiState.searchValue, uiState.isOpen, uiState.step, handleSetStep, chip]);
764
+ }, [uiState.searchValue, uiState.isOpen, uiState.step, handleSetStep, chip, isMobile]);
733
765
  (0, react_1.useEffect)(() => {
734
766
  var _a;
735
767
  uiState.isOpen && ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus());
@@ -763,6 +795,7 @@ const GroupsFilterRaw = props => {
763
795
  const selectedCount = (0, stateReducerHelper_1.getFrozenCount)(state);
764
796
  const isStateHasData = Object.keys(state.groupsMap).length > 0;
765
797
  const isApplyDisabled = !(0, stateReducerHelper_1.isStateChanged)(state);
798
+ const isDataEmpty = dataItems.length === 0;
766
799
  const memoizedContent = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsxs)("div", {
767
800
  className: (0, classNames_1.classNames)(["zen-groups-filter-menu", isMobile ? "zen-groups-filter-menu--mobile" : ""]),
768
801
  ref: menuRef,
@@ -776,7 +809,7 @@ const GroupsFilterRaw = props => {
776
809
  id: groupsFilterId,
777
810
  placeholder: translate("Filter by group")
778
811
  })
779
- }) : null, isStateHasData && !uiState.hasError && (0, jsx_runtime_1.jsxs)(groupsFilterMenu_1.GroupsFilterMenu, {
812
+ }) : null, isStateHasData && !uiState.hasError && !(uiState.isLoading && isDataEmpty) && (0, jsx_runtime_1.jsxs)(groupsFilterMenu_1.GroupsFilterMenu, {
780
813
  onCancelClick: handleCancel,
781
814
  onApplyClick: handleApply,
782
815
  onResetClick: handleReset,
@@ -806,10 +839,10 @@ const GroupsFilterRaw = props => {
806
839
  onRelationChange: onRelationChange,
807
840
  children: getGroupsBox()
808
841
  })]
809
- }), !uiState.hasError && !isStateHasData && !Object.keys(state.groupsMap).length && (0, jsx_runtime_1.jsx)(skeletonList_1.SkeletonList, {
842
+ }), (!uiState.hasError && !isStateHasData && !Object.keys(state.groupsMap).length || uiState.isLoading && isDataEmpty) && (0, jsx_runtime_1.jsx)(skeletonList_1.SkeletonList, {
810
843
  className: "zen-groups-filter__waiting"
811
844
  })]
812
- }), [isMobile, chip, onSearchChipChange, uiState.searchValue, uiState.hasError, uiState.step, uiState.currentAdjustmentId, groupsFilterId, translate, isStateHasData, handleCancel, handleApply, handleReset, isApplyDisabled, state, handleAdvancedDialogOpen, handleCurrentlySelectedClick, getSearchResult, getGroupsBox, handleBackButtonClick, handleHomeButtonClick, selectAllHandler, basicHandleBackButtonClick]);
845
+ }), [isMobile, chip, onSearchChipChange, uiState.searchValue, uiState.hasError, uiState.step, uiState.currentAdjustmentId, groupsFilterId, translate, isStateHasData, handleCancel, handleApply, handleReset, isApplyDisabled, state, handleAdvancedDialogOpen, handleCurrentlySelectedClick, getSearchResult, getGroupsBox, handleBackButtonClick, handleHomeButtonClick, selectAllHandler, basicHandleBackButtonClick, uiState.isLoading, isDataEmpty]);
813
846
  const memoizedFooterButtons = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsxs)(footerButtons_1.FooterButtons, {
814
847
  children: [(0, jsx_runtime_1.jsx)(button_1.Button, {
815
848
  onClick: handleApply,
@@ -887,7 +920,7 @@ const GroupsFilterRaw = props => {
887
920
  isOpen: uiState.isOpen,
888
921
  className: (0, classNames_1.classNames)(["zen-groups-filter__popup", uiState.isOpenAdvancedFilter ? "zen-groups-filter__popup--inactive" : "", classNamePopup || ""]),
889
922
  onOpenChange: onOptionsToggle,
890
- useTrapFocusWithTrigger: uiState.isOpenAdvancedFilter ? "off" : "withTrigger",
923
+ useTrapFocusWithTrigger: uiState.isOpenAdvancedFilter ? "off" : "none",
891
924
  shouldHoldScroll: true,
892
925
  triggerRef: triggerRef,
893
926
  ariaLabel: translate("Organization groups filter"),
@@ -928,7 +961,8 @@ const GroupsFilterRaw = props => {
928
961
  ref: triggerRef,
929
962
  fullSize: fullSize,
930
963
  placeholder: groupPlaceHolder,
931
- popupId: popupId
964
+ popupId: popupId,
965
+ handleFocusOnPopup: handleFocusOnPopup
932
966
  }), isMobile ? memoizedMobileView : memoizedDesktopView, uiState.isOpenAdvancedFilter && getAdvancedDialog]
933
967
  });
934
968
  };
@@ -15,9 +15,10 @@ interface IGroupsFilterTrigger {
15
15
  ref?: React.RefObject<HTMLDivElement | null>;
16
16
  isError?: boolean;
17
17
  popupId?: string;
18
+ handleFocusOnPopup?: () => void;
18
19
  }
19
20
  export declare const GroupsFilterTrigger: {
20
- ({ value, className, onChange, placeholder, isOpenPopup, count, withGlobeIcon, inputRef, handleClick, fullSize, ref, isError, popupId, ...otherProps }: IGroupsFilterTrigger): import("react/jsx-runtime").JSX.Element;
21
+ ({ value, className, onChange, placeholder, isOpenPopup, count, withGlobeIcon, inputRef, handleClick, fullSize, ref, isError, popupId, handleFocusOnPopup, ...otherProps }: IGroupsFilterTrigger): import("react/jsx-runtime").JSX.Element;
21
22
  displayName: string;
22
23
  };
23
24
  export declare const TRANSLATIONS: string[];
@@ -89,9 +89,10 @@ const GroupsFilterTrigger = _a => {
89
89
  fullSize,
90
90
  ref,
91
91
  isError,
92
- popupId
92
+ popupId,
93
+ handleFocusOnPopup
93
94
  } = _a,
94
- otherProps = __rest(_a, ["value", "className", "onChange", "placeholder", "isOpenPopup", "count", "withGlobeIcon", "inputRef", "handleClick", "fullSize", "ref", "isError", "popupId"]);
95
+ otherProps = __rest(_a, ["value", "className", "onChange", "placeholder", "isOpenPopup", "count", "withGlobeIcon", "inputRef", "handleClick", "fullSize", "ref", "isError", "popupId", "handleFocusOnPopup"]);
95
96
  const {
96
97
  translate
97
98
  } = (0, useLanguage_1.useLanguage)();
@@ -101,6 +102,12 @@ const GroupsFilterTrigger = _a => {
101
102
  if (e.key === "Enter" && !isOpenPopup) {
102
103
  handleClick();
103
104
  }
105
+ if (e.key === "ArrowDown" && !isOpenPopup) {
106
+ handleClick();
107
+ }
108
+ if (e.key === "ArrowDown" && isOpenPopup) {
109
+ handleFocusOnPopup === null || handleFocusOnPopup === void 0 ? void 0 : handleFocusOnPopup();
110
+ }
104
111
  if (e.key === "Escape" && isOpenPopup && e.nativeEvent) {
105
112
  e.nativeEvent.stopImmediatePropagation();
106
113
  handleClick();
package/dist/index.css CHANGED
@@ -1653,6 +1653,7 @@
1653
1653
  position: absolute;
1654
1654
  z-index: 11000;
1655
1655
  overflow-y: auto;
1656
+ outline: none;
1656
1657
  }
1657
1658
  .zen-absolute * {
1658
1659
  box-sizing: border-box;
@@ -2813,7 +2814,7 @@
2813
2814
  padding: 12px 8px 12px 16px;
2814
2815
  }
2815
2816
  .zen-menu-button__action:focus,
2816
- .zen-menu-button__action:focus-within,
2817
+ .zen-menu-button__action:focus-visible,
2817
2818
  .zen-menu-button__action:hover:not(.zen-menu-button__action--disabled):not(.zen-menu-button__action--selected):not(.zen-menu-button__action--active) {
2818
2819
  color: var(--text-primary);
2819
2820
  fill: var(--text-secondary);
@@ -3534,6 +3535,9 @@
3534
3535
  left: 0;
3535
3536
  }
3536
3537
  }
3538
+ .zen-action-list {
3539
+ outline: none;
3540
+ }
3537
3541
  .zen-controlled-menu {
3538
3542
  z-index: 11002;
3539
3543
  }
@@ -5316,12 +5320,59 @@
5316
5320
  }
5317
5321
  .zen-summary-tile__trigger {
5318
5322
  cursor: pointer;
5323
+ background: none;
5324
+ border: none;
5325
+ padding: 0;
5326
+ line-height: 0;
5327
+ position: relative;
5328
+ }
5329
+ .zen-summary-tile__trigger::before {
5330
+ content: "";
5331
+ position: absolute;
5332
+ top: 50%;
5333
+ left: 50%;
5334
+ transform: translate(-50%, -50%);
5335
+ width: 24px;
5336
+ height: 24px;
5337
+ }
5338
+ .zen-summary-tile__trigger:focus-visible {
5339
+ outline: 2px solid var(--borders-form-field--active);
5340
+ outline-offset: 2px;
5341
+ border-radius: 2px;
5342
+ }
5343
+ .zen-summary-tile--action > .zen-summary-tile__trigger {
5344
+ position: absolute;
5345
+ top: 12px;
5346
+ right: 12px;
5319
5347
  }
5320
5348
  .zen-summary-tile--action {
5321
5349
  cursor: pointer;
5322
5350
  display: flex;
5323
5351
  flex-direction: column;
5324
5352
  text-align: start;
5353
+ position: relative;
5354
+ }
5355
+ .zen-summary-tile__clickable-area {
5356
+ background: none;
5357
+ border: none;
5358
+ padding: 0;
5359
+ cursor: pointer;
5360
+ display: flex;
5361
+ flex-direction: column;
5362
+ text-align: start;
5363
+ width: 100%;
5364
+ height: 100%;
5365
+ color: inherit;
5366
+ fill: inherit;
5367
+ font: inherit;
5368
+ border-radius: inherit;
5369
+ }
5370
+ .zen-summary-tile__clickable-area:focus-visible {
5371
+ outline: none;
5372
+ }
5373
+ .zen-summary-tile--action:has(.zen-summary-tile__clickable-area:focus-visible) {
5374
+ outline: 2px solid var(--borders-form-field--active);
5375
+ outline-offset: -1px;
5325
5376
  }
5326
5377
  .zen-summary-tile__title-block {
5327
5378
  height: 16px;
@@ -8481,7 +8532,7 @@
8481
8532
  .zen-status-pill__pill-container {
8482
8533
  display: flex;
8483
8534
  align-items: center;
8484
- gap: 8px;
8535
+ gap: 4px;
8485
8536
  position: relative;
8486
8537
  cursor: pointer;
8487
8538
  }
@@ -8500,6 +8551,9 @@
8500
8551
  .zen-status-pill__pill-container:hover .zen-status-pill__container--error {
8501
8552
  border-color: var(--accents-error--detail);
8502
8553
  }
8554
+ .zen-status-pill__pill-container:hover .zen-status-pill__container--upsell {
8555
+ border-color: var(--action-secondary--hover);
8556
+ }
8503
8557
  .zen-status-pill__container {
8504
8558
  font-family: var(--main-font);
8505
8559
  font-size: 12px;
@@ -8583,8 +8637,15 @@
8583
8637
  .zen-status-pill__container--error:hover {
8584
8638
  border-color: var(--accents-error--detail);
8585
8639
  }
8586
- .zen-status-pill__container:focus-visible,
8587
- .zen-status-pill__container:focus-visible + .zen-status-pill__container {
8640
+ .zen-status-pill__container--upsell {
8641
+ background-color: var(--action-secondary--default);
8642
+ fill: var(--text-reverse-primary);
8643
+ color: var(--text-reverse-primary);
8644
+ }
8645
+ .zen-status-pill__container--upsell:hover {
8646
+ border-color: var(--action-secondary--hover);
8647
+ }
8648
+ .zen-status-pill__container:focus-visible {
8588
8649
  outline: none;
8589
8650
  border-color: var(--borders-form-field--active);
8590
8651
  }
@@ -8609,6 +8670,12 @@
8609
8670
  .zen-status-pill__text--error {
8610
8671
  color: var(--accents-error--detail);
8611
8672
  }
8673
+ .zen-status-pill__text--upsell {
8674
+ color: var(--text-reverse-primary);
8675
+ }
8676
+ .zen-status-pill__text--centered {
8677
+ margin-right: 0;
8678
+ }
8612
8679
  .zen-status-pill__expand-button {
8613
8680
  padding: 0;
8614
8681
  margin-left: auto;
@@ -8634,13 +8701,20 @@
8634
8701
  fill: var(--accents-error--detail);
8635
8702
  color: var(--accents-error--detail);
8636
8703
  }
8704
+ .zen-status-pill__expand-button--upsell {
8705
+ fill: var(--text-reverse-primary);
8706
+ color: var(--text-reverse-primary);
8707
+ }
8637
8708
  .zen-status-pill__icon {
8638
8709
  display: flex;
8639
8710
  align-items: center;
8640
- height: 16px;
8711
+ height: 12px;
8641
8712
  margin-right: 4px;
8642
8713
  flex-shrink: 0;
8643
8714
  }
8715
+ .zen-status-pill__icon--large {
8716
+ height: 16px;
8717
+ }
8644
8718
  .zen-status-pill__icon--default {
8645
8719
  fill: var(--action-secondary--default);
8646
8720
  color: var(--action-secondary--default);
@@ -8661,25 +8735,71 @@
8661
8735
  fill: var(--accents-error--detail);
8662
8736
  color: var(--accents-error--detail);
8663
8737
  }
8738
+ .zen-status-pill__icon--upsell {
8739
+ fill: var(--text-reverse-primary);
8740
+ color: var(--text-reverse-primary);
8741
+ }
8664
8742
  .zen-status-pill__icon--standalone {
8665
8743
  margin-right: 0;
8666
8744
  }
8667
- .zen-status-pill-popup__main-pill {
8668
- display: flex;
8669
- align-items: center;
8670
- gap: 8px;
8745
+ .zen-absolute:has(.zen-status-pill-popup) {
8746
+ overflow: visible;
8747
+ }
8748
+ .zen-status-pill-popup {
8749
+ box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.2);
8750
+ border-radius: 4px;
8751
+ background-color: white;
8752
+ max-height: 560px;
8753
+ overflow: hidden;
8754
+ outline: none;
8671
8755
  }
8672
8756
  .zen-status-pill-popup__container {
8673
- box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, 0.2);
8674
8757
  display: flex;
8675
8758
  flex-direction: column;
8676
- border-radius: 8px;
8677
- padding: 16px 16px 16px 16px;
8759
+ padding: 12px 8px;
8678
8760
  gap: 16px;
8679
- background-color: white;
8680
- width: 308px;
8681
- margin: 10px;
8682
- max-height: 420px;
8761
+ overflow-y: auto;
8762
+ max-height: 480px;
8763
+ }
8764
+ .zen-status-pill-popup__container--small {
8765
+ width: 220px;
8766
+ }
8767
+ .zen-status-pill-popup__container--medium {
8768
+ width: 320px;
8769
+ }
8770
+ .zen-status-pill-popup__container--large {
8771
+ width: 420px;
8772
+ }
8773
+ .zen-status-pill-popup__title-item {
8774
+ display: flex;
8775
+ align-items: center;
8776
+ padding: 12px 8px;
8777
+ gap: 16px;
8778
+ border-bottom: 1px solid var(--borders-general);
8779
+ }
8780
+ .zen-status-pill-popup__title-item-text {
8781
+ flex: 1;
8782
+ min-width: 0;
8783
+ overflow: hidden;
8784
+ text-overflow: ellipsis;
8785
+ white-space: nowrap;
8786
+ color: var(--text-secondary);
8787
+ font-feature-settings: 'liga' off, 'clig' off;
8788
+ font-family: Roboto, sans-serif;
8789
+ font-size: 14px;
8790
+ font-style: normal;
8791
+ font-weight: 500;
8792
+ line-height: 16px;
8793
+ letter-spacing: 0.16px;
8794
+ }
8795
+ .zen-status-pill-popup__footer {
8796
+ display: flex;
8797
+ flex-direction: column;
8798
+ }
8799
+ .zen-status-pill-popup__children {
8800
+ display: flex;
8801
+ flex-direction: column;
8802
+ gap: 8px;
8683
8803
  }
8684
8804
  .zen-status-pill-popup__content-header {
8685
8805
  display: flex;
@@ -8749,10 +8869,61 @@
8749
8869
  .zen-status-pill-popup__actions {
8750
8870
  display: flex;
8751
8871
  flex-direction: column;
8752
- gap: 8px;
8872
+ gap: 4px;
8753
8873
  }
8754
8874
  .zen-status-pill-popup__divider.zen-divider {
8755
- background-color: var(--borders-secondary);
8875
+ background-color: var(--borders-general);
8876
+ }
8877
+ .zen-status-pill-popup--mobile .zen-mobile-sheet__title {
8878
+ border-bottom: 1px solid var(--borders-general);
8879
+ }
8880
+ .zen-status-pill-popup--mobile .zen-mobile-sheet__content {
8881
+ padding: 16px;
8882
+ max-height: 90vh;
8883
+ overflow-y: auto;
8884
+ }
8885
+ .zen-status-pill-popup__mobile-title {
8886
+ font-family: var(--main-font);
8887
+ font-size: 16px;
8888
+ font-style: normal;
8889
+ font-weight: 500;
8890
+ letter-spacing: 0;
8891
+ line-height: 24px;
8892
+ text-transform: none;
8893
+ color: var(--text-primary);
8894
+ }
8895
+ .zen-status-pill-popup__mobile-content {
8896
+ display: flex;
8897
+ flex-direction: column;
8898
+ gap: 16px;
8899
+ }
8900
+ .zen-status-pill-popup__view-more-button {
8901
+ display: flex;
8902
+ align-items: center;
8903
+ justify-content: center;
8904
+ gap: 8px;
8905
+ margin: 16px 8px 8px;
8906
+ }
8907
+ .zen-status-pill-popup__view-more-badge {
8908
+ font-family: var(--main-font);
8909
+ font-size: 12px;
8910
+ font-style: normal;
8911
+ font-weight: 400;
8912
+ letter-spacing: 0.32px;
8913
+ line-height: 16px;
8914
+ text-transform: none;
8915
+ display: inline-flex;
8916
+ align-items: center;
8917
+ justify-content: center;
8918
+ min-width: 22px;
8919
+ height: 22px;
8920
+ padding: 0 6px;
8921
+ border-radius: 999px;
8922
+ background-color: var(--action-primary--default);
8923
+ color: var(--text-reverse-primary);
8924
+ line-height: 1;
8925
+ text-align: center;
8926
+ box-sizing: border-box;
8756
8927
  }
8757
8928
  .zen-beta-pill--mobile {
8758
8929
  min-width: unset;
@@ -9400,6 +9571,25 @@ button.zen-summary__clickable {
9400
9571
  display: flex;
9401
9572
  fill: var(--text-secondary);
9402
9573
  justify-content: center;
9574
+ background: none;
9575
+ border: none;
9576
+ padding: 0;
9577
+ line-height: 0;
9578
+ position: relative;
9579
+ }
9580
+ .zen-summary__trigger::before {
9581
+ content: "";
9582
+ position: absolute;
9583
+ top: 50%;
9584
+ left: 50%;
9585
+ transform: translate(-50%, -50%);
9586
+ width: 24px;
9587
+ height: 24px;
9588
+ }
9589
+ .zen-summary__trigger:focus-visible {
9590
+ outline: 2px solid var(--borders-form-field--active);
9591
+ outline-offset: 2px;
9592
+ border-radius: 2px;
9403
9593
  }
9404
9594
  .zen-summary__data {
9405
9595
  align-items: center;
package/dist/index.d.ts CHANGED
@@ -720,7 +720,7 @@ export { PageLayout } from "./pageLayout/pageLayout";
720
720
  export { type IPagination, Pagination } from "./pagination/pagination";
721
721
  export { PaginationType } from "./pagination/paginationType";
722
722
  export { Pill } from "./pill/pill";
723
- export { type IPillExpandableAction, type IBaseData, type IPromisedBaseData, type IPillExpandable, PillExpandable } from "./pillExpandable/pillExpandable";
723
+ export { type IPillExpandableAction, type IBaseData, type IPromisedBaseData, type TPopoverSize, type IPillExpandable, PillExpandable } from "./pillExpandable/pillExpandable";
724
724
  export { type IPopup, Popup } from "./popup/popup";
725
725
  export { type IPrimaryIcon, PrimaryIcon } from "./primaryIcon/primaryIcon";
726
726
  export { ProgressBarType, ProgreesBarSize, type TProgressBarSize, ProgressBar } from "./progressBar/progressBar";
@@ -14,9 +14,11 @@ interface IMarkerClasses {
14
14
  * If not provided, defaults to 'zen-list-item' based classes
15
15
  * @param onBeforeDragOver - Optional callback function called before placing the placeholder at a new position.
16
16
  * Receives the target position and should return false to prevent the drag operation.
17
+ * @param itemsGap - Optional gap size in pixels between list items. Used to adjust placeholder positioning
18
+ * calculations during drag operations. Defaults to 0.
17
19
  * @returns An object containing the `onDragStart` event handler to be attached to draggable elements
18
20
  */
19
- export declare const useDragAndDrop: (containerRef: RefObject<HTMLElement | null>, onChangeOrder: (startPosition: number, endPosition: number) => void, marksClassNames?: IMarkerClasses, onBeforeDragOver?: (endPosition: number) => boolean) => {
21
+ export declare const useDragAndDrop: (containerRef: RefObject<HTMLElement | null>, onChangeOrder: (startPosition: number, endPosition: number) => void, marksClassNames?: IMarkerClasses, onBeforeDragOver?: (endPosition: number) => boolean, itemsGap?: number) => {
20
22
  onDragStart: (e: React.PointerEvent<HTMLElement>) => void;
21
23
  };
22
24
  export {};