@geotab/zenith 3.10.0-beta.7 → 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 +33 -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 +3257 -2925
- 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/list.d.ts +1 -0
- package/dist/list/list.js +2 -2
- package/dist/list/listItem/listItem.d.ts +1 -3
- package/dist/list/listItem/listItem.js +6 -5
- 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/list.d.ts +1 -0
- package/esm/list/list.js +2 -2
- package/esm/list/listItem/listItem.d.ts +1 -3
- package/esm/list/listItem/listItem.js +6 -5
- 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
|
@@ -2,18 +2,24 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { createElement, useCallback, useMemo } from "react";
|
|
3
3
|
import { classNames } from "../../commonHelpers/classNames/classNames";
|
|
4
4
|
import { IconChevronRight } from "../../icons/iconChevronRight";
|
|
5
|
+
import { IconChevronLeft } from "../../icons/iconChevronLeft";
|
|
6
|
+
import { useDirectionalIcon } from "../../utils/localization/useDirectionalIcon";
|
|
5
7
|
import { useDriveClassName } from "../../utils/theme/useDriveClassName";
|
|
6
8
|
import { useDrive } from "../../utils/theme/useDrive";
|
|
7
9
|
import { getMenuButtonState } from "../utils/getMenuButtonState";
|
|
10
|
+
import { isSafeHref } from "../utils/isSafeHref";
|
|
11
|
+
import { getSafeRel } from "../utils/getSafeRel";
|
|
8
12
|
export const MenuButton = ({ id, onClick, hasChildren, disabled, icon, name, link, target, rel, className = "", active = null, ref }) => {
|
|
9
13
|
const { hasState, isActive } = getMenuButtonState(active, disabled);
|
|
10
14
|
const driveMenuButtonActionClasses = useDriveClassName("zen-menu-button__action");
|
|
11
15
|
const isDrive = useDrive();
|
|
16
|
+
const ChevronIcon = useDirectionalIcon(IconChevronRight, IconChevronLeft);
|
|
12
17
|
const linkEvents = useMemo(() => ({
|
|
13
18
|
onKeyDown: e => {
|
|
14
19
|
if (e.key === " ") {
|
|
15
20
|
e.preventDefault();
|
|
16
21
|
const linkEl = e.target;
|
|
22
|
+
linkEl.dataset.spaceDown = "1";
|
|
17
23
|
linkEl.classList.add("zen-menu-button__action--active");
|
|
18
24
|
}
|
|
19
25
|
},
|
|
@@ -22,7 +28,10 @@ export const MenuButton = ({ id, onClick, hasChildren, disabled, icon, name, lin
|
|
|
22
28
|
e.preventDefault();
|
|
23
29
|
const linkEl = e.target;
|
|
24
30
|
linkEl.classList.remove("zen-menu-button__action--active");
|
|
25
|
-
linkEl.
|
|
31
|
+
if (linkEl.dataset.spaceDown) {
|
|
32
|
+
delete linkEl.dataset.spaceDown;
|
|
33
|
+
linkEl.click();
|
|
34
|
+
}
|
|
26
35
|
}
|
|
27
36
|
}
|
|
28
37
|
}), []);
|
|
@@ -40,13 +49,13 @@ export const MenuButton = ({ id, onClick, hasChildren, disabled, icon, name, lin
|
|
|
40
49
|
createElement(icon, {
|
|
41
50
|
size: isDrive ? "huge" : "large",
|
|
42
51
|
className: classNames(["zen-caption__pre-content", "zen-menu-button__icon"])
|
|
43
|
-
}), _jsx("span", { className: "zen-menu-button__action-text", children: name }), !!hasChildren && (_jsx(
|
|
52
|
+
}), _jsx("span", { className: "zen-menu-button__action-text", children: name }), !!hasChildren && (_jsx(ChevronIcon, { size: isDrive ? "huge" : "large", className: classNames(["zen-caption__pre-content", "zen-menu-button__more-icon"]) }))] }));
|
|
44
53
|
const linkTemplate = (_jsxs("a", Object.assign({ "data-id": id, role: "menuitem", className: classNames([
|
|
45
54
|
"zen-menu-button__action",
|
|
46
55
|
"zen-caption",
|
|
47
56
|
disabled ? "zen-menu-button__action--disabled" : "",
|
|
48
57
|
driveMenuButtonActionClasses || ""
|
|
49
|
-
]), href: disabled ? undefined : link, "aria-disabled": disabled, onClick: onClickHandler, target: target, rel: rel }, linkEvents, { children: [!!icon &&
|
|
58
|
+
]), href: disabled || !isSafeHref(link) ? undefined : link, "aria-disabled": disabled, onClick: onClickHandler, target: target, rel: getSafeRel(rel, target) }, linkEvents, { children: [!!icon &&
|
|
50
59
|
createElement(icon, {
|
|
51
60
|
size: isDrive ? "huge" : "large",
|
|
52
61
|
className: "zen-caption__pre-content"
|
|
@@ -2,6 +2,7 @@ import { FC, ReactElement } from "react";
|
|
|
2
2
|
import { IMenuButton } from "./menuButton";
|
|
3
3
|
import "./menuItem.less";
|
|
4
4
|
import { TAlignment } from "../../absolute/absolute";
|
|
5
|
+
export { isMenuItem } from "../utils/isMenuItem";
|
|
5
6
|
interface IMenuItemInternal {
|
|
6
7
|
isMobile?: boolean;
|
|
7
8
|
setIsOpen?: (v: boolean) => void;
|
|
@@ -12,6 +13,4 @@ export interface IMenuControlledItem extends IMenuItem {
|
|
|
12
13
|
export interface IMenuItem extends IMenuButton {
|
|
13
14
|
alignment?: TAlignment;
|
|
14
15
|
}
|
|
15
|
-
export declare const isMenuItem: (element: ReactElement | undefined) => boolean;
|
|
16
16
|
export declare const MenuItem: FC<Omit<IMenuItem & IMenuControlledItem & IMenuItemInternal, "hasChildren">>;
|
|
17
|
-
export {};
|
|
@@ -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
|
+
};
|