@geotab/zenith 3.6.3 → 3.7.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 (149) hide show
  1. package/README.md +15 -0
  2. package/dist/absolute/absolute.d.ts +3 -1
  3. package/dist/absolute/absolute.js +4 -4
  4. package/dist/checkbox/checkbox.d.ts +3 -1
  5. package/dist/checkbox/checkbox.js +5 -8
  6. package/dist/checkboxListWithAction/checkboxListWithAction.d.ts +3 -1
  7. package/dist/checkboxListWithAction/checkboxListWithAction.js +185 -3
  8. package/dist/controlledPopup/controlledPopup.d.ts +3 -1
  9. package/dist/controlledPopup/controlledPopup.js +2 -2
  10. package/dist/dropdown/dropdownPopup.d.ts +1 -1
  11. package/dist/dropdown/dropdownTrigger.d.ts +1 -1
  12. package/dist/dropdownRaw/dropdownList.d.ts +2 -1
  13. package/dist/dropdownRaw/dropdownList.js +15 -4
  14. package/dist/dropdownRaw/dropdownPopup.d.ts +3 -1
  15. package/dist/dropdownRaw/dropdownPopup.js +35 -5
  16. package/dist/dropdownRaw/dropdownRaw.js +82 -7
  17. package/dist/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
  18. package/dist/dropdownRaw/dropdownSearchableTrigger.js +7 -2
  19. package/dist/dropdownRaw/dropdownTrigger.d.ts +2 -1
  20. package/dist/dropdownRaw/dropdownTrigger.js +3 -5
  21. package/dist/footerButtons/footerButtons.d.ts +6 -4
  22. package/dist/footerButtons/footerButtons.js +3 -8
  23. package/dist/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +8 -2
  24. package/dist/groupsFilterRaw/groupsFilterInitialState.js +16 -0
  25. package/dist/groupsFilterRaw/groupsFilterRaw.js +43 -9
  26. package/dist/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
  27. package/dist/groupsFilterRaw/groupsFilterTrigger.js +13 -2
  28. package/dist/index.css +222 -18
  29. package/dist/index.d.ts +1 -1
  30. package/dist/list/hooks/useDragAndDrop.d.ts +3 -1
  31. package/dist/list/hooks/useDragAndDrop.js +11 -4
  32. package/dist/menu/components/menuItem.js +12 -2
  33. package/dist/menu/contexts/pathContext.d.ts +3 -1
  34. package/dist/menu/contexts/pathProvider.d.ts +1 -1
  35. package/dist/menu/contexts/pathProvider.js +1 -1
  36. package/dist/menu/controlledMenu.js +97 -29
  37. package/dist/nav/nav.d.ts +2 -1
  38. package/dist/nav/nav.js +3 -2
  39. package/dist/nav/navEditList/navEditList.js +2 -1
  40. package/dist/nav/navItem/navItem.d.ts +1 -0
  41. package/dist/nav/navItem/navItem.js +4 -1
  42. package/dist/pillExpandable/pillContent.d.ts +2 -1
  43. package/dist/pillExpandable/pillContent.js +8 -3
  44. package/dist/pillExpandable/pillExpandable.d.ts +27 -4
  45. package/dist/pillExpandable/pillExpandable.js +426 -196
  46. package/dist/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
  47. package/dist/pillExpandable/pillExpandablePopoverContent.js +7 -0
  48. package/dist/pillExpandable/pillExpandableSimple.d.ts +5 -3
  49. package/dist/pillExpandable/pillExpandableSimple.js +12 -5
  50. package/dist/summary/summary.js +29 -1
  51. package/dist/summaryTile/summaryTile.d.ts +2 -1
  52. package/dist/summaryTile/summaryTile.js +175 -65
  53. package/dist/summaryTile/summaryTileTrigger.d.ts +1 -1
  54. package/dist/summaryTile/summaryTileTrigger.js +1 -1
  55. package/dist/toggleButtonRaw/toggleButtonRaw.js +2 -1
  56. package/dist/utils/localization/getSupportedLanguage.d.ts +2 -2
  57. package/dist/utils/localization/getSupportedLanguage.js +28 -8
  58. package/dist/utils/localization/languageContext.d.ts +1 -1
  59. package/dist/utils/localization/translations/cs.json +2 -1
  60. package/dist/utils/localization/translations/de.json +2 -1
  61. package/dist/utils/localization/translations/en.json +2 -1
  62. package/dist/utils/localization/translations/es.json +2 -1
  63. package/dist/utils/localization/translations/fr-FR.json +2 -1
  64. package/dist/utils/localization/translations/fr.json +2 -1
  65. package/dist/utils/localization/translations/id.json +2 -1
  66. package/dist/utils/localization/translations/it.json +2 -1
  67. package/dist/utils/localization/translations/ja.json +2 -1
  68. package/dist/utils/localization/translations/ms.json +2 -1
  69. package/dist/utils/localization/translations/nl.json +2 -1
  70. package/dist/utils/localization/translations/pl.json +2 -1
  71. package/dist/utils/localization/translations/pt-BR.json +2 -1
  72. package/dist/utils/localization/translations/sv.json +2 -1
  73. package/dist/utils/localization/translations/th.json +2 -1
  74. package/dist/utils/localization/translations/tr.json +2 -1
  75. package/dist/utils/localization/translations/zh-Hans.json +2 -1
  76. package/esm/absolute/absolute.d.ts +3 -1
  77. package/esm/absolute/absolute.js +4 -4
  78. package/esm/checkbox/checkbox.d.ts +3 -1
  79. package/esm/checkbox/checkbox.js +5 -8
  80. package/esm/checkboxListWithAction/checkboxListWithAction.d.ts +3 -1
  81. package/esm/checkboxListWithAction/checkboxListWithAction.js +186 -4
  82. package/esm/controlledPopup/controlledPopup.d.ts +3 -1
  83. package/esm/controlledPopup/controlledPopup.js +2 -2
  84. package/esm/dropdown/dropdownPopup.d.ts +1 -1
  85. package/esm/dropdown/dropdownTrigger.d.ts +1 -1
  86. package/esm/dropdownRaw/dropdownList.d.ts +2 -1
  87. package/esm/dropdownRaw/dropdownList.js +16 -5
  88. package/esm/dropdownRaw/dropdownPopup.d.ts +3 -1
  89. package/esm/dropdownRaw/dropdownPopup.js +37 -7
  90. package/esm/dropdownRaw/dropdownRaw.js +82 -7
  91. package/esm/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
  92. package/esm/dropdownRaw/dropdownSearchableTrigger.js +7 -2
  93. package/esm/dropdownRaw/dropdownTrigger.d.ts +2 -1
  94. package/esm/dropdownRaw/dropdownTrigger.js +3 -5
  95. package/esm/footerButtons/footerButtons.d.ts +6 -4
  96. package/esm/footerButtons/footerButtons.js +3 -8
  97. package/esm/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +9 -3
  98. package/esm/groupsFilterRaw/groupsFilterInitialState.js +16 -0
  99. package/esm/groupsFilterRaw/groupsFilterRaw.js +43 -9
  100. package/esm/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
  101. package/esm/groupsFilterRaw/groupsFilterTrigger.js +13 -2
  102. package/esm/index.d.ts +1 -1
  103. package/esm/list/hooks/useDragAndDrop.d.ts +3 -1
  104. package/esm/list/hooks/useDragAndDrop.js +11 -4
  105. package/esm/menu/components/menuItem.js +12 -2
  106. package/esm/menu/contexts/pathContext.d.ts +3 -1
  107. package/esm/menu/contexts/pathProvider.d.ts +1 -1
  108. package/esm/menu/contexts/pathProvider.js +1 -1
  109. package/esm/menu/controlledMenu.js +98 -30
  110. package/esm/nav/nav.d.ts +2 -1
  111. package/esm/nav/nav.js +3 -2
  112. package/esm/nav/navEditList/navEditList.js +2 -1
  113. package/esm/nav/navItem/navItem.d.ts +1 -0
  114. package/esm/nav/navItem/navItem.js +5 -2
  115. package/esm/pillExpandable/pillContent.d.ts +2 -1
  116. package/esm/pillExpandable/pillContent.js +8 -3
  117. package/esm/pillExpandable/pillExpandable.d.ts +27 -4
  118. package/esm/pillExpandable/pillExpandable.js +427 -197
  119. package/esm/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
  120. package/esm/pillExpandable/pillExpandablePopoverContent.js +3 -0
  121. package/esm/pillExpandable/pillExpandableSimple.d.ts +5 -3
  122. package/esm/pillExpandable/pillExpandableSimple.js +12 -5
  123. package/esm/summary/summary.js +29 -1
  124. package/esm/summaryTile/summaryTile.d.ts +2 -1
  125. package/esm/summaryTile/summaryTile.js +140 -43
  126. package/esm/summaryTile/summaryTileTrigger.d.ts +1 -1
  127. package/esm/summaryTile/summaryTileTrigger.js +1 -1
  128. package/esm/toggleButtonRaw/toggleButtonRaw.js +2 -1
  129. package/esm/utils/localization/getSupportedLanguage.d.ts +2 -2
  130. package/esm/utils/localization/getSupportedLanguage.js +28 -8
  131. package/esm/utils/localization/languageContext.d.ts +1 -1
  132. package/esm/utils/localization/translations/cs.json +2 -1
  133. package/esm/utils/localization/translations/de.json +2 -1
  134. package/esm/utils/localization/translations/en.json +2 -1
  135. package/esm/utils/localization/translations/es.json +2 -1
  136. package/esm/utils/localization/translations/fr-FR.json +2 -1
  137. package/esm/utils/localization/translations/fr.json +2 -1
  138. package/esm/utils/localization/translations/id.json +2 -1
  139. package/esm/utils/localization/translations/it.json +2 -1
  140. package/esm/utils/localization/translations/ja.json +2 -1
  141. package/esm/utils/localization/translations/ms.json +2 -1
  142. package/esm/utils/localization/translations/nl.json +2 -1
  143. package/esm/utils/localization/translations/pl.json +2 -1
  144. package/esm/utils/localization/translations/pt-BR.json +2 -1
  145. package/esm/utils/localization/translations/sv.json +2 -1
  146. package/esm/utils/localization/translations/th.json +2 -1
  147. package/esm/utils/localization/translations/tr.json +2 -1
  148. package/esm/utils/localization/translations/zh-Hans.json +2 -1
  149. package/package.json +4 -7
