@geotab/zenith 3.15.0 → 3.16.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/absolute/absolute.js +1 -1
- package/dist/betaPill/betaPill.js +9 -9
- package/dist/commonHelpers/arrowNavigation/arrowNavigationHelper.d.ts +1 -0
- package/dist/commonHelpers/arrowNavigation/arrowNavigationHelper.js +5 -1
- package/dist/commonHelpers/hooks/useTrapFocus.d.ts +9 -0
- package/dist/commonHelpers/hooks/useTrapFocus.js +66 -14
- package/dist/controlledPopup/controlledPopup.d.ts +1 -1
- package/dist/controlledPopup/controlledPopup.js +1 -1
- package/dist/dropdownRaw/dropdownSearchableTrigger.js +1 -1
- package/dist/filtersBar/components/filtersBarRange/filtersBarRange.d.ts +1 -1
- package/dist/filtersBar/filtersBarSidePanel/components/filtersBarSidePanelRange/filtersBarSidePanelRange.d.ts +1 -1
- package/dist/filtersBar/filtersBarSidePanel/components/filtersBarSidePanelRange/filtersBarSidePanelRange.js +8 -5
- package/dist/filtersBar/filtersContainer/filtersContainer.js +7 -4
- package/dist/header/header.js +9 -2
- package/dist/header/headerHelpers.js +8 -5
- package/dist/index.css +142 -11
- package/dist/index.d.ts +6 -1
- package/dist/index.js +12 -3
- package/dist/modal/modal.d.ts +48 -0
- package/dist/modal/modal.js +37 -7
- package/dist/nav/navHeader/navHeader.d.ts +1 -1
- package/dist/nav/navHeader/navHeaderSearch/navHeaderSearch.js +1 -1
- package/dist/nav/navItem/navItem.d.ts +15 -2
- package/dist/nav/navItem/navItem.js +49 -7
- package/dist/nav/utils/navUtils.d.ts +2 -2
- package/dist/pillExpandable/pillExpandable.js +6 -3
- package/dist/rangeRaw/components/rangeField.d.ts +2 -1
- package/dist/rangeRaw/components/rangeField.js +4 -3
- package/dist/rangeRaw/rangeRaw.js +8 -5
- package/dist/rangeRaw/types.d.ts +1 -0
- package/dist/sidePanel/sidePanel.js +3 -2
- package/dist/table/selectable/interfaces.d.ts +13 -0
- package/dist/table/selectable/useSelectableRows.js +46 -12
- package/dist/table/selectable/utils/calculateSelectionState.js +35 -0
- package/dist/table/selectable/utils/isRowChecked.js +12 -1
- package/dist/table/table.d.ts +2 -0
- package/dist/table/table.js +3 -1
- package/dist/tabs/tabs.js +14 -5
- package/dist/textInputRaw/textInputRaw.js +1 -1
- package/dist/textInputRaw/types.d.ts +1 -0
- package/dist/tooltip/components/inlineTrigger.d.ts +43 -0
- package/dist/tooltip/components/inlineTrigger.js +42 -0
- package/dist/tooltip/tooltip.d.ts +5 -2
- package/dist/tooltip/tooltip.js +15 -4
- package/dist/trendIndicator/trendIndicator.d.ts +47 -0
- package/dist/trendIndicator/trendIndicator.js +47 -0
- package/dist/trendIndicator/trendIndicatorUtils.d.ts +9 -0
- package/dist/trendIndicator/trendIndicatorUtils.js +18 -0
- package/dist/utils/experimentalFeatures/experimentalContext.d.ts +17 -0
- package/dist/utils/experimentalFeatures/experimentalContext.js +29 -0
- package/dist/utils/experimentalFeatures/index.d.ts +4 -0
- package/dist/utils/experimentalFeatures/index.js +9 -0
- package/dist/utils/experimentalFeatures/registry.d.ts +13 -0
- package/dist/utils/experimentalFeatures/registry.js +11 -0
- package/dist/utils/experimentalFeatures/useExperimentalFeature.d.ts +3 -0
- package/dist/utils/experimentalFeatures/useExperimentalFeature.js +25 -0
- package/dist/utils/localization/translations/ar.json +1 -1
- package/dist/utils/localization/translations/bg-BG.json +1 -1
- package/dist/utils/localization/translations/cs.json +1 -1
- package/dist/utils/localization/translations/da-DK.json +1 -1
- package/dist/utils/localization/translations/de.json +1 -1
- package/dist/utils/localization/translations/el-GR.json +1 -1
- package/dist/utils/localization/translations/en.json +1 -1
- package/dist/utils/localization/translations/es.json +1 -1
- package/dist/utils/localization/translations/et-EE.json +1 -1
- package/dist/utils/localization/translations/fi-FI.json +1 -1
- package/dist/utils/localization/translations/fr-FR.json +1 -1
- package/dist/utils/localization/translations/fr.json +1 -1
- package/dist/utils/localization/translations/hu-HU.json +1 -1
- package/dist/utils/localization/translations/id.json +1 -1
- package/dist/utils/localization/translations/it.json +1 -1
- package/dist/utils/localization/translations/ja.json +1 -1
- package/dist/utils/localization/translations/ka-GE.json +1 -1
- package/dist/utils/localization/translations/ko-KR.json +1 -1
- package/dist/utils/localization/translations/lt-LT.json +1 -1
- package/dist/utils/localization/translations/lv-LV.json +1 -1
- package/dist/utils/localization/translations/ms.json +1 -1
- package/dist/utils/localization/translations/nb-NO.json +1 -1
- package/dist/utils/localization/translations/nl.json +1 -1
- package/dist/utils/localization/translations/pl.json +1 -1
- package/dist/utils/localization/translations/pt-BR.json +1 -1
- package/dist/utils/localization/translations/pt-PT.json +1 -1
- package/dist/utils/localization/translations/ro-RO.json +1 -1
- package/dist/utils/localization/translations/sk-SK.json +1 -1
- package/dist/utils/localization/translations/sv.json +1 -1
- package/dist/utils/localization/translations/th.json +1 -1
- package/dist/utils/localization/translations/tr.json +1 -1
- package/dist/utils/localization/translations/zh-Hans.json +1 -1
- package/dist/utils/localization/translations/zh-TW.json +1 -1
- package/esm/absolute/absolute.js +1 -1
- package/esm/betaPill/betaPill.js +9 -9
- package/esm/commonHelpers/arrowNavigation/arrowNavigationHelper.d.ts +1 -0
- package/esm/commonHelpers/arrowNavigation/arrowNavigationHelper.js +3 -0
- package/esm/commonHelpers/hooks/useTrapFocus.d.ts +9 -0
- package/esm/commonHelpers/hooks/useTrapFocus.js +67 -15
- package/esm/controlledPopup/controlledPopup.d.ts +1 -1
- package/esm/controlledPopup/controlledPopup.js +1 -1
- package/esm/dropdownRaw/dropdownSearchableTrigger.js +1 -1
- package/esm/filtersBar/components/filtersBarRange/filtersBarRange.d.ts +1 -1
- package/esm/filtersBar/filtersBarSidePanel/components/filtersBarSidePanelRange/filtersBarSidePanelRange.d.ts +1 -1
- package/esm/filtersBar/filtersBarSidePanel/components/filtersBarSidePanelRange/filtersBarSidePanelRange.js +8 -5
- package/esm/filtersBar/filtersContainer/filtersContainer.js +7 -4
- package/esm/header/header.js +9 -2
- package/esm/header/headerHelpers.js +8 -5
- package/esm/index.d.ts +6 -1
- package/esm/index.js +5 -1
- package/esm/modal/modal.d.ts +48 -0
- package/esm/modal/modal.js +37 -7
- package/esm/nav/navHeader/navHeader.d.ts +1 -1
- package/esm/nav/navHeader/navHeaderSearch/navHeaderSearch.js +1 -1
- package/esm/nav/navItem/navItem.d.ts +15 -2
- package/esm/nav/navItem/navItem.js +49 -7
- package/esm/nav/utils/navUtils.d.ts +2 -2
- package/esm/pillExpandable/pillExpandable.js +6 -3
- package/esm/rangeRaw/components/rangeField.d.ts +2 -1
- package/esm/rangeRaw/components/rangeField.js +4 -3
- package/esm/rangeRaw/rangeRaw.js +8 -5
- package/esm/rangeRaw/types.d.ts +1 -0
- package/esm/sidePanel/sidePanel.js +3 -2
- package/esm/table/selectable/interfaces.d.ts +13 -0
- package/esm/table/selectable/useSelectableRows.js +46 -12
- package/esm/table/selectable/utils/calculateSelectionState.js +35 -0
- package/esm/table/selectable/utils/isRowChecked.js +12 -1
- package/esm/table/table.d.ts +2 -0
- package/esm/table/table.js +2 -0
- package/esm/tabs/tabs.js +14 -5
- package/esm/testHelpers/renderWithFeatures.d.ts +4 -0
- package/esm/testHelpers/renderWithFeatures.js +6 -0
- package/esm/textInputRaw/textInputRaw.js +1 -1
- package/esm/textInputRaw/types.d.ts +1 -0
- package/esm/tooltip/components/inlineTrigger.d.ts +43 -0
- package/esm/tooltip/components/inlineTrigger.js +38 -0
- package/esm/tooltip/tooltip.d.ts +5 -2
- package/esm/tooltip/tooltip.js +15 -4
- package/esm/trendIndicator/trendIndicator.d.ts +47 -0
- package/esm/trendIndicator/trendIndicator.js +43 -0
- package/esm/trendIndicator/trendIndicatorUtils.d.ts +9 -0
- package/esm/trendIndicator/trendIndicatorUtils.js +14 -0
- package/esm/utils/experimentalFeatures/experimentalContext.d.ts +17 -0
- package/esm/utils/experimentalFeatures/experimentalContext.js +25 -0
- package/esm/utils/experimentalFeatures/index.d.ts +4 -0
- package/esm/utils/experimentalFeatures/index.js +3 -0
- package/esm/utils/experimentalFeatures/registry.d.ts +13 -0
- package/esm/utils/experimentalFeatures/registry.js +8 -0
- package/esm/utils/experimentalFeatures/useExperimentalFeature.d.ts +3 -0
- package/esm/utils/experimentalFeatures/useExperimentalFeature.js +21 -0
- package/esm/utils/localization/translations/ar.json +1 -1
- package/esm/utils/localization/translations/bg-BG.json +1 -1
- package/esm/utils/localization/translations/cs.json +1 -1
- package/esm/utils/localization/translations/da-DK.json +1 -1
- package/esm/utils/localization/translations/de.json +1 -1
- package/esm/utils/localization/translations/el-GR.json +1 -1
- package/esm/utils/localization/translations/en.json +1 -1
- package/esm/utils/localization/translations/es.json +1 -1
- package/esm/utils/localization/translations/et-EE.json +1 -1
- package/esm/utils/localization/translations/fi-FI.json +1 -1
- package/esm/utils/localization/translations/fr-FR.json +1 -1
- package/esm/utils/localization/translations/fr.json +1 -1
- package/esm/utils/localization/translations/hu-HU.json +1 -1
- package/esm/utils/localization/translations/id.json +1 -1
- package/esm/utils/localization/translations/it.json +1 -1
- package/esm/utils/localization/translations/ja.json +1 -1
- package/esm/utils/localization/translations/ka-GE.json +1 -1
- package/esm/utils/localization/translations/ko-KR.json +1 -1
- package/esm/utils/localization/translations/lt-LT.json +1 -1
- package/esm/utils/localization/translations/lv-LV.json +1 -1
- package/esm/utils/localization/translations/ms.json +1 -1
- package/esm/utils/localization/translations/nb-NO.json +1 -1
- package/esm/utils/localization/translations/nl.json +1 -1
- package/esm/utils/localization/translations/pl.json +1 -1
- package/esm/utils/localization/translations/pt-BR.json +1 -1
- package/esm/utils/localization/translations/pt-PT.json +1 -1
- package/esm/utils/localization/translations/ro-RO.json +1 -1
- package/esm/utils/localization/translations/sk-SK.json +1 -1
- package/esm/utils/localization/translations/sv.json +1 -1
- package/esm/utils/localization/translations/th.json +1 -1
- package/esm/utils/localization/translations/tr.json +1 -1
- package/esm/utils/localization/translations/zh-Hans.json +1 -1
- package/esm/utils/localization/translations/zh-TW.json +1 -1
- package/package.json +36 -16
- package/dist/banner/utils/isBannerTarget.d.ts +0 -1
- package/dist/banner/utils/isBannerTarget.js +0 -11
- package/esm/banner/utils/isBannerTarget.d.ts +0 -1
- package/esm/banner/utils/isBannerTarget.js +0 -7
|
@@ -111,7 +111,7 @@ const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, trigger
|
|
|
111
111
|
returnFocusToTrigger();
|
|
112
112
|
}
|
|
113
113
|
}, [isOpen, returnFocusToTrigger]);
|
|
114
|
-
const condition = (0, react_1.useCallback)(() =>
|
|
114
|
+
const condition = (0, react_1.useCallback)((subscriptionTrigger) => useTrapFocusWithTrigger !== "off" && !!subscriptionTrigger, [useTrapFocusWithTrigger]);
|
|
115
115
|
(0, useTrapFocus_1.useTrapFocus)(popupRef, useTrapFocusWithTrigger === "withTrigger" ? triggerRef : undefined, isOpen, condition);
|
|
116
116
|
(0, useEscape_1.useEscape)(popupRef, handleEscape, isOpen);
|
|
117
117
|
(0, useArrowKey_1.useArrowKey)(popupRef, handleEscape, isOpen);
|
|
@@ -162,15 +162,15 @@ const BetaPill = props => {
|
|
|
162
162
|
const isMobile = (0, useMobile_1.useMobile)();
|
|
163
163
|
const pillClasses = (0, react_1.useMemo)(() => (0, classNames_1.classNames)(["zen-caption", "zen-beta-pill", isMobile ? "zen-beta-pill--mobile" : "", className !== null && className !== void 0 ? className : ""]), [isMobile, className]);
|
|
164
164
|
const contextActions = (0, betaPillContext_1.useBetaPillActions)();
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
resolvedMainAction = Object.assign(Object.assign({},
|
|
169
|
-
text:
|
|
170
|
-
});
|
|
171
|
-
resolvedSecondaryAction = Object.assign(Object.assign({},
|
|
172
|
-
text:
|
|
173
|
-
});
|
|
165
|
+
const rawMainAction = feedbackAction || (contextActions === null || contextActions === void 0 ? void 0 : contextActions.feedbackAction);
|
|
166
|
+
const rawSecondaryAction = betaOptionAction || (contextActions === null || contextActions === void 0 ? void 0 : contextActions.betaOptionAction);
|
|
167
|
+
if (rawMainAction || rawSecondaryAction) {
|
|
168
|
+
const resolvedMainAction = rawMainAction ? Object.assign(Object.assign({}, rawMainAction), {
|
|
169
|
+
text: rawMainAction.text || translate("Send feedback")
|
|
170
|
+
}) : undefined;
|
|
171
|
+
const resolvedSecondaryAction = rawSecondaryAction ? Object.assign(Object.assign({}, rawSecondaryAction), {
|
|
172
|
+
text: rawSecondaryAction.text || translate("Manage beta option")
|
|
173
|
+
}) : undefined;
|
|
174
174
|
return (0, jsx_runtime_1.jsx)(pillExpandable_1.PillExpandable, {
|
|
175
175
|
isBeta: true,
|
|
176
176
|
icon: iconLab_1.IconLab,
|
|
@@ -5,6 +5,7 @@ interface IScrollOptions {
|
|
|
5
5
|
top: number;
|
|
6
6
|
left: number;
|
|
7
7
|
}
|
|
8
|
+
export declare const getDirectionalScrollDelta: (delta: number, isRTL: boolean) => number;
|
|
8
9
|
export declare const getScrollOptions: (action: string, element: HTMLElement | null, isRTL?: boolean) => IScrollOptions;
|
|
9
10
|
export declare const extractButtonAction: (event: React.MouseEvent<HTMLElement>) => TArrowsNavValue | null;
|
|
10
11
|
export declare const scrollElement: (element: HTMLElement, options: IScrollOptions) => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.scrollElement = exports.extractButtonAction = exports.getScrollOptions = exports.clearTimerTimeout = exports.clearTimerInterval = void 0;
|
|
3
|
+
exports.scrollElement = exports.extractButtonAction = exports.getScrollOptions = exports.getDirectionalScrollDelta = exports.clearTimerTimeout = exports.clearTimerInterval = void 0;
|
|
4
4
|
const zen_1 = require("../../utils/zen");
|
|
5
5
|
const clearTimerInterval = (timerId) => {
|
|
6
6
|
var _a;
|
|
@@ -38,6 +38,10 @@ const getLTRScrollLeft = (action, scrollLeft, step, element) => {
|
|
|
38
38
|
}
|
|
39
39
|
return scrollLeft;
|
|
40
40
|
};
|
|
41
|
+
// In RTL the horizontal scroll axis is inverted: scrollLeft is 0 at the right edge and goes negative
|
|
42
|
+
// toward the left edge, so a delta meant to move the viewport toward the arrow must flip sign.
|
|
43
|
+
const getDirectionalScrollDelta = (delta, isRTL) => (isRTL ? -delta : delta);
|
|
44
|
+
exports.getDirectionalScrollDelta = getDirectionalScrollDelta;
|
|
41
45
|
const getScrollOptions = (action, element, isRTL = false) => {
|
|
42
46
|
const step = (element === null || element === void 0 ? void 0 : element.offsetWidth) ? element.offsetWidth : 100;
|
|
43
47
|
const scrollTop = (element === null || element === void 0 ? void 0 : element.scrollTop) || 0;
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { RefObject } from "react";
|
|
2
2
|
type TElementToBool = (element: HTMLElement) => boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Traps keyboard (Tab) focus within `containerRef` (and optionally its `triggerRef`).
|
|
5
|
+
*
|
|
6
|
+
* Nested-popup contract: for correct nested-popup behaviour, a focused element that triggers an
|
|
7
|
+
* open child popup must expose a `data-popup-id` attribute whose value is the `id` of the child
|
|
8
|
+
* popup element rendered in the DOM. When present, focus is deferred to that child popup's trap.
|
|
9
|
+
* This contract is fulfilled automatically by `ControlledPopup`; callers using `useTrapFocus`
|
|
10
|
+
* directly must set `data-popup-id` themselves or nested popups will silently lose focus handling.
|
|
11
|
+
*/
|
|
3
12
|
export declare const useTrapFocus: (containerRef: RefObject<HTMLElement | null>, triggerRef: RefObject<HTMLElement | null> | undefined, subscriptionTrigger: unknown, condition?: (t: unknown) => boolean, isElementVisible?: TElementToBool) => void;
|
|
4
13
|
export {};
|
|
@@ -9,18 +9,38 @@ const isChildOf_1 = require("../../utils/isChildOf");
|
|
|
9
9
|
const isElementHidden_1 = require("../../utils/isElementHidden");
|
|
10
10
|
const zen_1 = require("../../utils/zen");
|
|
11
11
|
const findFirstVisible = (elems, isElementVisible) => elems.find(elem => isElementVisible(elem));
|
|
12
|
+
/**
|
|
13
|
+
* Traps keyboard (Tab) focus within `containerRef` (and optionally its `triggerRef`).
|
|
14
|
+
*
|
|
15
|
+
* Nested-popup contract: for correct nested-popup behaviour, a focused element that triggers an
|
|
16
|
+
* open child popup must expose a `data-popup-id` attribute whose value is the `id` of the child
|
|
17
|
+
* popup element rendered in the DOM. When present, focus is deferred to that child popup's trap.
|
|
18
|
+
* This contract is fulfilled automatically by `ControlledPopup`; callers using `useTrapFocus`
|
|
19
|
+
* directly must set `data-popup-id` themselves or nested popups will silently lose focus handling.
|
|
20
|
+
*/
|
|
12
21
|
const useTrapFocus = (containerRef, triggerRef, subscriptionTrigger, condition, isElementVisible) => {
|
|
13
22
|
/* eslint-disable complexity */
|
|
14
23
|
const handleKeyDown = (0, react_1.useCallback)(e => {
|
|
15
|
-
var _a, _b, _c, _d, _e, _f;
|
|
24
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
16
25
|
/* eslint-enable complexity */
|
|
17
26
|
const getChildCondition = () => {
|
|
18
|
-
var _a, _b;
|
|
27
|
+
var _a, _b, _c;
|
|
28
|
+
const targetEl = e.target;
|
|
29
|
+
// If the target is a trigger for an open child popup, defer to that popup's
|
|
30
|
+
// focus trap. Key on data-popup-id + DOM presence so this works even when
|
|
31
|
+
// preventAttributesAutoSet suppresses aria-expanded.
|
|
32
|
+
const dataPopupId = targetEl.getAttribute("data-popup-id");
|
|
33
|
+
if (dataPopupId &&
|
|
34
|
+
((_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.getElementById(dataPopupId)) &&
|
|
35
|
+
(0, isChildOf_1.isChildOf)(targetEl, containerRef.current) &&
|
|
36
|
+
targetEl !== (triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
19
39
|
return triggerRef
|
|
20
|
-
? !(0, isChildOf_1.isChildOf)(
|
|
21
|
-
|
|
22
|
-
!(0, isChildOf_1.isChildOf)(
|
|
23
|
-
: !(0, isChildOf_1.isChildOf)(
|
|
40
|
+
? !(0, isChildOf_1.isChildOf)(targetEl, containerRef.current) &&
|
|
41
|
+
targetEl !== ((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.body) &&
|
|
42
|
+
!(0, isChildOf_1.isChildOf)(targetEl, triggerRef.current)
|
|
43
|
+
: !(0, isChildOf_1.isChildOf)(targetEl, containerRef.current) && targetEl !== ((_c = zen_1.zen.document) === null || _c === void 0 ? void 0 : _c.body);
|
|
24
44
|
};
|
|
25
45
|
if (!containerRef.current || getChildCondition()) {
|
|
26
46
|
return;
|
|
@@ -30,9 +50,14 @@ const useTrapFocus = (containerRef, triggerRef, subscriptionTrigger, condition,
|
|
|
30
50
|
: !(0, dialogHelpers_1.isElementInsideContainer)(target, containerEl.current) &&
|
|
31
51
|
!(0, dialogHelpers_1.isElementInsideContainer)(target, triggerEl.current);
|
|
32
52
|
const isTargetOutside = e.target ? checkIsElementOutside(e.target, containerRef, triggerRef) : undefined;
|
|
33
|
-
const
|
|
53
|
+
const triggerElement = (_a = triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current) !== null && _a !== void 0 ? _a : null;
|
|
54
|
+
const triggerSelf = (triggerElement === null || triggerElement === void 0 ? void 0 : triggerElement.matches(focusableSelector_1.FOCUSABLE_SELECTOR)) ? [triggerElement] : [];
|
|
55
|
+
const triggerChildren = Array.from((_b = triggerElement === null || triggerElement === void 0 ? void 0 : triggerElement.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR)) !== null && _b !== void 0 ? _b : []);
|
|
56
|
+
// querySelectorAll only returns descendants (never the element itself), so triggerSelf
|
|
57
|
+
// and triggerChildren are disjoint by definition and need no deduplication.
|
|
58
|
+
const triggerSelectors = [...triggerSelf, ...triggerChildren];
|
|
34
59
|
const containerSelectors = containerRef.current.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR);
|
|
35
|
-
const focusable = triggerRef ? [...
|
|
60
|
+
const focusable = triggerRef ? [...triggerSelectors, ...Array.from(containerSelectors)] : [...Array.from(containerSelectors)];
|
|
36
61
|
if (!focusable.length) {
|
|
37
62
|
return;
|
|
38
63
|
}
|
|
@@ -49,32 +74,59 @@ const useTrapFocus = (containerRef, triggerRef, subscriptionTrigger, condition,
|
|
|
49
74
|
return;
|
|
50
75
|
}
|
|
51
76
|
if (e.shiftKey) {
|
|
52
|
-
if (((
|
|
77
|
+
if (((_c = zen_1.zen.document) === null || _c === void 0 ? void 0 : _c.activeElement) === first) {
|
|
53
78
|
e.preventDefault();
|
|
54
79
|
last === null || last === void 0 ? void 0 : last.focus();
|
|
55
80
|
return;
|
|
56
81
|
}
|
|
57
|
-
if (firstContainerFocusable && ((
|
|
82
|
+
if (firstContainerFocusable && ((_d = zen_1.zen.document) === null || _d === void 0 ? void 0 : _d.activeElement) === firstContainerFocusable) {
|
|
58
83
|
e.preventDefault();
|
|
59
84
|
lastTriggerFocusable === null || lastTriggerFocusable === void 0 ? void 0 : lastTriggerFocusable.focus();
|
|
60
85
|
}
|
|
61
86
|
return;
|
|
62
87
|
}
|
|
63
|
-
if (((
|
|
88
|
+
if (((_e = zen_1.zen.document) === null || _e === void 0 ? void 0 : _e.activeElement) === last) {
|
|
64
89
|
e.preventDefault();
|
|
65
90
|
first === null || first === void 0 ? void 0 : first.focus();
|
|
66
91
|
return;
|
|
67
92
|
}
|
|
68
|
-
if (lastTriggerFocusable && ((
|
|
93
|
+
if (lastTriggerFocusable && ((_f = zen_1.zen.document) === null || _f === void 0 ? void 0 : _f.activeElement) === lastTriggerFocusable) {
|
|
69
94
|
e.preventDefault();
|
|
70
95
|
firstContainerFocusable === null || firstContainerFocusable === void 0 ? void 0 : firstContainerFocusable.focus();
|
|
71
96
|
}
|
|
72
|
-
else if (isLastChildOfFirst && first && (0, isChildOf_1.isChildOf)((
|
|
97
|
+
else if (isLastChildOfFirst && first && (0, isChildOf_1.isChildOf)((_g = zen_1.zen.document) === null || _g === void 0 ? void 0 : _g.activeElement, first)) {
|
|
73
98
|
e.preventDefault();
|
|
74
99
|
}
|
|
75
100
|
return;
|
|
76
101
|
}
|
|
77
|
-
},
|
|
102
|
+
},
|
|
103
|
+
// condition is consumed by useKeydown below, not read by handleKeyDown directly; its absence from deps is intentional.
|
|
104
|
+
[containerRef, triggerRef, isElementVisible]);
|
|
78
105
|
(0, useKeydown_1.useKeydown)(handleKeyDown, subscriptionTrigger, condition);
|
|
106
|
+
// When withTrigger mode closes (condition goes false), restore focus to the trigger
|
|
107
|
+
// if focus landed on body (which happens when the popup's focused element is unmounted).
|
|
108
|
+
// This restoration is intentionally scoped to the "focused element unmounted → body" case;
|
|
109
|
+
// the general close case (e.g. click-outside, item selection) is handled separately by the
|
|
110
|
+
// returnFocusToTrigger effect in absolute.tsx. Both are idempotent, so overlap is harmless.
|
|
111
|
+
// Initialized to false because popups mount closed; the guard below reconciles the first
|
|
112
|
+
// active/inactive edge, so a popup that mounts already open still resolves correctly.
|
|
113
|
+
const isActiveRef = (0, react_1.useRef)(false);
|
|
114
|
+
(0, react_1.useEffect)(() => {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
const isActive = condition ? condition(subscriptionTrigger) : !!subscriptionTrigger;
|
|
117
|
+
// Guard: short-circuit when the raw open/close state is unchanged to avoid spurious
|
|
118
|
+
// focus restoration if an unstable condition reference re-fires this effect.
|
|
119
|
+
if (!!subscriptionTrigger === isActiveRef.current) {
|
|
120
|
+
isActiveRef.current = isActive;
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (!isActive && isActiveRef.current && (triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current)) {
|
|
124
|
+
const active = (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.activeElement;
|
|
125
|
+
if (!active || active === ((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.body)) {
|
|
126
|
+
triggerRef.current.focus();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
isActiveRef.current = isActive;
|
|
130
|
+
}, [condition, subscriptionTrigger, triggerRef]);
|
|
79
131
|
};
|
|
80
132
|
exports.useTrapFocus = useTrapFocus;
|
|
@@ -10,7 +10,7 @@ import { IAlignment } from "../utils/positioningUtils/alignments";
|
|
|
10
10
|
export type TAlignment = "top" | "top-left" | "top-right" | "left" | "left-top" | "left-bottom" | "right" | "right-top" | "right-bottom" | "bottom" | "bottom-left" | "bottom-right";
|
|
11
11
|
export interface IControlledPopup extends IZenComponentProps {
|
|
12
12
|
triggerRef: RefObject<HTMLElement | null>;
|
|
13
|
-
/** Alignment of the popup relative to its trigger. Defaults to `"bottom-
|
|
13
|
+
/** Alignment of the popup relative to its trigger. Defaults to `"bottom-start"`. */
|
|
14
14
|
alignment?: TAlignmentAbsolute;
|
|
15
15
|
id?: string;
|
|
16
16
|
className?: string;
|
|
@@ -11,7 +11,7 @@ const ControlledPopup = ({ isOpen, id, paddingX, paddingY, triggerRef, className
|
|
|
11
11
|
const autoId = (0, react_1.useId)();
|
|
12
12
|
const popupId = id || autoId;
|
|
13
13
|
const isClientReady = (0, useClientReady_1.useClientReady)();
|
|
14
|
-
const rtlAlignment = (0, useRTLAlignment_1.useRTLAlignment)(alignment !== null && alignment !== void 0 ? alignment : "bottom-
|
|
14
|
+
const rtlAlignment = (0, useRTLAlignment_1.useRTLAlignment)(alignment !== null && alignment !== void 0 ? alignment : "bottom-start");
|
|
15
15
|
(0, react_1.useEffect)(() => {
|
|
16
16
|
if (!triggerRef.current || !isClientReady) {
|
|
17
17
|
return;
|
|
@@ -183,7 +183,7 @@ const DropdownSearchableTrigger = _a => {
|
|
|
183
183
|
} = _a,
|
|
184
184
|
otherProps = __rest(_a, ["value", "className", "onChange", "placeholder", "isOpenPopup", "inputRef", "handleClick", "width", "title", "id", "disabled", "count", "currentSelection", "isError", "fullWidth", "ref", "name", "onBlur", "popupId", "handleFocusOnPopup", "dataAnalyticsId"])
|
|
185
185
|
// eslint-disable-next-line complexity
|
|
186
|
-
|
|
186
|
+
;
|
|
187
187
|
const {
|
|
188
188
|
isFormSection
|
|
189
189
|
} = (0, react_1.useContext)(formSectionProvider_1.FormSectionContext);
|
|
@@ -3,7 +3,7 @@ import { IRange, IRangeValues } from "../../../range/range";
|
|
|
3
3
|
export interface IFiltersBarRangeState {
|
|
4
4
|
value: IRangeValues;
|
|
5
5
|
}
|
|
6
|
-
interface IFiltersBarRangeProps extends Pick<IRange, "id" | "defaultValue" | "unit" | "labelMin" | "labelMax" | "disabled" | "label" | "triggerAriaLabel" | "min" | "max" | "fullWidthTriggerButton" | "fullBounded" | "className" | "allowEqualMinMax"> {
|
|
6
|
+
interface IFiltersBarRangeProps extends Pick<IRange, "id" | "defaultValue" | "unit" | "labelMin" | "labelMax" | "disabled" | "label" | "triggerAriaLabel" | "min" | "max" | "fullWidthTriggerButton" | "fullBounded" | "className" | "allowEqualMinMax" | "integer"> {
|
|
7
7
|
}
|
|
8
8
|
export interface IFiltersBarRange extends IFiltersBarItem<IFiltersBarRangeState, IFiltersBarRangeProps> {
|
|
9
9
|
className?: string;
|
|
@@ -2,4 +2,4 @@ import "./filtersBarSidePanelRange.less";
|
|
|
2
2
|
import { IRange } from "../../../../range/range";
|
|
3
3
|
export interface IFiltersBarSidePanelRange extends Omit<IRange, "label" | "fullWidthTriggerButton" | "defaultValue"> {
|
|
4
4
|
}
|
|
5
|
-
export declare const FiltersBarSidePanelRange: ({ className, id, onChange, value, unit, min, max, fullBounded, allowEqualMinMax, labelMin, labelMax, disabled }: IFiltersBarSidePanelRange) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare const FiltersBarSidePanelRange: ({ className, id, onChange, value, unit, min, max, fullBounded, allowEqualMinMax, labelMin, labelMax, disabled, integer }: IFiltersBarSidePanelRange) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -94,7 +94,8 @@ const FiltersBarSidePanelRange = ({
|
|
|
94
94
|
allowEqualMinMax,
|
|
95
95
|
labelMin,
|
|
96
96
|
labelMax,
|
|
97
|
-
disabled
|
|
97
|
+
disabled,
|
|
98
|
+
integer
|
|
98
99
|
}) => {
|
|
99
100
|
const generatedId = (0, react_1.useId)();
|
|
100
101
|
const intId = id || generatedId;
|
|
@@ -153,8 +154,9 @@ const FiltersBarSidePanelRange = ({
|
|
|
153
154
|
min: min,
|
|
154
155
|
isMinField: true,
|
|
155
156
|
direction: directionState,
|
|
156
|
-
disabled: disabled
|
|
157
|
-
|
|
157
|
+
disabled: disabled,
|
|
158
|
+
integer: integer
|
|
159
|
+
}), [rangeFieldClasses, labelMin, translate, unit, currentValue.min, errorType, min, max, handleChange, directionState, disabled, integer]);
|
|
158
160
|
const memoizedMaxRangeField = (0, react_1.useMemo)(() => (0, jsx_runtime_1.jsx)(rangeField_1.RangeField, {
|
|
159
161
|
className: (0, classNames_1.classNames)([rangeFieldClasses, "zen-filters-bar-side-panel-range__max-field"]),
|
|
160
162
|
label: labelMax || translate("Max"),
|
|
@@ -168,8 +170,9 @@ const FiltersBarSidePanelRange = ({
|
|
|
168
170
|
min: min,
|
|
169
171
|
isMinField: false,
|
|
170
172
|
direction: directionState,
|
|
171
|
-
disabled: disabled
|
|
172
|
-
|
|
173
|
+
disabled: disabled,
|
|
174
|
+
integer: integer
|
|
175
|
+
}), [rangeFieldClasses, labelMax, translate, unit, currentValue.max, errorType, min, max, handleChange, directionState, disabled, integer]);
|
|
173
176
|
return (0, jsx_runtime_1.jsxs)("div", {
|
|
174
177
|
ref: setFieldsContainerRef,
|
|
175
178
|
id: intId,
|
|
@@ -17,6 +17,7 @@ const useDirectionalIcon_1 = require("../../utils/localization/useDirectionalIco
|
|
|
17
17
|
const useLanguage_1 = require("../../utils/localization/useLanguage");
|
|
18
18
|
const useDriveClassName_1 = require("../../utils/theme/useDriveClassName");
|
|
19
19
|
const useIsRTL_1 = require("../../utils/localization/useIsRTL");
|
|
20
|
+
const arrowNavigationHelper_1 = require("../../commonHelpers/arrowNavigation/arrowNavigationHelper");
|
|
20
21
|
const zen_1 = require("../../utils/zen");
|
|
21
22
|
injectString("cs", "Scroll to start", "P\u0159ej\xEDt na za\u010D\xE1tek");
|
|
22
23
|
injectString("da-DK", "Scroll to start", "Rul til start");
|
|
@@ -92,13 +93,15 @@ const getScrollButtonType = (element, isRTL) => {
|
|
|
92
93
|
return "";
|
|
93
94
|
}
|
|
94
95
|
if (isRTL) {
|
|
96
|
+
// scrollLeft is 0 at the start (right edge) and negative toward the end (left edge),
|
|
97
|
+
// so the button to offer is the mirror of the LTR case below.
|
|
95
98
|
if (scrollLeft < -1 && scrollLeft > clientWidth - scrollWidth + 1) {
|
|
96
99
|
return "both";
|
|
97
100
|
}
|
|
98
101
|
if (scrollLeft >= -1) {
|
|
99
|
-
return "
|
|
102
|
+
return "end";
|
|
100
103
|
}
|
|
101
|
-
return "
|
|
104
|
+
return "start";
|
|
102
105
|
}
|
|
103
106
|
if (scrollLeft > 0 && scrollWidth > clientWidth + scrollLeft + 1) {
|
|
104
107
|
return "both";
|
|
@@ -234,7 +237,7 @@ const FiltersContainer = ({
|
|
|
234
237
|
className: (0, classNames_1.classNames)(["zen-filters-toolbar__scroller", driveClassNameScroller || "", "zen-filters-toolbar__start", showLeft ? `${scrollerClass}--visible` : "", isHiddenDisplay.left ? `${scrollerClass}--hidden` : ""]),
|
|
235
238
|
icon: ScrollStartIcon,
|
|
236
239
|
iconPosition: textIconButton_1.ButtonIconPosition.Start,
|
|
237
|
-
onClick: handleScrollButtonClick(-scrollableStep)
|
|
240
|
+
onClick: handleScrollButtonClick((0, arrowNavigationHelper_1.getDirectionalScrollDelta)(-scrollableStep, isRTL))
|
|
238
241
|
}), (0, jsx_runtime_1.jsx)("div", {
|
|
239
242
|
ref: scrollableRef,
|
|
240
243
|
className: (0, classNames_1.classNames)(["zen-filters-toolbar__scrollable", !isHiddenDisplay.left ? "has-left-scroller" : "", !isHiddenDisplay.right ? "has-right-scroller" : ""]),
|
|
@@ -248,7 +251,7 @@ const FiltersContainer = ({
|
|
|
248
251
|
title: translate("Scroll to end"),
|
|
249
252
|
className: (0, classNames_1.classNames)([scrollerClass, driveClassNameScroller || "", "zen-filters-toolbar__end", showRight ? `${scrollerClass}--visible` : "", isHiddenDisplay.right ? `${scrollerClass}--hidden` : ""]),
|
|
250
253
|
icon: ScrollEndIcon,
|
|
251
|
-
onClick: handleScrollButtonClick(scrollableStep),
|
|
254
|
+
onClick: handleScrollButtonClick((0, arrowNavigationHelper_1.getDirectionalScrollDelta)(scrollableStep, isRTL)),
|
|
252
255
|
iconPosition: textIconButton_1.ButtonIconPosition.End
|
|
253
256
|
})]
|
|
254
257
|
}) : null;
|
package/dist/header/header.js
CHANGED
|
@@ -187,11 +187,13 @@ const Header = ({ children, className, onFiltersBarOpen
|
|
|
187
187
|
const headerRefWidth = ((_a = headerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) || 0;
|
|
188
188
|
const leftElementsRefWidth = ((_b = leftElementsRef.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect().width) || 0;
|
|
189
189
|
const rightelementsRefWidth = ((_c = rightElementsRef.current) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect().width) || 0;
|
|
190
|
-
|
|
190
|
+
// Mobile padding: 8px * 2 = 16px (zen-main-header--mobile .zen-main-header__section--padding)
|
|
191
|
+
// Desktop padding: 20px * 2 = 40px + 8px gaps between sections ≈ 48px
|
|
192
|
+
const paddings = isMobile ? 16 : 48;
|
|
191
193
|
const gaps = 8 + (rightelementsRefWidth ? 8 : 0);
|
|
192
194
|
const calculatedMiddleWidth = headerRefWidth - gaps - paddings - rightelementsRefWidth - leftElementsRefWidth;
|
|
193
195
|
setMiddleWidth(calculatedMiddleWidth);
|
|
194
|
-
}, []);
|
|
196
|
+
}, [isMobile]);
|
|
195
197
|
const resizeCallBack = (0, useThrottle_1.useThrottle)(() => {
|
|
196
198
|
calculateMiddleWidth();
|
|
197
199
|
if (!isMobile) {
|
|
@@ -248,6 +250,11 @@ const Header = ({ children, className, onFiltersBarOpen
|
|
|
248
250
|
const prefixesForTitleSize = ["large", "medium", "small"];
|
|
249
251
|
return prefixesForTitleSize[count - 1];
|
|
250
252
|
}, [collapsedElements.length, mobileFilterCondition, mobileSearchCondition, rightElements.length, visibleElements.length]);
|
|
253
|
+
// On mobile, title shrink when items overflow is handled via CSS (flex-shrink: 1 and
|
|
254
|
+
// min-width: 0 are always set on .zen-header__section--left for mobile in header.less).
|
|
255
|
+
// Applying this via React state caused a measurement feedback loop: adding shrink-title
|
|
256
|
+
// increased middleWidth → items fit → condition became false → title expanded → items
|
|
257
|
+
// overflowed → condition became true again → oscillation.
|
|
251
258
|
const titleShrinkCondition = (visibleElements.length === 0 && rightElements.length) || (mobileSearchCondition && mobileFilterCondition);
|
|
252
259
|
const fullClassName = (0, classNames_1.classNames)([
|
|
253
260
|
"zen-main-header zen-main-header--background-color",
|
|
@@ -87,11 +87,14 @@ const getItemsForRender = (items, isMobile) => {
|
|
|
87
87
|
exports.getItemsForRender = getItemsForRender;
|
|
88
88
|
const getItemsForMeasure = (items, isMobile) => (0, exports.getItemsForRender)(items, isMobile).map((el, ind) => {
|
|
89
89
|
const elProps = el.props;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
// Only HeaderCustomMenuWrapper components receive their original id in the
|
|
91
|
+
// measurement clone. These components use id purely as a registration key inside
|
|
92
|
+
// useCustomMenu and do NOT forward it to a DOM attribute, so no duplicate HTML
|
|
93
|
+
// element id is created in the hidden measurement container (MYG-141810).
|
|
94
|
+
// All other items (HeaderButton, HeaderMenu, …) keep id: undefined, preserving
|
|
95
|
+
// the MYG-133482 protection against duplicate DOM ids.
|
|
96
|
+
const isCustomMenuWrapper = el.type.displayName === exports.HeaderCustomMenuWrapper;
|
|
97
|
+
return (0, react_1.cloneElement)(el, Object.assign(Object.assign({ key: `measure-key-${ind}-${items.length}` }, (isCustomMenuWrapper ? {} : { id: undefined })), { "data-zen-measure-id": elProps.id }));
|
|
95
98
|
});
|
|
96
99
|
exports.getItemsForMeasure = getItemsForMeasure;
|
|
97
100
|
const filterItems = (items, isMobile) => {
|