@geotab/zenith 3.10.0 → 3.11.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/README.md +29 -0
- package/dist/calendar/calendar.js +7 -4
- package/dist/card/components/title.js +4 -1
- package/dist/card/components/titleLink.js +5 -2
- package/dist/chart/barChart/getDefaultOptions.d.ts +2 -1
- package/dist/chart/barChart/getDefaultOptions.js +5 -2
- package/dist/chart/barChart.js +6 -4
- package/dist/chart/lineChart/getDefaultOptions.d.ts +2 -1
- package/dist/chart/lineChart/getDefaultOptions.js +5 -2
- package/dist/chart/lineChart.js +4 -2
- package/dist/checkboxListWithAction/checkboxListWithAction.js +4 -1
- package/dist/commonHelpers/arrowNavigation/components/arrowButton/arrowButton.js +4 -1
- package/dist/commonStyles/pillStyles/pillContent.less +13 -14
- package/dist/commonStyles/pillStyles/pillStyles.less +4 -5
- package/dist/commonStyles/pillStyles/pillTextContent.less +2 -2
- package/dist/commonStyles/typography/typography.less +579 -19
- package/dist/controlledPopup/controlledPopup.d.ts +1 -0
- package/dist/controlledPopup/controlledPopup.js +3 -1
- package/dist/dataGrid/cell/cell.d.ts +2 -1
- package/dist/dataGrid/cell/cell.js +2 -2
- package/dist/dataGrid/dataGrid.js +7 -4
- package/dist/dataGrid/listColumn.d.ts +2 -0
- package/dist/dataGrid/row/row.d.ts +2 -1
- package/dist/dataGrid/row/row.js +13 -9
- package/dist/dataGrid/withFlexibleColumns/components/columnSettingsList.js +2 -1
- package/dist/dataGrid/withSelectableRows/components/bulkActions/bulkActions.d.ts +4 -0
- package/dist/dateRangeInner/dateRangeInner.js +5 -2
- package/dist/dateRangeRaw/dateRangeRaw.js +5 -2
- package/dist/dateRangeRaw/utils/parseLabel.js +1 -1
- package/dist/dropdownRaw/dropdownRaw.js +12 -6
- package/dist/fileUpload/components/dropZoneContent.js +100 -100
- package/dist/fileUpload/fileUpload.js +100 -100
- package/dist/filters/components/filtersSearchList.js +4 -1
- package/dist/filtersBar/filtersContainer/filtersContainer.js +62 -61
- package/dist/formStepperButtons/formStepperButtons.js +4 -1
- package/dist/groupsFilterRaw/groupsFilterAdjustmentState.js +4 -1
- package/dist/groupsFilterRaw/groupsFilterInitialState.js +4 -1
- package/dist/header/headerBack.js +4 -1
- package/dist/icons/iconAlignLeft.js +1 -3
- package/dist/icons/iconAlignmentLeft.js +1 -3
- package/dist/icons/iconAlignmentRight.js +1 -3
- package/dist/icons/iconArrowBottomLeft.js +1 -3
- package/dist/icons/iconArrowBottomRight.js +1 -3
- package/dist/icons/iconArrowLeftPath.js +1 -3
- package/dist/icons/iconArrowRight.js +1 -3
- package/dist/icons/iconArrowRightCircle.js +1 -3
- package/dist/icons/iconArrowRightPath.js +1 -3
- package/dist/icons/iconArrowTopLeft.js +1 -3
- package/dist/icons/iconArrowTopRight.js +1 -3
- package/dist/icons/iconChevronDoubleRight.js +1 -3
- package/dist/icons/iconChevronRight.js +1 -3
- package/dist/icons/iconChevronRightSmall.js +1 -3
- package/dist/icons/iconCornerDownLeft.js +1 -3
- package/dist/icons/iconCornerDownRight.js +1 -3
- package/dist/icons/iconCornerLeftDown.js +1 -3
- package/dist/icons/iconCornerLeftUp.js +1 -3
- package/dist/icons/iconCornerRightDown.js +1 -3
- package/dist/icons/iconCornerRightUp.js +1 -3
- package/dist/icons/iconCornerUpLeft.js +1 -3
- package/dist/icons/iconCornerUpRight.js +1 -3
- package/dist/index.css +3254 -2922
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/lineChartMini/lineChartMini.js +15 -3
- package/dist/list/itemData/itemDataInternal.js +4 -1
- package/dist/list/listItem/listItem.js +4 -1
- package/dist/menu/components/controlledMenuList/controlledMenuList.d.ts +27 -0
- package/dist/menu/components/controlledMenuList/controlledMenuList.js +126 -0
- package/dist/menu/components/createControlledMenuList.d.ts +37 -0
- package/dist/menu/components/createControlledMenuList.js +55 -0
- package/dist/menu/components/createMenuItem.d.ts +67 -0
- package/dist/menu/components/createMenuItem.js +97 -0
- package/dist/menu/components/menuButton.js +12 -3
- package/dist/menu/components/menuItem.d.ts +1 -2
- package/dist/menu/components/menuItem.js +20 -74
- package/dist/menu/contexts/usePathContext.d.ts +2 -0
- package/dist/menu/contexts/usePathContext.js +9 -0
- package/dist/menu/controlledMenu.js +8 -175
- package/dist/menu/utils/buildMenuContent.d.ts +2 -0
- package/dist/menu/utils/buildMenuContent.js +38 -0
- package/dist/menu/utils/findContent.d.ts +2 -2
- package/dist/menu/utils/findContent.js +4 -3
- package/dist/menu/utils/getItemLabel.d.ts +2 -0
- package/dist/menu/utils/getItemLabel.js +8 -0
- package/dist/menu/utils/getSafeRel.d.ts +1 -0
- package/dist/menu/utils/getSafeRel.js +14 -0
- package/dist/menu/utils/isMenuItem.d.ts +2 -0
- package/dist/menu/utils/isMenuItem.js +13 -0
- package/dist/menu/utils/isSafeHref.d.ts +1 -0
- package/dist/menu/utils/isSafeHref.js +10 -0
- package/dist/menu/utils/normalizeSeparators.d.ts +2 -0
- package/dist/menu/utils/normalizeSeparators.js +23 -0
- package/dist/menu/utils/resolveKeys.d.ts +12 -0
- package/dist/menu/utils/resolveKeys.js +22 -0
- package/dist/menu/utils/useLastValidSheet.d.ts +7 -0
- package/dist/menu/utils/useLastValidSheet.js +30 -0
- package/dist/menu/utils/useMenuItemCore.d.ts +31 -0
- package/dist/menu/utils/useMenuItemCore.js +54 -0
- package/dist/menu/utils/useMenuItemKeyboardNav.d.ts +2 -0
- package/dist/menu/utils/useMenuItemKeyboardNav.js +15 -0
- package/dist/menu/utils/useMenuListKeyboardNav.d.ts +12 -0
- package/dist/menu/utils/useMenuListKeyboardNav.js +77 -0
- package/dist/menu/utils/useMenuPath.d.ts +6 -0
- package/dist/menu/utils/useMenuPath.js +35 -0
- package/dist/nav/navItem/navItem.js +10 -5
- package/dist/nav/navSection/navSection.js +7 -5
- package/dist/pagination/paginationArrow.js +10 -3
- package/dist/radioGroupRaw/radioGroupRaw.js +2 -1
- package/dist/rangeRaw/rangeRaw.js +0 -1
- package/dist/selectList/selectList.helpers.d.ts +1 -1
- package/dist/selectList/selectList.helpers.js +29 -4
- package/dist/selectList/selectList.js +3 -1
- package/dist/selectList/selectList.reducer.js +1 -2
- package/dist/selectList/selectListItem.js +4 -1
- package/dist/sortControl/sortControl.js +59 -4
- package/dist/table/children/useTableChildren.d.ts +1 -1
- package/dist/table/children/useTableChildren.js +3 -3
- package/dist/table/flexible/columnsList.js +4 -2
- package/dist/table/selectable/useSelectableRows.d.ts +8 -0
- package/dist/table/selectable/useSelectableRows.js +14 -6
- package/dist/table/table.js +1 -7
- package/dist/tabs/tabs.js +60 -58
- package/dist/tabs/tabsTestHelper.js +2 -2
- package/dist/timePickerRaw/timePickerRaw.js +1 -1
- package/dist/toggleButtonRaw/toggleButtonRaw.js +5 -2
- package/dist/utils/localization/translations/ar.json +3 -1
- package/dist/utils/localization/translations/cs.json +9 -5
- package/dist/utils/localization/translations/da-DK.json +9 -5
- package/dist/utils/localization/translations/de.json +9 -5
- package/dist/utils/localization/translations/en.json +5 -1
- package/dist/utils/localization/translations/es.json +9 -5
- package/dist/utils/localization/translations/fi-FI.json +9 -5
- package/dist/utils/localization/translations/fr-FR.json +9 -5
- package/dist/utils/localization/translations/fr.json +9 -5
- package/dist/utils/localization/translations/hu-HU.json +9 -5
- package/dist/utils/localization/translations/id.json +9 -5
- package/dist/utils/localization/translations/it.json +9 -5
- package/dist/utils/localization/translations/ja.json +9 -5
- package/dist/utils/localization/translations/ko-KR.json +9 -5
- package/dist/utils/localization/translations/ms.json +9 -5
- package/dist/utils/localization/translations/nb-NO.json +9 -5
- package/dist/utils/localization/translations/nl.json +9 -5
- package/dist/utils/localization/translations/pl.json +9 -5
- package/dist/utils/localization/translations/pt-BR.json +9 -5
- package/dist/utils/localization/translations/pt-PT.json +9 -5
- package/dist/utils/localization/translations/ro-RO.json +9 -5
- package/dist/utils/localization/translations/sk-SK.json +9 -5
- package/dist/utils/localization/translations/sv.json +9 -5
- package/dist/utils/localization/translations/th.json +9 -5
- package/dist/utils/localization/translations/tr.json +9 -5
- package/dist/utils/localization/translations/zh-Hans.json +9 -5
- package/dist/utils/localization/translations/zh-TW.json +9 -5
- package/dist/utils/localization/useDirectionalIcon.d.ts +3 -0
- package/dist/utils/localization/useDirectionalIcon.js +9 -0
- package/dist/utils/positioningUtils/alignments.d.ts +2 -2
- package/dist/utils/positioningUtils/alignments.js +2 -2
- package/dist/utils/positioningUtils/calculatePosition.js +4 -6
- package/esm/calendar/calendar.js +7 -4
- package/esm/card/components/title.js +4 -1
- package/esm/card/components/titleLink.js +5 -2
- package/esm/chart/barChart/getDefaultOptions.d.ts +2 -1
- package/esm/chart/barChart/getDefaultOptions.js +5 -2
- package/esm/chart/barChart.js +6 -4
- package/esm/chart/lineChart/getDefaultOptions.d.ts +2 -1
- package/esm/chart/lineChart/getDefaultOptions.js +5 -2
- package/esm/chart/lineChart.js +4 -2
- package/esm/checkboxListWithAction/checkboxListWithAction.js +4 -1
- package/esm/commonHelpers/arrowNavigation/components/arrowButton/arrowButton.js +4 -1
- package/esm/controlledPopup/controlledPopup.d.ts +1 -0
- package/esm/controlledPopup/controlledPopup.js +3 -1
- package/esm/dataGrid/cell/cell.d.ts +2 -1
- package/esm/dataGrid/cell/cell.js +2 -2
- package/esm/dataGrid/dataGrid.js +7 -4
- package/esm/dataGrid/listColumn.d.ts +2 -0
- package/esm/dataGrid/row/row.d.ts +2 -1
- package/esm/dataGrid/row/row.js +13 -9
- package/esm/dataGrid/withFlexibleColumns/components/columnSettingsList.js +2 -1
- package/esm/dataGrid/withSelectableRows/components/bulkActions/bulkActions.d.ts +4 -0
- package/esm/dateRangeInner/dateRangeInner.js +5 -2
- package/esm/dateRangeRaw/dateRangeRaw.js +5 -2
- package/esm/dateRangeRaw/utils/parseLabel.js +1 -1
- package/esm/dropdownRaw/dropdownRaw.js +12 -6
- package/esm/fileUpload/components/dropZoneContent.js +100 -100
- package/esm/fileUpload/fileUpload.js +100 -100
- package/esm/filters/components/filtersSearchList.js +4 -1
- package/esm/filtersBar/filtersContainer/filtersContainer.js +62 -61
- package/esm/formStepperButtons/formStepperButtons.js +4 -1
- package/esm/groupsFilterRaw/groupsFilterAdjustmentState.js +4 -1
- package/esm/groupsFilterRaw/groupsFilterInitialState.js +4 -1
- package/esm/header/headerBack.js +4 -1
- package/esm/icons/iconAlignLeft.js +1 -3
- package/esm/icons/iconAlignmentLeft.js +1 -3
- package/esm/icons/iconAlignmentRight.js +1 -3
- package/esm/icons/iconArrowBottomLeft.js +1 -3
- package/esm/icons/iconArrowBottomRight.js +1 -3
- package/esm/icons/iconArrowLeftPath.js +1 -3
- package/esm/icons/iconArrowRight.js +1 -3
- package/esm/icons/iconArrowRightCircle.js +1 -3
- package/esm/icons/iconArrowRightPath.js +1 -3
- package/esm/icons/iconArrowTopLeft.js +1 -3
- package/esm/icons/iconArrowTopRight.js +1 -3
- package/esm/icons/iconChevronDoubleRight.js +1 -3
- package/esm/icons/iconChevronRight.js +1 -3
- package/esm/icons/iconChevronRightSmall.js +1 -3
- package/esm/icons/iconCornerDownLeft.js +1 -3
- package/esm/icons/iconCornerDownRight.js +1 -3
- package/esm/icons/iconCornerLeftDown.js +1 -3
- package/esm/icons/iconCornerLeftUp.js +1 -3
- package/esm/icons/iconCornerRightDown.js +1 -3
- package/esm/icons/iconCornerRightUp.js +1 -3
- package/esm/icons/iconCornerUpLeft.js +1 -3
- package/esm/icons/iconCornerUpRight.js +1 -3
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/lineChartMini/lineChartMini.js +15 -3
- package/esm/list/itemData/itemDataInternal.js +4 -1
- package/esm/list/listItem/listItem.js +4 -1
- package/esm/menu/components/controlledMenuList/controlledMenuList.d.ts +27 -0
- package/esm/menu/components/controlledMenuList/controlledMenuList.js +123 -0
- package/esm/menu/components/createControlledMenuList.d.ts +37 -0
- package/esm/menu/components/createControlledMenuList.js +51 -0
- package/esm/menu/components/createMenuItem.d.ts +67 -0
- package/esm/menu/components/createMenuItem.js +93 -0
- package/esm/menu/components/menuButton.js +12 -3
- package/esm/menu/components/menuItem.d.ts +1 -2
- package/esm/menu/components/menuItem.js +20 -74
- package/esm/menu/contexts/usePathContext.d.ts +2 -0
- package/esm/menu/contexts/usePathContext.js +5 -0
- package/esm/menu/controlledMenu.js +10 -177
- package/esm/menu/utils/buildMenuContent.d.ts +2 -0
- package/esm/menu/utils/buildMenuContent.js +34 -0
- package/esm/menu/utils/findContent.d.ts +2 -2
- package/esm/menu/utils/findContent.js +4 -3
- package/esm/menu/utils/getItemLabel.d.ts +2 -0
- package/esm/menu/utils/getItemLabel.js +4 -0
- package/esm/menu/utils/getSafeRel.d.ts +1 -0
- package/esm/menu/utils/getSafeRel.js +10 -0
- package/esm/menu/utils/isMenuItem.d.ts +2 -0
- package/esm/menu/utils/isMenuItem.js +9 -0
- package/esm/menu/utils/isSafeHref.d.ts +1 -0
- package/esm/menu/utils/isSafeHref.js +6 -0
- package/esm/menu/utils/normalizeSeparators.d.ts +2 -0
- package/esm/menu/utils/normalizeSeparators.js +19 -0
- package/esm/menu/utils/resolveKeys.d.ts +12 -0
- package/esm/menu/utils/resolveKeys.js +18 -0
- package/esm/menu/utils/useLastValidSheet.d.ts +7 -0
- package/esm/menu/utils/useLastValidSheet.js +26 -0
- package/esm/menu/utils/useMenuItemCore.d.ts +31 -0
- package/esm/menu/utils/useMenuItemCore.js +50 -0
- package/esm/menu/utils/useMenuItemKeyboardNav.d.ts +2 -0
- package/esm/menu/utils/useMenuItemKeyboardNav.js +11 -0
- package/esm/menu/utils/useMenuListKeyboardNav.d.ts +12 -0
- package/esm/menu/utils/useMenuListKeyboardNav.js +73 -0
- package/esm/menu/utils/useMenuPath.d.ts +6 -0
- package/esm/menu/utils/useMenuPath.js +31 -0
- package/esm/nav/navItem/navItem.js +10 -5
- package/esm/nav/navSection/navSection.js +7 -5
- package/esm/pagination/paginationArrow.js +10 -3
- package/esm/radioGroupRaw/radioGroupRaw.js +2 -1
- package/esm/rangeRaw/rangeRaw.js +0 -1
- package/esm/selectList/selectList.helpers.d.ts +1 -1
- package/esm/selectList/selectList.helpers.js +29 -4
- package/esm/selectList/selectList.js +3 -1
- package/esm/selectList/selectList.reducer.js +1 -2
- package/esm/selectList/selectListItem.js +4 -1
- package/esm/sortControl/sortControl.js +59 -4
- package/esm/table/children/useTableChildren.d.ts +1 -1
- package/esm/table/children/useTableChildren.js +3 -3
- package/esm/table/flexible/columnsList.js +4 -2
- package/esm/table/selectable/useSelectableRows.d.ts +8 -0
- package/esm/table/selectable/useSelectableRows.js +14 -6
- package/esm/table/table.js +1 -7
- package/esm/tabs/tabs.js +60 -58
- package/esm/tabs/tabsTestHelper.js +2 -2
- package/esm/testHelpers/mockAbsoluteAlignment.d.ts +1 -0
- package/esm/testHelpers/mockAbsoluteAlignment.js +10 -0
- package/esm/timePickerRaw/timePickerRaw.js +1 -1
- package/esm/toggleButtonRaw/toggleButtonRaw.js +5 -2
- package/esm/utils/localization/translations/ar.json +3 -1
- package/esm/utils/localization/translations/cs.json +9 -5
- package/esm/utils/localization/translations/da-DK.json +9 -5
- package/esm/utils/localization/translations/de.json +9 -5
- package/esm/utils/localization/translations/en.json +5 -1
- package/esm/utils/localization/translations/es.json +9 -5
- package/esm/utils/localization/translations/fi-FI.json +9 -5
- package/esm/utils/localization/translations/fr-FR.json +9 -5
- package/esm/utils/localization/translations/fr.json +9 -5
- package/esm/utils/localization/translations/hu-HU.json +9 -5
- package/esm/utils/localization/translations/id.json +9 -5
- package/esm/utils/localization/translations/it.json +9 -5
- package/esm/utils/localization/translations/ja.json +9 -5
- package/esm/utils/localization/translations/ko-KR.json +9 -5
- package/esm/utils/localization/translations/ms.json +9 -5
- package/esm/utils/localization/translations/nb-NO.json +9 -5
- package/esm/utils/localization/translations/nl.json +9 -5
- package/esm/utils/localization/translations/pl.json +9 -5
- package/esm/utils/localization/translations/pt-BR.json +9 -5
- package/esm/utils/localization/translations/pt-PT.json +9 -5
- package/esm/utils/localization/translations/ro-RO.json +9 -5
- package/esm/utils/localization/translations/sk-SK.json +9 -5
- package/esm/utils/localization/translations/sv.json +9 -5
- package/esm/utils/localization/translations/th.json +9 -5
- package/esm/utils/localization/translations/tr.json +9 -5
- package/esm/utils/localization/translations/zh-Hans.json +9 -5
- package/esm/utils/localization/translations/zh-TW.json +9 -5
- package/esm/utils/localization/useDirectionalIcon.d.ts +3 -0
- package/esm/utils/localization/useDirectionalIcon.js +5 -0
- package/esm/utils/positioningUtils/alignments.d.ts +2 -2
- package/esm/utils/positioningUtils/alignments.js +2 -2
- package/esm/utils/positioningUtils/calculatePosition.js +4 -6
- package/package.json +123 -122
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
3
|
-
import {
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */
|
|
3
|
+
import { Fragment, cloneElement, useCallback } from "react";
|
|
4
4
|
import { MenuButton } from "./menuButton";
|
|
5
|
-
import { ControlledMenu } from "../controlledMenu";
|
|
6
5
|
import { ControlledPopup } from "../../controlledPopup/controlledPopup";
|
|
7
|
-
import { PathContext } from "../contexts/pathContext";
|
|
8
6
|
import { classNames } from "../../commonHelpers/classNames/classNames";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
import { isSeparator } from "./menuSeparator";
|
|
12
|
-
export const isMenuItem = (element) => {
|
|
13
|
-
if (!element || !element.type) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
if (element.type === ControlledMenu.Item) {
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
if ((typeof element.type === "object" || typeof element.type === "function") && "displayName" in element.type) {
|
|
20
|
-
return element.type.displayName === "MenuItem";
|
|
21
|
-
}
|
|
22
|
-
return false;
|
|
23
|
-
};
|
|
7
|
+
import { useMenuItemCore } from "../utils/useMenuItemCore";
|
|
8
|
+
export { isMenuItem } from "../utils/isMenuItem";
|
|
24
9
|
export const MenuItem = ({ id, children, name, icon, disabled, onClick, link, target, rel, isMobile = false, setIsOpen, trigger, className, active, alignment }) => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
10
|
+
const { ref, isOpen, hasChildren, content, openedViaKeyboard, contentAlignment, path, onOpenBranch, handleOpenChange } = useMenuItemCore({
|
|
11
|
+
id,
|
|
12
|
+
children,
|
|
13
|
+
className,
|
|
14
|
+
alignment,
|
|
15
|
+
isMobile,
|
|
16
|
+
setIsOpen,
|
|
17
|
+
onClick
|
|
18
|
+
});
|
|
19
|
+
// MenuButton.onClick signature is (id, e) — adapt the hook's (e)-only handler
|
|
20
|
+
const memoizedDesktopActionOnClick = useCallback((_, e) => {
|
|
29
21
|
setIsOpen === null || setIsOpen === void 0 ? void 0 : setIsOpen(false);
|
|
30
|
-
onClick === null || onClick === void 0 ? void 0 : onClick(
|
|
31
|
-
}, [setIsOpen, onClick]);
|
|
22
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(id, e);
|
|
23
|
+
}, [setIsOpen, onClick, id]);
|
|
24
|
+
// MenuItem-specific callbacks (not provided by hook)
|
|
32
25
|
const memoizedMobileActionOnClick = useCallback((itemId, e) => {
|
|
33
26
|
onOpenBranch(id);
|
|
34
27
|
!link && (onClick === null || onClick === void 0 ? void 0 : onClick(itemId, e));
|
|
@@ -46,54 +39,7 @@ export const MenuItem = ({ id, children, name, icon, disabled, onClick, link, ta
|
|
|
46
39
|
}
|
|
47
40
|
onClick === null || onClick === void 0 ? void 0 : onClick(id, e);
|
|
48
41
|
}, [onClick, onOpenBranch, id, trigger]);
|
|
49
|
-
|
|
50
|
-
closeBranch();
|
|
51
|
-
}, [closeBranch]);
|
|
52
|
-
const ref = useRef(null);
|
|
53
|
-
const content = useMemo(() => {
|
|
54
|
-
const cont = [];
|
|
55
|
-
Children.map(children, (child) => {
|
|
56
|
-
if (!child) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (typeof child === "string") {
|
|
60
|
-
cont.push(_jsx("li", { className: classNames(["zen-menu-item__content", className !== null && className !== void 0 ? className : ""]), role: "presentation", children: child }, generateId()));
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
if (isValidElement(child) && isSeparator(child)) {
|
|
64
|
-
const clone = cloneElement(child, {
|
|
65
|
-
key: child.props.key || generateId()
|
|
66
|
-
});
|
|
67
|
-
cont.push(clone);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (isMenuItem(child)) {
|
|
71
|
-
const childProps = child.props;
|
|
72
|
-
const clone = cloneElement(child, {
|
|
73
|
-
isMobile,
|
|
74
|
-
key: childProps.id,
|
|
75
|
-
setIsOpen
|
|
76
|
-
});
|
|
77
|
-
cont.push(clone);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const childProps = child.props;
|
|
81
|
-
cont.push(_jsx("li", { className: classNames(["zen-menu-item__content", className !== null && className !== void 0 ? className : ""]), role: "presentation", children: child }, childProps.id || childProps["data-id"] || generateId()));
|
|
82
|
-
});
|
|
83
|
-
return cont;
|
|
84
|
-
}, [children, isMobile, setIsOpen, className]);
|
|
85
|
-
const isOpen = useMemo(() => path.includes(id), [path, id]);
|
|
86
|
-
// Track previous isOpen state to detect when submenu opens
|
|
87
|
-
const wasOpenRef = useRef(false);
|
|
88
|
-
const localOpenedViaKeyboardRef = useRef(false);
|
|
89
|
-
// Capture keyboard navigation state synchronously when isOpen transitions to true
|
|
90
|
-
if (isOpen && !wasOpenRef.current && navigatedViaKeyboardRef) {
|
|
91
|
-
localOpenedViaKeyboardRef.current = navigatedViaKeyboardRef.current;
|
|
92
|
-
navigatedViaKeyboardRef.current = false; // Reset for next navigation
|
|
93
|
-
}
|
|
94
|
-
wasOpenRef.current = isOpen;
|
|
95
|
-
const openedViaKeyboard = localOpenedViaKeyboardRef.current;
|
|
96
|
-
if (content.length === 0) {
|
|
42
|
+
if (!hasChildren) {
|
|
97
43
|
return (_jsx(MenuButton, { id: id, name: name, icon: icon, disabled: disabled, link: link, target: target, rel: rel, onClick: memoizedDesktopActionOnClick, className: className, active: active, hasChildren: false }, id));
|
|
98
44
|
}
|
|
99
45
|
if (isMobile) {
|
|
@@ -109,6 +55,6 @@ export const MenuItem = ({ id, children, name, icon, disabled, onClick, link, ta
|
|
|
109
55
|
else {
|
|
110
56
|
popupTrigger = (_jsx(MenuButton, { id: id, ref: ref, name: name, icon: icon, disabled: disabled, hasChildren: true, onClick: memoizedTriggerOnClick, active: active }, id));
|
|
111
57
|
}
|
|
112
|
-
return (_jsxs(Fragment, { children: [popupTrigger, _jsx(ControlledPopup, { className: classNames([`zen-controlled-menu-submenu--${path.length}`]), useTrapFocusWithTrigger: openedViaKeyboard ? "on" : "withTrigger", alignment: contentAlignment, triggerRef: ref, isOpen: isOpen, onOpenChange:
|
|
58
|
+
return (_jsxs(Fragment, { children: [popupTrigger, _jsx(ControlledPopup, { className: classNames([`zen-controlled-menu-submenu--${path.length}`]), useTrapFocusWithTrigger: openedViaKeyboard ? "on" : "withTrigger", alignment: contentAlignment, triggerRef: ref, isOpen: isOpen, onOpenChange: handleOpenChange, ariaLabel: popupTrigger.props.name, recalculateOnScroll: true, children: _jsx("ul", { role: "menu", className: "zen-menu-item", children: content }) })] }, id));
|
|
113
59
|
};
|
|
114
60
|
MenuItem.displayName = "MenuItem";
|
|
@@ -1,45 +1,26 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
2
|
-
|
|
3
|
-
import { Children, cloneElement, isValidElement, useState, useMemo, useCallback, useEffect, useRef } from "react";
|
|
4
|
-
import { MenuItem, isMenuItem } from "./components/menuItem";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback, useEffect, useRef } from "react";
|
|
5
3
|
import { classNames } from "../commonHelpers/classNames/classNames";
|
|
6
|
-
import { findContent } from "./utils/findContent";
|
|
7
|
-
import { findFirstFocusable } from "./utils/findFirstFocusable";
|
|
8
|
-
import { findLastFocusable } from "./utils/findLastFocusable";
|
|
9
|
-
import { findNextFocusable } from "./utils/findNextFocusable";
|
|
10
|
-
import { isButton } from "./utils/isButton";
|
|
11
|
-
import { isLink } from "./utils/isLink";
|
|
12
|
-
import { findPrevFocusable } from "./utils/findPrevFocusable";
|
|
13
|
-
import { MenuButton } from "./components/menuButton";
|
|
14
|
-
import { IconArrowLeft } from "../icons/iconArrowLeft";
|
|
15
4
|
import { ControlledPopup } from "../controlledPopup/controlledPopup";
|
|
16
5
|
import { MobileSheet } from "../mobileSheet/mobileSheet";
|
|
17
6
|
import { DeviceType } from "../commonHelpers/hooks/deviceType";
|
|
18
7
|
import { useDeviceType } from "../commonHelpers/hooks/useDeviceType";
|
|
19
|
-
import { generateId } from "../commonHelpers/generateId";
|
|
20
|
-
import { PathProvider } from "./contexts/pathProvider";
|
|
21
|
-
import { isSeparator, MenuSeparator } from "./components/menuSeparator";
|
|
22
8
|
import { FOCUSABLE_SELECTOR } from "../utils/focusableSelector";
|
|
9
|
+
import { ControlledMenuList } from "./components/controlledMenuList/controlledMenuList";
|
|
10
|
+
const EmbeddedMenuList = ControlledMenuList;
|
|
23
11
|
export const ControlledMenu = ({ children, isOpen, setIsOpen, triggerRef, ariaLabel, ariaLabelledby, id, title, className = "", listClassName = "", paddingX = 0, paddingY = 0, alignment, closeOnScroll = true }) => {
|
|
24
12
|
const [deviceType, setDeviceType] = useState(DeviceType.Desktop);
|
|
25
13
|
const isMobile = deviceType === DeviceType.Mobile;
|
|
26
14
|
const memoizedOnChange = useCallback(setIsOpen, [setIsOpen]);
|
|
27
15
|
useDeviceType(setDeviceType);
|
|
28
16
|
const menuListRef = useRef(null);
|
|
29
|
-
const [path, setPath] = useState([]);
|
|
30
|
-
// Track if the trigger was activated via keyboard
|
|
31
17
|
const openedViaKeyboardRef = useRef(false);
|
|
32
|
-
// Track if submenu was navigated via keyboard (ArrowRight)
|
|
33
|
-
const navigatedViaKeyboardRef = useRef(false);
|
|
34
|
-
// Track if keyboard is actively being used for navigation (vs mouse/touch)
|
|
35
|
-
const keyboardActiveRef = useRef(false);
|
|
36
|
-
// Listen for keyboard activation on trigger
|
|
37
18
|
useEffect(() => {
|
|
38
19
|
const trigger = triggerRef.current;
|
|
39
20
|
if (!trigger)
|
|
40
21
|
return undefined;
|
|
41
22
|
const handleKeyDown = (e) => {
|
|
42
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
23
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowRight") {
|
|
43
24
|
openedViaKeyboardRef.current = true;
|
|
44
25
|
}
|
|
45
26
|
};
|
|
@@ -53,12 +34,6 @@ export const ControlledMenu = ({ children, isOpen, setIsOpen, triggerRef, ariaLa
|
|
|
53
34
|
trigger.removeEventListener("mousedown", handleMouseDown);
|
|
54
35
|
};
|
|
55
36
|
}, [triggerRef]);
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
if (path.length && !isOpen) {
|
|
58
|
-
setPath([]);
|
|
59
|
-
}
|
|
60
|
-
}, [isOpen, path, setPath]);
|
|
61
|
-
// Focus the menu list container or first item when menu opens (for keyboard navigation)
|
|
62
37
|
useEffect(() => {
|
|
63
38
|
var _a;
|
|
64
39
|
if (isOpen && !isMobile && menuListRef.current) {
|
|
@@ -70,156 +45,14 @@ export const ControlledMenu = ({ children, isOpen, setIsOpen, triggerRef, ariaLa
|
|
|
70
45
|
}
|
|
71
46
|
}
|
|
72
47
|
}, [isOpen, isMobile]);
|
|
73
|
-
const onOpenBranch = useCallback((branchId) => {
|
|
74
|
-
if (!branchId) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
if (!path.includes(branchId)) {
|
|
78
|
-
setPath([...path, branchId]);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (path.includes(branchId)) {
|
|
82
|
-
setPath(v => {
|
|
83
|
-
const newPath = [...v];
|
|
84
|
-
newPath.pop();
|
|
85
|
-
return newPath;
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}, [setPath, path]);
|
|
89
|
-
const closeBranch = useCallback(() => {
|
|
90
|
-
setPath(v => {
|
|
91
|
-
const newPath = [...v];
|
|
92
|
-
newPath.pop();
|
|
93
|
-
return newPath;
|
|
94
|
-
});
|
|
95
|
-
}, [setPath]);
|
|
96
|
-
const [content, parent] = useMemo(() => {
|
|
97
|
-
let par = null;
|
|
98
|
-
let currentChildren = children;
|
|
99
|
-
if (isMobile && path.length > 0) {
|
|
100
|
-
const el = findContent(children, ControlledMenu.Item, path[path.length - 1]);
|
|
101
|
-
if (el || isValidElement(el)) {
|
|
102
|
-
const elProps = el.props;
|
|
103
|
-
currentChildren = elProps.children;
|
|
104
|
-
par = el;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
let cont = [];
|
|
108
|
-
Children.map(currentChildren, (child) => {
|
|
109
|
-
if (!child) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (typeof child === "string") {
|
|
113
|
-
cont.push(_jsx("li", { role: "presentation", className: classNames(["zen-menu-item__content"]), children: child }, generateId()));
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (isValidElement(child) && isSeparator(child)) {
|
|
117
|
-
const clone = cloneElement(child, {
|
|
118
|
-
key: child.props.key || generateId()
|
|
119
|
-
});
|
|
120
|
-
cont.push(clone);
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (isValidElement(child) && isMenuItem(child)) {
|
|
124
|
-
const clone = cloneElement(child, {
|
|
125
|
-
isMobile,
|
|
126
|
-
key: child.props.id,
|
|
127
|
-
setIsOpen,
|
|
128
|
-
onClick: child.props.onClick
|
|
129
|
-
});
|
|
130
|
-
cont.push(clone);
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const childProps = child.props;
|
|
134
|
-
cont.push(_jsx("li", { className: classNames(["zen-menu-item__content"]), role: "presentation", children: child }, childProps.id || childProps["data-id"] || generateId()));
|
|
135
|
-
});
|
|
136
|
-
while (cont[0] && isSeparator(cont[0])) {
|
|
137
|
-
cont.shift();
|
|
138
|
-
}
|
|
139
|
-
while (cont[cont.length - 1] && isSeparator(cont[cont.length - 1])) {
|
|
140
|
-
cont.pop();
|
|
141
|
-
}
|
|
142
|
-
cont = cont.filter((el, indx, arr) => {
|
|
143
|
-
if (isSeparator(el) && arr[indx - 1] && isSeparator(arr[indx - 1])) {
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
return true;
|
|
147
|
-
});
|
|
148
|
-
return [cont, par];
|
|
149
|
-
}, [children, isMobile, path, setIsOpen]);
|
|
150
|
-
// Handle keyboard navigation when no menu item is focused (e.g., when menu just opened)
|
|
151
|
-
const handleUnfocusedKeyDown = (e, menuList) => {
|
|
152
|
-
var _a, _b;
|
|
153
|
-
if (e.key === "ArrowDown" || e.key === "Home") {
|
|
154
|
-
e.preventDefault();
|
|
155
|
-
(_a = findFirstFocusable(menuList)) === null || _a === void 0 ? void 0 : _a.focus();
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
if (e.key === "ArrowUp" || e.key === "End") {
|
|
159
|
-
e.preventDefault();
|
|
160
|
-
(_b = findLastFocusable(menuList)) === null || _b === void 0 ? void 0 : _b.focus();
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
return false;
|
|
164
|
-
};
|
|
165
|
-
const onMouseDown = () => {
|
|
166
|
-
keyboardActiveRef.current = false;
|
|
167
|
-
};
|
|
168
|
-
const onKeyDown = e => {
|
|
169
|
-
var _a, _b, _c, _d;
|
|
170
|
-
keyboardActiveRef.current = true;
|
|
171
|
-
const target = e.target;
|
|
172
|
-
const currentTarget = e.currentTarget;
|
|
173
|
-
if (!isButton(target) && !isLink(target)) {
|
|
174
|
-
if (target === currentTarget) {
|
|
175
|
-
const menuList = currentTarget.querySelector("ul");
|
|
176
|
-
if (menuList) {
|
|
177
|
-
handleUnfocusedKeyDown(e, menuList);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (e.key === "ArrowDown") {
|
|
183
|
-
e.preventDefault();
|
|
184
|
-
(_a = findNextFocusable(target)) === null || _a === void 0 ? void 0 : _a.focus();
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
if (e.key === "ArrowUp") {
|
|
188
|
-
e.preventDefault();
|
|
189
|
-
(_b = findPrevFocusable(target)) === null || _b === void 0 ? void 0 : _b.focus();
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
if (e.key === "Home") {
|
|
193
|
-
e.preventDefault();
|
|
194
|
-
(_c = findFirstFocusable(target)) === null || _c === void 0 ? void 0 : _c.focus();
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
if (e.key === "End") {
|
|
198
|
-
e.preventDefault();
|
|
199
|
-
(_d = findLastFocusable(target)) === null || _d === void 0 ? void 0 : _d.focus();
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
if (isButton(target) &&
|
|
203
|
-
(e.key === "ArrowRight" || e.key === "Enter" || e.key === " ") &&
|
|
204
|
-
target.classList.contains("zen-menu-button__action--has-children")) {
|
|
205
|
-
e.preventDefault();
|
|
206
|
-
navigatedViaKeyboardRef.current = true;
|
|
207
|
-
target.click();
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
const renderMenuList = () => (_jsx("div", { ref: menuListRef, tabIndex: -1, onKeyDown: onKeyDown, onMouseDown: onMouseDown, className: classNames(["zen-action-list", className]), children: _jsxs("ul", { role: "menu", className: classNames(["zen-menu-item", className, listClassName]), children: [parent ? (_jsx(MenuButton, { id: "root", name: parent.props.name || "", icon: IconArrowLeft, onClick: closeBranch, hasChildren: false, disabled: false }, "root")) : null, content] }) }));
|
|
211
48
|
const hideMenu = useCallback(() => {
|
|
212
|
-
closeBranch();
|
|
213
49
|
setIsOpen(false);
|
|
214
|
-
}, [
|
|
50
|
+
}, [setIsOpen]);
|
|
215
51
|
if (isMobile) {
|
|
216
|
-
return (
|
|
52
|
+
return (_jsxs(MobileSheet, { label: title, isOpen: isOpen, triggerRef: triggerRef, onHidePanel: hideMenu, onCloseClick: hideMenu, children: [_jsx(MobileSheet.Title, { children: title }), _jsx(MobileSheet.Content, { children: _jsx(EmbeddedMenuList, { ref: menuListRef, setIsOpen: setIsOpen, isOpen: isOpen, className: className, listClassName: listClassName, children: children }) })] }));
|
|
217
53
|
}
|
|
218
|
-
return (_jsx(
|
|
219
|
-
// focusOnOpen is false - ControlledMenu handles focus based on input method
|
|
220
|
-
// (keyboard vs mouse) in its own useEffect
|
|
221
|
-
focusOnOpen: false, children: renderMenuList() }) }) }));
|
|
54
|
+
return (_jsx(ControlledPopup, { id: id, useTrapFocusWithTrigger: "on", className: classNames(["zen-controlled-menu", className]), onOpenChange: memoizedOnChange, isOpen: isOpen, triggerRef: triggerRef, paddingX: paddingX, paddingY: paddingY, alignment: alignment, ariaLabelledby: ariaLabelledby, ariaLabel: ariaLabel || title, recalculateOnScroll: true, focusOnOpen: false, closeOnScroll: closeOnScroll, children: _jsx(EmbeddedMenuList, { ref: menuListRef, setIsOpen: setIsOpen, isOpen: isOpen, className: className, listClassName: listClassName, children: children }) }));
|
|
222
55
|
};
|
|
223
|
-
ControlledMenu.Item =
|
|
224
|
-
ControlledMenu.Separator =
|
|
56
|
+
ControlledMenu.Item = ControlledMenuList.Item;
|
|
57
|
+
ControlledMenu.Separator = ControlledMenuList.Separator;
|
|
225
58
|
export const TRANSLATIONS = ["Back"];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */
|
|
3
|
+
import { Children, cloneElement, isValidElement } from "react";
|
|
4
|
+
import { classNames } from "../../commonHelpers/classNames/classNames";
|
|
5
|
+
import { isSeparator } from "../components/menuSeparator";
|
|
6
|
+
import { isMenuItem } from "./isMenuItem";
|
|
7
|
+
import { generateId } from "../../commonHelpers/generateId";
|
|
8
|
+
export function buildMenuContent(children, isMobile, setIsOpen, className) {
|
|
9
|
+
const cont = [];
|
|
10
|
+
Children.map(children, (child) => {
|
|
11
|
+
if (!child) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (typeof child === "string") {
|
|
15
|
+
cont.push(_jsx("li", { className: classNames(["zen-menu-item__content", className !== null && className !== void 0 ? className : ""]), role: "presentation", children: child }, generateId()));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (isValidElement(child) && isSeparator(child)) {
|
|
19
|
+
const clone = cloneElement(child, { key: child.props.key || generateId() });
|
|
20
|
+
cont.push(clone);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (isMenuItem(child)) {
|
|
24
|
+
const childProps = child.props;
|
|
25
|
+
const clone = cloneElement(child, { isMobile, key: childProps.id, setIsOpen });
|
|
26
|
+
cont.push(clone);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
30
|
+
const childProps = child.props;
|
|
31
|
+
cont.push(_jsx("li", { className: classNames(["zen-menu-item__content", className !== null && className !== void 0 ? className : ""]), role: "presentation", children: child }, childProps.id || childProps["data-id"] || generateId()));
|
|
32
|
+
});
|
|
33
|
+
return cont;
|
|
34
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare const findContent: (children: ReactNode,
|
|
1
|
+
import { ReactNode, ReactElement } from "react";
|
|
2
|
+
export declare const findContent: (children: ReactNode, matcher: (child: ReactElement) => boolean, id?: string) => ReactElement | null;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export const findContent = (children,
|
|
2
|
+
export const findContent = (children, matcher, id) => {
|
|
3
3
|
let found = null;
|
|
4
4
|
React.Children.forEach(children, (child) => {
|
|
5
5
|
if (found || !React.isValidElement(child)) {
|
|
6
6
|
return;
|
|
7
7
|
}
|
|
8
8
|
const childProps = child.props;
|
|
9
|
-
|
|
9
|
+
const matches = matcher(child);
|
|
10
|
+
if (id ? matches && childProps.id === id : matches) {
|
|
10
11
|
found = child;
|
|
11
12
|
return;
|
|
12
13
|
}
|
|
13
14
|
if (childProps.children) {
|
|
14
|
-
found = findContent(childProps.children,
|
|
15
|
+
found = findContent(childProps.children, matcher, id);
|
|
15
16
|
}
|
|
16
17
|
});
|
|
17
18
|
return found;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getSafeRel: (rel?: string, target?: string) => string | undefined;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const getSafeRel = (rel, target) => {
|
|
2
|
+
if (target !== "_blank")
|
|
3
|
+
return rel;
|
|
4
|
+
const parts = rel ? rel.split(/\s+/) : [];
|
|
5
|
+
if (!parts.includes("noopener"))
|
|
6
|
+
parts.push("noopener");
|
|
7
|
+
if (!parts.includes("noreferrer"))
|
|
8
|
+
parts.push("noreferrer");
|
|
9
|
+
return parts.join(" ");
|
|
10
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const isMenuItem = (element) => {
|
|
2
|
+
if (!element || !element.type) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
if ((typeof element.type === "object" || typeof element.type === "function") && "displayName" in element.type) {
|
|
6
|
+
return element.type.displayName === "MenuItem";
|
|
7
|
+
}
|
|
8
|
+
return false;
|
|
9
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isSafeHref: (href?: string) => boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isSeparator } from "../components/menuSeparator";
|
|
2
|
+
export const normalizeSeparators = (items) => {
|
|
3
|
+
// Find the first non-separator index
|
|
4
|
+
let start = 0;
|
|
5
|
+
while (start < items.length && isSeparator(items[start])) {
|
|
6
|
+
start++;
|
|
7
|
+
}
|
|
8
|
+
// Find the last non-separator index
|
|
9
|
+
let end = items.length - 1;
|
|
10
|
+
while (end >= start && isSeparator(items[end])) {
|
|
11
|
+
end--;
|
|
12
|
+
}
|
|
13
|
+
// If all items are separators or array is empty
|
|
14
|
+
if (start > end) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
// Slice to remove leading/trailing separators and filter consecutive duplicates
|
|
18
|
+
return items.slice(start, end + 1).filter((el, i, arr) => !(isSeparator(el) && arr[i - 1] && isSeparator(arr[i - 1])));
|
|
19
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const verticalKeys: {
|
|
2
|
+
keyNext: string;
|
|
3
|
+
keyPrev: string;
|
|
4
|
+
keyOpenNested: string;
|
|
5
|
+
keyBack: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const resolveKeys: (target: HTMLElement, isHorizontal: boolean) => {
|
|
8
|
+
keyNext: string;
|
|
9
|
+
keyPrev: string;
|
|
10
|
+
keyOpenNested: string;
|
|
11
|
+
keyBack: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const verticalKeys = {
|
|
2
|
+
keyNext: "ArrowDown",
|
|
3
|
+
keyPrev: "ArrowUp",
|
|
4
|
+
keyOpenNested: "ArrowRight",
|
|
5
|
+
keyBack: "ArrowLeft"
|
|
6
|
+
};
|
|
7
|
+
export const resolveKeys = (target, isHorizontal) => {
|
|
8
|
+
const inSubMenu = isHorizontal && !!target.closest('[class*="zen-controlled-menu-submenu"]');
|
|
9
|
+
if (inSubMenu) {
|
|
10
|
+
return verticalKeys;
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
keyNext: isHorizontal ? "ArrowRight" : "ArrowDown",
|
|
14
|
+
keyPrev: isHorizontal ? "ArrowLeft" : "ArrowUp",
|
|
15
|
+
keyOpenNested: isHorizontal ? "ArrowUp" : "ArrowRight",
|
|
16
|
+
keyBack: isHorizontal ? "ArrowDown" : "ArrowLeft"
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from "react";
|
|
2
|
+
export declare const useLastValidSheet: (nestedContent: ReactElement[] | null, nestedParent: ReactElement | null, path: string[], children: ReactNode) => {
|
|
3
|
+
sheetContent: ReactElement<unknown, string | import("react").JSXElementConstructor<any>>[];
|
|
4
|
+
sheetParent: ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | null;
|
|
5
|
+
sheetPathLength: number;
|
|
6
|
+
sheetParentName: string;
|
|
7
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useRef } from "react";
|
|
2
|
+
import { findContent } from "./findContent";
|
|
3
|
+
import { getItemLabel } from "./getItemLabel";
|
|
4
|
+
import { isMenuItem } from "../components/menuItem";
|
|
5
|
+
// Preserves the last non-null nested sheet state so the MobileSheet has content
|
|
6
|
+
// to render during its closing animation after `nestedContent` goes null.
|
|
7
|
+
export const useLastValidSheet = (nestedContent, nestedParent, path, children) => {
|
|
8
|
+
const lastNestedContentRef = useRef([]);
|
|
9
|
+
const lastNestedParentRef = useRef(null);
|
|
10
|
+
const lastPathLengthRef = useRef(0);
|
|
11
|
+
const lastSheetTitleRef = useRef("");
|
|
12
|
+
const rootEl = path.length > 0 ? findContent(children, isMenuItem, path[0]) : null;
|
|
13
|
+
const currentSheetTitle = rootEl ? getItemLabel(rootEl) : "";
|
|
14
|
+
if (nestedContent !== null) {
|
|
15
|
+
lastNestedContentRef.current = nestedContent;
|
|
16
|
+
lastNestedParentRef.current = nestedParent;
|
|
17
|
+
lastPathLengthRef.current = path.length;
|
|
18
|
+
lastSheetTitleRef.current = currentSheetTitle;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
sheetContent: nestedContent !== null ? nestedContent : lastNestedContentRef.current,
|
|
22
|
+
sheetParent: nestedContent !== null ? nestedParent : lastNestedParentRef.current,
|
|
23
|
+
sheetPathLength: nestedContent !== null ? path.length : lastPathLengthRef.current,
|
|
24
|
+
sheetParentName: nestedContent !== null ? currentSheetTitle : lastSheetTitleRef.current
|
|
25
|
+
};
|
|
26
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { TAlignment } from "../../absolute/absolute";
|
|
3
|
+
export interface IUseMenuItemCoreParams {
|
|
4
|
+
id: string;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
alignment?: TAlignment;
|
|
8
|
+
isMobile?: boolean;
|
|
9
|
+
setIsOpen?: (v: boolean) => void;
|
|
10
|
+
onClick?: (id: string, e: React.MouseEvent) => void;
|
|
11
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Core menu item logic shared between MenuItem and createMenuItem.
|
|
15
|
+
* Consolidates context access, state computation, and callback memoization.
|
|
16
|
+
*/
|
|
17
|
+
export declare const useMenuItemCore: ({ id, children, className, alignment, isMobile, setIsOpen, onClick, onOpenChange }: IUseMenuItemCoreParams) => {
|
|
18
|
+
ref: import("react").RefObject<HTMLButtonElement | null>;
|
|
19
|
+
isOpen: boolean;
|
|
20
|
+
hasChildren: boolean;
|
|
21
|
+
content: ReactNode[];
|
|
22
|
+
openedViaKeyboard: boolean;
|
|
23
|
+
contentAlignment: TAlignment;
|
|
24
|
+
path: string[];
|
|
25
|
+
onOpenBranch: (id: string) => void;
|
|
26
|
+
closeBranch: () => void;
|
|
27
|
+
navigatedViaKeyboardRef: import("react").RefObject<boolean> | undefined;
|
|
28
|
+
handleDesktopActionClick: (e: React.MouseEvent) => void;
|
|
29
|
+
handleTriggerClick: () => void;
|
|
30
|
+
handleOpenChange: () => void;
|
|
31
|
+
};
|