package/README.md CHANGED
@@ -54,6 +54,21 @@ Zenith library provides components defined in Zenith Design System. It includes
54
54
 
55
55
  ## Change log
56
56
 
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
+ - Add `onDropdownStateChange` callback to NavItem
71
+
57
72
  ### 3.6.3
58
73
 
59
74
  Patch for the `Nav` component.
@@ -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) {
@@ -13,5 +13,7 @@ export interface ICheckbox extends IZenComponentProps {
13
13
  reverse?: boolean;
14
14
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
15
15
  wrapped?: boolean;
16
+ tabIndex?: number;
17
+ describedBy?: string;
16
18
  }
17
- export declare const Checkbox: ({ reverse, fullWidth, id, checked, indeterminate, title, className, children, disabled, wrapped, ...rest }: ICheckbox) => import("react/jsx-runtime").JSX.Element;
19
+ export declare const Checkbox: ({ reverse, fullWidth, id, checked, indeterminate, title, className, children, disabled, wrapped, describedBy, ...rest }: ICheckbox) => import("react/jsx-runtime").JSX.Element;
@@ -46,21 +46,18 @@ const checkboxIconCheckmark_1 = require("./checkboxIconCheckmark");
46
46
  const checkboxIconMinus_1 = require("./checkboxIconMinus");
47
47
  const useMobile_1 = require("../commonHelpers/hooks/useMobile");
48
48
  const Checkbox = (_a) => {
49
- var { reverse, fullWidth, id, checked, indeterminate, title, className = "", children, disabled, wrapped } = _a, rest = __rest(_a, ["reverse", "fullWidth", "id", "checked", "indeterminate", "title", "className", "children", "disabled", "wrapped"]);
49
+ var { reverse, fullWidth, id, checked, indeterminate, title, className = "", children, disabled, wrapped, describedBy } = _a, rest = __rest(_a, ["reverse", "fullWidth", "id", "checked", "indeterminate", "title", "className", "children", "disabled", "wrapped", "describedBy"]);
50
50
  const state = (0, checkboxUtils_1.getCheckboxState)(checked, indeterminate);
51
51
  const generatedId = react_1.default.useId();
52
52
  const intId = id || generatedId;
53
53
  const driveClasses = (0, useDriveClassName_1.useDriveClassName)("zen-checkbox");
54
54
  const isMobile = (0, useMobile_1.useMobile)();
55
55
  const checkboxIconClasses = (0, react_1.useMemo)(() => (0, classNames_1.classNames)(["zen-checkbox__icon", disabled ? "zen-checkbox__icon--disabled" : ""]), [disabled]);
56
- const checkbox = (0, jsx_runtime_1.jsx)(triStateCheckbox_1.TriStateCheckbox, Object.assign({ className: "zen-checkbox__input", id: intId, checked: checked, indeterminate: indeterminate, disabled: disabled, "aria-label": title }, rest));
57
- const iconAndLabel = (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "zen-checkbox__box", children: state === checkboxState_1.CheckboxState.Indeterminate ? (0, jsx_runtime_1.jsx)(checkboxIconMinus_1.CheckboxIconMinus, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" }) :
58
- state === checkboxState_1.CheckboxState.On ? (0, jsx_runtime_1.jsx)(checkboxIconCheckmark_1.CheckboxIconCheckmark, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" }) : null }), children
59
- ? (0, jsx_runtime_1.jsx)("div", { className: (0, classNames_1.classNames)(["zen-checkbox__label-text", fullWidth ? "zen-checkbox__label-text--full-width" : ""]), children: children })
60
- : null] });
56
+ const checkbox = ((0, jsx_runtime_1.jsx)(triStateCheckbox_1.TriStateCheckbox, Object.assign({ className: "zen-checkbox__input", id: intId, checked: checked, indeterminate: indeterminate, disabled: disabled, "aria-label": title, "aria-describedby": describedBy }, rest)));
57
+ const iconAndLabel = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "zen-checkbox__box", children: state === checkboxState_1.CheckboxState.Indeterminate ? ((0, jsx_runtime_1.jsx)(checkboxIconMinus_1.CheckboxIconMinus, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" })) : state === checkboxState_1.CheckboxState.On ? ((0, jsx_runtime_1.jsx)(checkboxIconCheckmark_1.CheckboxIconCheckmark, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" })) : null }), children ? (0, jsx_runtime_1.jsx)("div", { className: (0, classNames_1.classNames)(["zen-checkbox__label-text", fullWidth ? "zen-checkbox__label-text--full-width" : ""]), children: children }) : null] }));
61
58
  if (wrapped) {
62
- return (0, jsx_runtime_1.jsxs)("label", { className: (0, classNames_1.classNames)(["zen-checkbox", driveClasses || "", className]), title: title, children: [checkbox, (0, jsx_runtime_1.jsx)("div", { className: (0, classNames_1.classNames)(["zen-checkbox__label", reverse ? "zen-checkbox__label--reverse" : ""]), children: iconAndLabel })] });
59
+ return ((0, jsx_runtime_1.jsxs)("label", { className: (0, classNames_1.classNames)(["zen-checkbox", driveClasses || "", className]), title: title, children: [checkbox, (0, jsx_runtime_1.jsx)("div", { className: (0, classNames_1.classNames)(["zen-checkbox__label", reverse ? "zen-checkbox__label--reverse" : ""]), children: iconAndLabel })] }));
63
60
  }
