@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.
- package/README.md +15 -0
- package/dist/absolute/absolute.d.ts +3 -1
- package/dist/absolute/absolute.js +4 -4
- package/dist/checkbox/checkbox.d.ts +3 -1
- package/dist/checkbox/checkbox.js +5 -8
- package/dist/checkboxListWithAction/checkboxListWithAction.d.ts +3 -1
- package/dist/checkboxListWithAction/checkboxListWithAction.js +185 -3
- package/dist/controlledPopup/controlledPopup.d.ts +3 -1
- package/dist/controlledPopup/controlledPopup.js +2 -2
- package/dist/dropdown/dropdownPopup.d.ts +1 -1
- package/dist/dropdown/dropdownTrigger.d.ts +1 -1
- package/dist/dropdownRaw/dropdownList.d.ts +2 -1
- package/dist/dropdownRaw/dropdownList.js +15 -4
- package/dist/dropdownRaw/dropdownPopup.d.ts +3 -1
- package/dist/dropdownRaw/dropdownPopup.js +35 -5
- package/dist/dropdownRaw/dropdownRaw.js +82 -7
- package/dist/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
- package/dist/dropdownRaw/dropdownSearchableTrigger.js +7 -2
- package/dist/dropdownRaw/dropdownTrigger.d.ts +2 -1
- package/dist/dropdownRaw/dropdownTrigger.js +3 -5
- package/dist/footerButtons/footerButtons.d.ts +6 -4
- package/dist/footerButtons/footerButtons.js +3 -8
- package/dist/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +8 -2
- package/dist/groupsFilterRaw/groupsFilterInitialState.js +16 -0
- package/dist/groupsFilterRaw/groupsFilterRaw.js +43 -9
- package/dist/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
- package/dist/groupsFilterRaw/groupsFilterTrigger.js +13 -2
- package/dist/index.css +222 -18
- package/dist/index.d.ts +1 -1
- package/dist/list/hooks/useDragAndDrop.d.ts +3 -1
- package/dist/list/hooks/useDragAndDrop.js +11 -4
- package/dist/menu/components/menuItem.js +12 -2
- package/dist/menu/contexts/pathContext.d.ts +3 -1
- package/dist/menu/contexts/pathProvider.d.ts +1 -1
- package/dist/menu/contexts/pathProvider.js +1 -1
- package/dist/menu/controlledMenu.js +97 -29
- package/dist/nav/nav.d.ts +2 -1
- package/dist/nav/nav.js +3 -2
- package/dist/nav/navEditList/navEditList.js +2 -1
- package/dist/nav/navItem/navItem.d.ts +1 -0
- package/dist/nav/navItem/navItem.js +4 -1
- package/dist/pillExpandable/pillContent.d.ts +2 -1
- package/dist/pillExpandable/pillContent.js +8 -3
- package/dist/pillExpandable/pillExpandable.d.ts +27 -4
- package/dist/pillExpandable/pillExpandable.js +426 -196
- package/dist/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
- package/dist/pillExpandable/pillExpandablePopoverContent.js +7 -0
- package/dist/pillExpandable/pillExpandableSimple.d.ts +5 -3
- package/dist/pillExpandable/pillExpandableSimple.js +12 -5
- package/dist/summary/summary.js +29 -1
- package/dist/summaryTile/summaryTile.d.ts +2 -1
- package/dist/summaryTile/summaryTile.js +175 -65
- package/dist/summaryTile/summaryTileTrigger.d.ts +1 -1
- package/dist/summaryTile/summaryTileTrigger.js +1 -1
- package/dist/toggleButtonRaw/toggleButtonRaw.js +2 -1
- package/dist/utils/localization/getSupportedLanguage.d.ts +2 -2
- package/dist/utils/localization/getSupportedLanguage.js +28 -8
- package/dist/utils/localization/languageContext.d.ts +1 -1
- package/dist/utils/localization/translations/cs.json +2 -1
- package/dist/utils/localization/translations/de.json +2 -1
- package/dist/utils/localization/translations/en.json +2 -1
- package/dist/utils/localization/translations/es.json +2 -1
- package/dist/utils/localization/translations/fr-FR.json +2 -1
- package/dist/utils/localization/translations/fr.json +2 -1
- package/dist/utils/localization/translations/id.json +2 -1
- package/dist/utils/localization/translations/it.json +2 -1
- package/dist/utils/localization/translations/ja.json +2 -1
- package/dist/utils/localization/translations/ms.json +2 -1
- package/dist/utils/localization/translations/nl.json +2 -1
- package/dist/utils/localization/translations/pl.json +2 -1
- package/dist/utils/localization/translations/pt-BR.json +2 -1
- package/dist/utils/localization/translations/sv.json +2 -1
- package/dist/utils/localization/translations/th.json +2 -1
- package/dist/utils/localization/translations/tr.json +2 -1
- package/dist/utils/localization/translations/zh-Hans.json +2 -1
- package/esm/absolute/absolute.d.ts +3 -1
- package/esm/absolute/absolute.js +4 -4
- package/esm/checkbox/checkbox.d.ts +3 -1
- package/esm/checkbox/checkbox.js +5 -8
- package/esm/checkboxListWithAction/checkboxListWithAction.d.ts +3 -1
- package/esm/checkboxListWithAction/checkboxListWithAction.js +186 -4
- package/esm/controlledPopup/controlledPopup.d.ts +3 -1
- package/esm/controlledPopup/controlledPopup.js +2 -2
- package/esm/dropdown/dropdownPopup.d.ts +1 -1
- package/esm/dropdown/dropdownTrigger.d.ts +1 -1
- package/esm/dropdownRaw/dropdownList.d.ts +2 -1
- package/esm/dropdownRaw/dropdownList.js +16 -5
- package/esm/dropdownRaw/dropdownPopup.d.ts +3 -1
- package/esm/dropdownRaw/dropdownPopup.js +37 -7
- package/esm/dropdownRaw/dropdownRaw.js +82 -7
- package/esm/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
- package/esm/dropdownRaw/dropdownSearchableTrigger.js +7 -2
- package/esm/dropdownRaw/dropdownTrigger.d.ts +2 -1
- package/esm/dropdownRaw/dropdownTrigger.js +3 -5
- package/esm/footerButtons/footerButtons.d.ts +6 -4
- package/esm/footerButtons/footerButtons.js +3 -8
- package/esm/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +9 -3
- package/esm/groupsFilterRaw/groupsFilterInitialState.js +16 -0
- package/esm/groupsFilterRaw/groupsFilterRaw.js +43 -9
- package/esm/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
- package/esm/groupsFilterRaw/groupsFilterTrigger.js +13 -2
- package/esm/index.d.ts +1 -1
- package/esm/list/hooks/useDragAndDrop.d.ts +3 -1
- package/esm/list/hooks/useDragAndDrop.js +11 -4
- package/esm/menu/components/menuItem.js +12 -2
- package/esm/menu/contexts/pathContext.d.ts +3 -1
- package/esm/menu/contexts/pathProvider.d.ts +1 -1
- package/esm/menu/contexts/pathProvider.js +1 -1
- package/esm/menu/controlledMenu.js +98 -30
- package/esm/nav/nav.d.ts +2 -1
- package/esm/nav/nav.js +3 -2
- package/esm/nav/navEditList/navEditList.js +2 -1
- package/esm/nav/navItem/navItem.d.ts +1 -0
- package/esm/nav/navItem/navItem.js +5 -2
- package/esm/pillExpandable/pillContent.d.ts +2 -1
- package/esm/pillExpandable/pillContent.js +8 -3
- package/esm/pillExpandable/pillExpandable.d.ts +27 -4
- package/esm/pillExpandable/pillExpandable.js +427 -197
- package/esm/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
- package/esm/pillExpandable/pillExpandablePopoverContent.js +3 -0
- package/esm/pillExpandable/pillExpandableSimple.d.ts +5 -3
- package/esm/pillExpandable/pillExpandableSimple.js +12 -5
- package/esm/summary/summary.js +29 -1
- package/esm/summaryTile/summaryTile.d.ts +2 -1
- package/esm/summaryTile/summaryTile.js +140 -43
- package/esm/summaryTile/summaryTileTrigger.d.ts +1 -1
- package/esm/summaryTile/summaryTileTrigger.js +1 -1
- package/esm/toggleButtonRaw/toggleButtonRaw.js +2 -1
- package/esm/utils/localization/getSupportedLanguage.d.ts +2 -2
- package/esm/utils/localization/getSupportedLanguage.js +28 -8
- package/esm/utils/localization/languageContext.d.ts +1 -1
- package/esm/utils/localization/translations/cs.json +2 -1
- package/esm/utils/localization/translations/de.json +2 -1
- package/esm/utils/localization/translations/en.json +2 -1
- package/esm/utils/localization/translations/es.json +2 -1
- package/esm/utils/localization/translations/fr-FR.json +2 -1
- package/esm/utils/localization/translations/fr.json +2 -1
- package/esm/utils/localization/translations/id.json +2 -1
- package/esm/utils/localization/translations/it.json +2 -1
- package/esm/utils/localization/translations/ja.json +2 -1
- package/esm/utils/localization/translations/ms.json +2 -1
- package/esm/utils/localization/translations/nl.json +2 -1
- package/esm/utils/localization/translations/pl.json +2 -1
- package/esm/utils/localization/translations/pt-BR.json +2 -1
- package/esm/utils/localization/translations/sv.json +2 -1
- package/esm/utils/localization/translations/th.json +2 -1
- package/esm/utils/localization/translations/tr.json +2 -1
- package/esm/utils/localization/translations/zh-Hans.json +2 -1
- 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
|
|
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;
|