64
- return (0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-checkbox", isMobile && !driveClasses ? "zen-checkbox--mobile" : "", driveClasses || "", className]), children: [checkbox, (0, jsx_runtime_1.jsx)("label", { className: (0, classNames_1.classNames)(["zen-checkbox__label", reverse ? "zen-checkbox__label--reverse" : ""]), htmlFor: intId, title: title, children: iconAndLabel })] });
61
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-checkbox", isMobile && !driveClasses ? "zen-checkbox--mobile" : "", driveClasses || "", className]), children: [checkbox, (0, jsx_runtime_1.jsx)("label", { className: (0, classNames_1.classNames)(["zen-checkbox__label", reverse ? "zen-checkbox__label--reverse" : ""]), htmlFor: intId, title: title, children: iconAndLabel })] }));
65
62
  };
66
63
  exports.Checkbox = Checkbox;
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import "./checkboxListWithAction.less";
2
3
  import { IZenComponentProps } from "../commonHelpers/zenComponent";
3
4
  import { IColor } from "../groupsFilterRaw/groupsFilterInterfaces";
@@ -23,6 +24,7 @@ export interface ICheckboxListWithAction extends IZenComponentProps {
23
24
  search?: string[];
24
25
  onChange: (value: IChangeCheckbox) => void;
25
26
  onClick: (id: string) => void;
27
+ handleTab?: (e: React.KeyboardEvent, shift?: boolean) => void;
26
28
  }
27
- export declare const CheckboxListWithAction: ({ label, options, onChange, onClick, search, className }: ICheckboxListWithAction) => import("react/jsx-runtime").JSX.Element;
29
+ export declare const CheckboxListWithAction: ({ label, options, onChange, onClick, search, className, handleTab }: ICheckboxListWithAction) => import("react/jsx-runtime").JSX.Element;
28
30
  export declare const TRANSLATIONS: string[];
@@ -87,6 +87,7 @@ injectString("tr", "Toggle {groupName} filter", "{groupName} filtresini de\u011F
87
87
  injectString("zh-Hans", "Toggle {groupName} filter", "\u5207\u6362 {groupName} \u7B5B\u9009\u5668");
88
88
  injectString("zh-TW", "Toggle {groupName} filter", "\u5207\u63DB\u300C{groupName}\u300D\u7BE9\u9078\u689D\u4EF6");
89
89
  injectString("ro-RO", "Toggle {groupName} filter", "Activa\u021Bi filtrul {groupName}");
90
+ injectString("en", "Has additional actions. Use right arrow to access button, left arrow to return.", "Has additional actions. Use right arrow to access button, left arrow to return.");
90
91
  const checkbox_1 = require("../checkbox/checkbox");
91
92
  const classNames_1 = require("../commonHelpers/classNames/classNames");
92
93
  const iconChevronRight_1 = require("../icons/iconChevronRight");
@@ -98,7 +99,8 @@ const CheckboxListWithAction = ({
98
99
  onChange,
99
100
  onClick,
100
101
  search = [],
101
- className
102
+ className,
103
+ handleTab
102
104
  }) => {
103
105
  const {
104
106
  translate
@@ -106,6 +108,11 @@ const CheckboxListWithAction = ({
106
108
  const driveComponentClass = (0, useDriveClassName_1.useDriveClassName)("zen-checkbox-list-with-action");
107
109
  const listId = (0, react_1.useId)();
108
110
  const checkboxId = `${listId}_check_list-item_`;
111
+ const navigationInstructionsId = `${listId}_navigation_instructions`;
112
+ const listRef = (0, react_1.useRef)(null);
113
+ const [focusedRowIndex, setFocusedRowIndex] = (0, react_1.useState)(0);
114
+ const [focusedElementType, setFocusedElementType] = (0, react_1.useState)("checkbox");
115
+ const isInitialized = (0, react_1.useRef)(false);
109
116
  const handleChange = e => {
110
117
  const evtTarget = e.target;
111
118
  const elId = evtTarget.getAttribute("id").replace(checkboxId, "");
@@ -120,7 +127,171 @@ const CheckboxListWithAction = ({
120
127
  const evtTarget = e.target;
121
128
  const elId = evtTarget.getAttribute("data-btn") || ((_a = evtTarget.parentElement) === null || _a === void 0 ? void 0 : _a.getAttribute("data-btn")) || "";
122
129
  onClick(elId);
130
+ setFocusedElementType("checkbox");
123
131
  };
132
+ const getFocusableElements = (0, react_1.useCallback)(() => {
133
+ if (!listRef.current || !options) return [];
134
+ const elements = [];
135
+ options.forEach((opt, rowIndex) => {
136
+ var _a;
137
+ const listItem = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(`li[data-item="${opt.property}"]`);
138
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
139
+ if (listItem) {
140
+ const checkbox = listItem.querySelector('input[type="checkbox"]');
141
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
142
+ if (checkbox) {
143
+ elements.push({
144
+ element: checkbox,
145
+ rowIndex,
146
+ type: "checkbox",
147
+ blocked: opt.blocked
148
+ });
149
+ }
150
+ if (opt.isWithAction) {
151
+ const button = listItem.querySelector("button[data-btn]");
152
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
153
+ if (button) {
154
+ elements.push({
155
+ element: button,
156
+ rowIndex,
157
+ type: "button",
158
+ blocked: opt.blocked
159
+ });
160
+ }
161
+ }
162
+ }
163
+ });
164
+ return elements;
165
+ }, [options]);
166
+ const updateTabIndex = (0, react_1.useCallback)((newRowIndex, newElementType) => {
167
+ const elements = getFocusableElements();
168
+ elements.forEach(({
169
+ element,
170
+ rowIndex,
171
+ type,
172
+ blocked
173
+ }) => {
174
+ const isActive = rowIndex === newRowIndex && type === newElementType && !blocked;
175
+ element.setAttribute("tabindex", isActive ? "0" : "-1");
176
+ });
177
+ }, [getFocusableElements]);
178
+ const handleKeyDown = (0, react_1.useCallback)(
179
+ // eslint-disable-next-line complexity
180
+ e => {
181
+ var _a;
182
+ const elements = getFocusableElements();
183
+ if (elements.length === 0 || !options) return;
184
+ let newRowIndex = focusedRowIndex;
185
+ let newElementType = focusedElementType;
186
+ let preventDefault = false;
187
+ if (e.key === "Enter") {
188
+ const evtTarget = e.target;
189
+ const elId = ((_a = evtTarget.getAttribute("id")) === null || _a === void 0 ? void 0 : _a.replace(checkboxId, "")) || "";
190
+ elId && onChange({
191
+ id: elId,
192
+ state: evtTarget.checked,
193
+ partial: evtTarget.dataset.indeterminate === "true"
194
+ });
195
+ return;
196
+ }
197
+ if (e.key === "ArrowDown") {
198
+ // Go to next row
199
+ do {
200
+ newRowIndex = (newRowIndex + 1) % options.length;
201
+ } while (options[newRowIndex].blocked && newRowIndex !== focusedRowIndex);
202
+ preventDefault = true;
203
+ } else if (e.key === "ArrowUp") {
204
+ // Go to previous row
205
+ do {
206
+ newRowIndex = (newRowIndex - 1 + options.length) % options.length;
207
+ } while (options[newRowIndex].blocked && newRowIndex !== focusedRowIndex);
208
+ preventDefault = true;
209
+ } else if (e.key === "ArrowRight") {
210
+ // Go to button if exists in current row and not blocked
211
+ if (options[focusedRowIndex].isWithAction && focusedElementType === "checkbox" && !options[focusedRowIndex].blocked) {
212
+ newElementType = "button";
213
+ preventDefault = true;
214
+ }
215
+ } else if (e.key === "ArrowLeft") {
216
+ // Go to checkbox if currently on button and checkbox not blocked
217
+ if (focusedElementType === "button" && !options[focusedRowIndex].blocked) {
218
+ newElementType = "checkbox";
219
+ preventDefault = true;
220
+ }
221
+ } else if (e.key === "Home") {
222
+ // Go to first non-blocked row
223
+ newRowIndex = 0;
224
+ while (newRowIndex < options.length && options[newRowIndex].blocked) {
225
+ newRowIndex++;
226
+ }
227
+ if (newRowIndex < options.length) {
228
+ newElementType = "checkbox";
229
+ preventDefault = true;
230
+ }
231
+ } else if (e.key === "End") {
232
+ // Go to last non-blocked row
233
+ newRowIndex = options.length - 1;
234
+ while (newRowIndex >= 0 && options[newRowIndex].blocked) {
235
+ newRowIndex--;
236
+ }
237
+ if (newRowIndex >= 0) {
238
+ newElementType = "checkbox";
239
+ preventDefault = true;
240
+ }
241
+ } else if (e.key === "Tab") {
242
+ if (handleTab) {
243
+ handleTab(e, e.shiftKey);
244
+ return;
245
+ }
246
+ }
247
+ if (preventDefault) {
248
+ e.preventDefault();
249
+ setFocusedRowIndex(newRowIndex);
250
+ setFocusedElementType(newElementType);
251
+ updateTabIndex(newRowIndex, newElementType);
252
+ // Find and focus the target element
253
+ const targetElement = elements.find(({
254
+ rowIndex,
255
+ type,
256
+ blocked
257
+ }) => rowIndex === newRowIndex && type === newElementType && !blocked);
258
+ targetElement === null || targetElement === void 0 ? void 0 : targetElement.element.focus();
259
+ }
260
+ }, [getFocusableElements, options, focusedRowIndex, focusedElementType, checkboxId, onChange, handleTab, updateTabIndex]);
261
+ const handleFocus = (0, react_1.useCallback)(e => {
262
+ const elements = getFocusableElements();
263
+ const focusedElement = e.target;
264
+ const targetElementInfo = elements.find(({
265
+ element
266
+ }) => element === focusedElement);
267
+ if (targetElementInfo && !targetElementInfo.blocked && (targetElementInfo.rowIndex !== focusedRowIndex || targetElementInfo.type !== focusedElementType)) {
268
+ setFocusedRowIndex(targetElementInfo.rowIndex);
269
+ setFocusedElementType(targetElementInfo.type);
270
+ updateTabIndex(targetElementInfo.rowIndex, targetElementInfo.type);
271
+ }
272
+ }, [focusedRowIndex, focusedElementType, getFocusableElements, updateTabIndex]);
273
+ // Initialize tabindex when options first become available
274
+ (0, react_1.useEffect)(() => {
275
+ if (options && options.length > 0 && !isInitialized.current) {
276
+ // Find first non-blocked row
277
+ let firstValidRow = 0;
278
+ while (firstValidRow < options.length && options[firstValidRow].blocked) {
279
+ firstValidRow++;
280
+ }
281
+ if (firstValidRow < options.length) {
282
+ setFocusedRowIndex(firstValidRow);
283
+ setFocusedElementType("checkbox");
284
+ updateTabIndex(firstValidRow, "checkbox");
285
+ isInitialized.current = true;
286
+ }
287
+ }
288
+ }, [options, updateTabIndex]);
289
+ // Update tabindex when focused position changes (only after initialization)
290
+ (0, react_1.useEffect)(() => {
291
+ if (isInitialized.current) {
292
+ updateTabIndex(focusedRowIndex, focusedElementType);
293
+ }
294
+ }, [focusedRowIndex, focusedElementType, updateTabIndex]);
124
295
  const getLabelColorInfo = (color, withRightPadding, isHidden, extraArgs) => {
125
296
  if (!color) {
126
297
  return null;
@@ -178,7 +349,8 @@ const CheckboxListWithAction = ({
178
349
  type: "button",
179
350
  onClick: handleClick,
180
351
  title: title,
181
- className: classN
352
+ className: classN,
353
+ tabIndex: -1
182
354
  }, otherArgs, {
183
355
  children: childEl
184
356
  })) : (0, jsx_runtime_1.jsx)("div", {
@@ -208,6 +380,9 @@ const CheckboxListWithAction = ({
208
380
  };
209
381
  return optionsArr ? (0, jsx_runtime_1.jsx)("ul", {
210
382
  className: "zen-checkbox-list-with-action__list",
383
+ ref: listRef,
384
+ onKeyDown: handleKeyDown,
385
+ onFocus: handleFocus,
211
386
  children: optionsArr.map((opt, ind) => {
212
387
  const titleForRender = opt.title || opt.label;
213
388
  const labelForRender = selectSearchTerm(opt.label);
@@ -223,7 +398,9 @@ const CheckboxListWithAction = ({
223
398
  checked: opt.checked,
224
399
  disabled: opt.blocked,
225
400
  title: translate("Toggle {groupName} filter").replace("{groupName}", titleForRender),
401
+ describedBy: opt.isWithAction ? navigationInstructionsId : undefined,
226
402
  "data-indeterminate": opt.partialChecked,
403
+ tabIndex: -1,
227
404
  children: opt.isWithAction ? null : labelElement
228
405
  }), opt.isWithAction && labelElement]
229
406
  }, `li_${ind}_${opt.property}`);
@@ -235,7 +412,12 @@ const CheckboxListWithAction = ({
235
412
  children: [label ? (0, jsx_runtime_1.jsx)("div", {
236
413
  className: "zen-checkbox-list-with-action__title",
237
414
  children: label
238
- }) : null, build(options)]
415
+ }) : null, build(options), (0, jsx_runtime_1.jsx)("div", {
416
+ id: navigationInstructionsId,
417
+ className: "zen-checkbox-list-with-action__sr-only",
418
+ "aria-hidden": "true",
419
+ children: translate("Has additional actions. Use right arrow to access button, left arrow to return.")
420
+ })]
239
421
  });
240
422
  };
241
423
  exports.CheckboxListWithAction = CheckboxListWithAction;
@@ -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;
@@ -1,3 +1,3 @@
1
1
  import { IDropdownPopup as IDropdownPopupRaw } from "../dropdownRaw/dropdownPopup";
2
- export declare const DropdownPopup: ({ alignment, triggerRef, classNamePopup, isMobile, inputValue, dialogAriaLabel, disabled, filterName, handleApplyClick, handleClearClick, handleTriggerClick, mobileSheetStackingClassName, onInputChange, hasApplyButton, inputId, isClearButtonDisabled, isWithFooter, placeholder, searchField, isSearchInPopup, isApplyButtonDisabled, isOpenCombo, inputRef, contentRef, children, onReadyForFocus, handleCheckboxChange, checkboxLabel, isChecked, popupId }: IDropdownPopupRaw) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const DropdownPopup: ({ alignment, triggerRef, classNamePopup, isMobile, inputValue, dialogAriaLabel, disabled, filterName, handleApplyClick, handleClearClick, handleTriggerClick, mobileSheetStackingClassName, onInputChange, hasApplyButton, inputId, isClearButtonDisabled, isWithFooter, placeholder, searchField, isSearchInPopup, isApplyButtonDisabled, isOpenCombo, inputRef, contentRef, children, onReadyForFocus, handleCheckboxChange, checkboxLabel, isChecked, popupId, handleKeydown, handleFocusOnSentinelItem }: IDropdownPopupRaw) => import("react/jsx-runtime").JSX.Element;
3
3
  export type IDropdownPopup = IDropdownPopupRaw;
@@ -1 +1 @@
1
- export declare const DropdownTrigger: ({ name, onBlur, isActive, id, triggerRef, searchField, placeholder, disabled, fullWidth, currentSelection, handleClick, inputValue, className, onSearchChange, width, title, triggerAriaLabel, count, inputRef, buttonType, isError, popupId, ...otherProps }: import("../dropdownRaw/dropdownTrigger").IDropdownTrigger) => import("react/jsx-runtime").JSX.Element;
1
+ export declare const DropdownTrigger: ({ name, onBlur, isActive, id, triggerRef, searchField, placeholder, disabled, fullWidth, currentSelection, handleClick, inputValue, className, onSearchChange, width, title, triggerAriaLabel, count, inputRef, buttonType, isError, popupId, handleFocusOnPopup, ...otherProps }: import("../dropdownRaw/dropdownTrigger").IDropdownTrigger) => import("react/jsx-runtime").JSX.Element;
@@ -32,11 +32,12 @@ export interface IDropdownList extends IZenComponentProps {
32
32
  handleCheckboxChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
33
33
  checkboxLabel?: string;
34
34
  isChecked?: boolean;
35
+ listElementRef?: React.RefObject<HTMLDivElement>;
35
36
  }
36
37
  interface IDropdownEmptyList extends Pick<IDropdownList, "className" | "width" | "onClearClick" | "onApplyClick" | "onCancelClick" | "hasApplyButton" | "isApplyDisabled" | "isClearButtonDisabled" | "isWithFooter"> {
37
38
  hasError: boolean;
38
39
  }
39
40
  export declare const EmptyList: ({ className, width, onClearClick, onApplyClick, onCancelClick, hasApplyButton, isApplyDisabled, isClearButtonDisabled, isWithFooter, hasError }: IDropdownEmptyList) => import("react/jsx-runtime").JSX.Element;
40
- export declare const DropdownList: ({ onBackButtonClick, onSelectAllClick, onClearClick, onApplyClick, onCancelClick, onChange, onSelect, onSingleSelect, listData, isAllSelected, backButtonName, width, minWidth, isSelectAllButtonDisable, hasSelectAllButton, filterName, isMultiselect, hasApplyButton, isApplyDisabled, isClearButtonDisabled, activeValue, forceSelection, isWithFooter, isMobile, handleCheckboxChange, checkboxLabel, isChecked }: IDropdownList) => import("react/jsx-runtime").JSX.Element;
41
+ export declare const DropdownList: ({ onBackButtonClick, onSelectAllClick, onClearClick, onApplyClick, onCancelClick, onChange, onSelect, onSingleSelect, listData, isAllSelected, backButtonName, width, minWidth, isSelectAllButtonDisable, hasSelectAllButton, filterName, isMultiselect, hasApplyButton, isApplyDisabled, isClearButtonDisabled, activeValue, forceSelection, isWithFooter, isMobile, handleCheckboxChange, checkboxLabel, isChecked, listElementRef }: IDropdownList) => import("react/jsx-runtime").JSX.Element;
41
42
  export declare const TRANSLATIONS: string[];
42
43
  export {};
@@ -349,7 +349,8 @@ const DropdownList = ({
349
349
  isMobile,
350
350
  handleCheckboxChange,
351
351
  checkboxLabel,
352
- isChecked
352
+ isChecked,
353
+ listElementRef
353
354
  }) => {
354
355
  const {
355
356
  translate
@@ -360,6 +361,13 @@ const DropdownList = ({
360
361
  const handleSelectAllClick = () => {
361
362
  onSelectAllClick(isAllSelected);
362
363
  };
364
+ const handleBackButtonKeyDown = (0, react_1.useCallback)(event => {
365
+ if (event.key === "ArrowLeft") {
366
+ event.preventDefault();
367
+ onBackButtonClick();
368
+ }
369
+ }, [onBackButtonClick]);
370
+ const componentRef = (0, react_1.useRef)(null);
363
371
  const handleChange = (0, react_1.useCallback)(value => {
364
372
  onChange(value);
365
373
  }, [onChange]);
@@ -380,10 +388,11 @@ const DropdownList = ({
380
388
  forceSelection ? onSingleSelect(false, newActiveEl || activeValue) : onSingleSelect(false, newActiveEl);
381
389
  }, [activeValue, forceSelection, onSingleSelect]);
382
390
  const selectButtonLabel = isAllSelected ? translate("Deselect all") : translate("Select all");
383
- const getActionButton = (label, title, icon, isDisabled, clickHandler, size) => (0, jsx_runtime_1.jsx)("button", {
391
+ const getActionButton = (label, title, icon, isDisabled, clickHandler, size, onKeyDown) => (0, jsx_runtime_1.jsx)("button", {
384
392
  type: "button",
385
393
  disabled: isDisabled,
386
394
  onClick: clickHandler,
395
+ onKeyDown: onKeyDown,
387
396
  className: "zen-dropdown-list__item zen-dropdown-list__item--interactive zen-dropdown-list__action-button zen-dropdown-list__action-button-back",
388
397
  title: title,
389
398
  children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, {
@@ -422,6 +431,7 @@ const DropdownList = ({
422
431
  };
423
432
  return (0, jsx_runtime_1.jsx)("div", {
424
433
  className: "zen-dropdown-list__elements",
434
+ ref: listElementRef,
425
435
  children: isMultiselect ? (0, jsx_runtime_1.jsx)(checkboxListWithAction_1.CheckboxListWithAction, {
426
436
  options: listData,
427
437
  label: "",
@@ -439,10 +449,11 @@ const DropdownList = ({
439
449
  value: createValue(listData, activeValue)
440
450
  })
441
451
  });
442
- }, [isMultiselect, listData, handleChange, handleClick, handleSingleChange, translate, listId, forceSelection, activeValue]);
452
+ }, [listElementRef, isMultiselect, listData, handleChange, handleClick, handleSingleChange, translate, listId, forceSelection, activeValue]);
443
453
  return (0, jsx_runtime_1.jsxs)("div", Object.assign({
444
454
  className: (0, classNames_1.classNames)(["zen-dropdown-list", driveComponentClass || ""])
445
455
  }, styleWidth, {
456
+ ref: componentRef,
446
457
  children: [filterName ? (0, jsx_runtime_1.jsx)("div", {
447
458
  className: "zen-dropdown-list__label",
448
459
  children: filterName
@@ -455,7 +466,7 @@ const DropdownList = ({
455
466
  })
456
467
  }) : null, backButtonName ? (0, jsx_runtime_1.jsx)("div", {
457
468
  className: "zen-dropdown-list__item-wrapper",
458
- children: getActionButton(backButtonName, translate("Back"), iconBackArrow_1.IconBackArrow, false, onBackButtonClick, "large")
469
+ children: getActionButton(backButtonName, translate("Back"), iconBackArrow_1.IconBackArrow, false, onBackButtonClick, "large", handleBackButtonKeyDown)
459
470
  }) : null, hasSelectAllButton ? getActionButton(selectButtonLabel, selectButtonLabel, iconCheckRadio_1.IconCheckRadio, !!isSelectAllButtonDisable, handleSelectAllClick, isDrive ? "huger" : "huge") : null, listDataComponent, isWithFooter ? (0, jsx_runtime_1.jsxs)("div", {
460
471
  className: "zen-dropdown-list__footer",
461
472
  children: [(0, jsx_runtime_1.jsx)(button_1.Button, {
@@ -31,5 +31,7 @@ export interface IDropdownPopup extends IZenComponentProps {
31
31
  checkboxLabel?: string;
32
32
  isChecked?: boolean;
33
33
  isSearchInPopup?: boolean;
34
+ handleKeydown: (event: React.KeyboardEvent<HTMLDivElement>) => void;
35
+ handleFocusOnSentinelItem?: () => void;
34
36
  }
35
- export declare const DropdownPopup: ({ alignment, triggerRef, classNamePopup, isMobile, inputValue, dialogAriaLabel, disabled, filterName, handleApplyClick, handleClearClick, handleTriggerClick, mobileSheetStackingClassName, onInputChange, hasApplyButton, inputId, isClearButtonDisabled, isWithFooter, placeholder, searchField, isSearchInPopup, isApplyButtonDisabled, isOpenCombo, inputRef, contentRef, children, onReadyForFocus, handleCheckboxChange, checkboxLabel, isChecked, popupId }: IDropdownPopup) => import("react/jsx-runtime").JSX.Element;
37
+ export declare const DropdownPopup: ({ alignment, triggerRef, classNamePopup, isMobile, inputValue, dialogAriaLabel, disabled, filterName, handleApplyClick, handleClearClick, handleTriggerClick, mobileSheetStackingClassName, onInputChange, hasApplyButton, inputId, isClearButtonDisabled, isWithFooter, placeholder, searchField, isSearchInPopup, isApplyButtonDisabled, isOpenCombo, inputRef, contentRef, children, onReadyForFocus, handleCheckboxChange, checkboxLabel, isChecked, popupId, handleKeydown, handleFocusOnSentinelItem }: IDropdownPopup) => import("react/jsx-runtime").JSX.Element;
@@ -19,6 +19,7 @@ const useLanguage_1 = require("../utils/localization/useLanguage");
19
19
  const footerButtons_1 = require("../footerButtons/footerButtons");
20
20
  const checkbox_1 = require("../checkbox/checkbox");
21
21
  const useScrollWithAndroidKeyboard_1 = require("../utils/useScrollWithAndroidKeyboard");
22
+ const keyboardHelpers_1 = require("../utils/keyboardHelpers");
22
23
  injectString("cs", "Filter by group", "Filtrovat podle skupiny");
23
24
  injectString("da-DK", "Filter by group", "Filtrer efter gruppe");
24
25
  injectString("de", "Filter by group", "Nach Gruppe filtern");
@@ -127,12 +128,16 @@ const DropdownPopup = ({
127
128
  handleCheckboxChange,
128
129
  checkboxLabel,
129
130
  isChecked,
130
- popupId
131
+ popupId,
132
+ handleKeydown,
133
+ handleFocusOnSentinelItem
131
134
  }) => {
132
135
  const {
133
136
  translate
134
137
  } = (0, useLanguage_1.useLanguage)();
135
138
  const triggerId = (0, react_1.useId)();
139
+ const footerButtonsRef = (0, react_1.useRef)(null);
140
+ const mobileContentRef = (0, react_1.useRef)(null);
136
141
  const {
137
142
  handleFocus,
138
143
  handleBlur,
@@ -141,7 +146,22 @@ const DropdownPopup = ({
141
146
  const memoizedHandleHide = (0, react_1.useCallback)(() => {
142
147
  handleTriggerClick(false);
143
148
  }, [handleTriggerClick]);
144
- const memoizedMobileContent = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, {
149
+ const handleMobileFocusOnSentinelItem = (0, react_1.useCallback)(() => {
150
+ if (!isMobile) {
151
+ return;
152
+ }
153
+ let nextFocusableElement = footerButtonsRef.current ? (0, keyboardHelpers_1.getFirstFocusableItem)(footerButtonsRef.current) : null;
154
+ if (nextFocusableElement) {
155
+ nextFocusableElement.focus();
156
+ return;
157
+ }
158
+ nextFocusableElement = (0, keyboardHelpers_1.getFirstFocusableItem)(mobileContentRef.current);
159
+ nextFocusableElement === null || nextFocusableElement === void 0 ? void 0 : nextFocusableElement.focus();
160
+ return;
161
+ }, [isMobile, footerButtonsRef, mobileContentRef]);
162
+ const memoizedMobileContent = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsxs)("div", {
163
+ onKeyDown: handleKeydown,
164
+ ref: mobileContentRef,
145
165
  children: [searchField ? (0, jsx_runtime_1.jsx)("div", {
146
166
  className: "zen-dropdown-mobile-sheet__search-container",
147
167
  children: (0, jsx_runtime_1.jsx)(searchInput_1.SearchInput, {
@@ -165,13 +185,18 @@ const DropdownPopup = ({
165
185
  }) : null, (0, jsx_runtime_1.jsx)("div", {
166
186
  ref: contentRef,
167
187
  children: children
188
+ }), (0, jsx_runtime_1.jsx)("div", {
189
+ tabIndex: 0,
190
+ onFocus: handleMobileFocusOnSentinelItem,
191
+ className: "zen-dropdown-list__sentinel-item"
168
192
  })]
169
- }), [searchField, onInputChange, handleBlur, handleFocus, inputValue, inputRef, inputId, triggerId, disabled, placeholder, translate, handleCheckboxChange, isChecked, checkboxLabel, contentRef, children]);
193
+ }), [handleKeydown, searchField, onInputChange, handleBlur, handleFocus, inputValue, inputRef, inputId, triggerId, disabled, placeholder, translate, handleCheckboxChange, isChecked, checkboxLabel, contentRef, children, handleMobileFocusOnSentinelItem]);
170
194
  const memoizedMobileFooter = (0, react_1.useMemo)(() => {
171
195
  if (!isWithFooter) {
172
196
  return null;
173
197
  }
174
198
  return (0, jsx_runtime_1.jsxs)(footerButtons_1.FooterButtons, {
199
+ ref: footerButtonsRef,
175
200
  children: [hasApplyButton ? (0, jsx_runtime_1.jsx)(button_1.Button, {
176
201
  onClick: handleApplyClick,
177
202
  type: buttonType_1.ButtonType.Primary,
@@ -224,6 +249,7 @@ const DropdownPopup = ({
224
249
  recalculateOnScroll: true,
225
250
  children: (0, jsx_runtime_1.jsxs)("div", {
226
251
  ref: contentRef,
252
+ onKeyDown: handleKeydown,
227
253
  children: [searchField && isSearchInPopup ? (0, jsx_runtime_1.jsx)("div", {
228
254
  className: "zen-dropdown-popup__search-container",
229
255
  children: (0, jsx_runtime_1.jsx)(searchInput_1.SearchInput, {
@@ -235,9 +261,13 @@ const DropdownPopup = ({
235
261
  disabled: disabled,
236
262
  placeholder: placeholder || translate("Filter by group")
237
263
  })
238
- }) : null, children]
264
+ }) : null, children, (0, jsx_runtime_1.jsx)("div", {
265
+ tabIndex: 0,
266
+ onFocus: handleFocusOnSentinelItem,
267
+ className: "zen-dropdown-list__sentinel-item"
268
+ })]
239
269
  })
240
- }), [alignment, children, classNamePopup, contentRef, dialogAriaLabel, disabled, handleTriggerClick, inputId, inputRef, inputValue, isOpenCombo, isSearchInPopup, onInputChange, placeholder, popupId, searchField, translate, triggerId, triggerRef]);
270
+ }), [alignment, children, classNamePopup, contentRef, dialogAriaLabel, disabled, handleFocusOnSentinelItem, handleKeydown, handleTriggerClick, inputId, inputRef, inputValue, isOpenCombo, isSearchInPopup, onInputChange, placeholder, popupId, searchField, translate, triggerId, triggerRef]);
241
271
  return isMobile ? memoizedMobileView : memoizedDesktopView;
242
272
  };
243
273
  exports.DropdownPopup = DropdownPopup;