@elliemae/ds-menu-button 3.39.0-rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. package/dist/cjs/DSMenuButton.js +50 -0
  2. package/dist/cjs/DSMenuButton.js.map +7 -0
  3. package/dist/cjs/DSMenuButtonCTX.js +38 -0
  4. package/dist/cjs/DSMenuButtonCTX.js.map +7 -0
  5. package/dist/cjs/config/useMenuButton.js +55 -0
  6. package/dist/cjs/config/useMenuButton.js.map +7 -0
  7. package/dist/cjs/config/useValidateProps.js +40 -0
  8. package/dist/cjs/config/useValidateProps.js.map +7 -0
  9. package/dist/cjs/constants/index.js +43 -0
  10. package/dist/cjs/constants/index.js.map +7 -0
  11. package/dist/cjs/index.js +41 -0
  12. package/dist/cjs/index.js.map +7 -0
  13. package/dist/cjs/package.json +7 -0
  14. package/dist/cjs/parts/ItemFactory.js +66 -0
  15. package/dist/cjs/parts/ItemFactory.js.map +7 -0
  16. package/dist/cjs/parts/MenuButtonContent.js +157 -0
  17. package/dist/cjs/parts/MenuButtonContent.js.map +7 -0
  18. package/dist/cjs/parts/MenuItem.js +244 -0
  19. package/dist/cjs/parts/MenuItem.js.map +7 -0
  20. package/dist/cjs/parts/SubMenu.js +126 -0
  21. package/dist/cjs/parts/SubMenu.js.map +7 -0
  22. package/dist/cjs/react-desc-prop-types.js +64 -0
  23. package/dist/cjs/react-desc-prop-types.js.map +7 -0
  24. package/dist/cjs/styled.js +128 -0
  25. package/dist/cjs/styled.js.map +7 -0
  26. package/dist/esm/DSMenuButton.js +20 -0
  27. package/dist/esm/DSMenuButton.js.map +7 -0
  28. package/dist/esm/DSMenuButtonCTX.js +8 -0
  29. package/dist/esm/DSMenuButtonCTX.js.map +7 -0
  30. package/dist/esm/config/useMenuButton.js +25 -0
  31. package/dist/esm/config/useMenuButton.js.map +7 -0
  32. package/dist/esm/config/useValidateProps.js +10 -0
  33. package/dist/esm/config/useValidateProps.js.map +7 -0
  34. package/dist/esm/constants/index.js +13 -0
  35. package/dist/esm/constants/index.js.map +7 -0
  36. package/dist/esm/index.js +11 -0
  37. package/dist/esm/index.js.map +7 -0
  38. package/dist/esm/package.json +7 -0
  39. package/dist/esm/parts/ItemFactory.js +36 -0
  40. package/dist/esm/parts/ItemFactory.js.map +7 -0
  41. package/dist/esm/parts/MenuButtonContent.js +127 -0
  42. package/dist/esm/parts/MenuButtonContent.js.map +7 -0
  43. package/dist/esm/parts/MenuItem.js +227 -0
  44. package/dist/esm/parts/MenuItem.js.map +7 -0
  45. package/dist/esm/parts/SubMenu.js +96 -0
  46. package/dist/esm/parts/SubMenu.js.map +7 -0
  47. package/dist/esm/react-desc-prop-types.js +34 -0
  48. package/dist/esm/react-desc-prop-types.js.map +7 -0
  49. package/dist/esm/styled.js +98 -0
  50. package/dist/esm/styled.js.map +7 -0
  51. package/dist/types/DSMenuButton.d.ts +7 -0
  52. package/dist/types/DSMenuButtonCTX.d.ts +11 -0
  53. package/dist/types/config/useMenuButton.d.ts +9 -0
  54. package/dist/types/config/useValidateProps.d.ts +3 -0
  55. package/dist/types/constants/index.d.ts +5 -0
  56. package/dist/types/index.d.ts +3 -0
  57. package/dist/types/parts/ItemFactory.d.ts +14 -0
  58. package/dist/types/parts/MenuButtonContent.d.ts +1 -0
  59. package/dist/types/parts/MenuItem.d.ts +21 -0
  60. package/dist/types/parts/SubMenu.d.ts +14 -0
  61. package/dist/types/react-desc-prop-types.d.ts +51 -0
  62. package/dist/types/styled.d.ts +15 -0
  63. package/package.json +76 -0
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { describe } from "@elliemae/ds-props-helpers";
4
+ import { DSDMenuButtonPropTypesSchema } from "./react-desc-prop-types.js";
5
+ import { useDSMenuButton } from "./config/useMenuButton.js";
6
+ import { DSMenuButtonName } from "./constants/index.js";
7
+ import { MenuButtonContext } from "./DSMenuButtonCTX.js";
8
+ import { MenuButtonContent } from "./parts/MenuButtonContent.js";
9
+ const DSMenuButton = (props) => {
10
+ const ctx = useDSMenuButton(props);
11
+ return /* @__PURE__ */ jsx(MenuButtonContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(MenuButtonContent, {}) });
12
+ };
13
+ DSMenuButton.displayName = DSMenuButtonName;
14
+ const DSMenuButtonWithSchema = describe(DSMenuButton);
15
+ DSMenuButtonWithSchema.propTypes = DSDMenuButtonPropTypesSchema;
16
+ export {
17
+ DSMenuButton,
18
+ DSMenuButtonWithSchema
19
+ };
20
+ //# sourceMappingURL=DSMenuButton.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSMenuButton.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport { describe } from '@elliemae/ds-props-helpers';\nimport { type MenuButtonT, DSDMenuButtonPropTypesSchema } from './react-desc-prop-types.js';\nimport { useDSMenuButton } from './config/useMenuButton.js';\nimport { DSMenuButtonName } from './constants/index.js';\nimport { MenuButtonContext } from './DSMenuButtonCTX.js';\nimport { MenuButtonContent } from './parts/MenuButtonContent.js';\n\nconst DSMenuButton = <T extends object = object>(props: MenuButtonT.Props<T>) => {\n const ctx = useDSMenuButton(props);\n\n return (\n <MenuButtonContext.Provider value={ctx}>\n <MenuButtonContent />\n </MenuButtonContext.Provider>\n );\n};\n\nDSMenuButton.displayName = DSMenuButtonName;\nconst DSMenuButtonWithSchema = describe(DSMenuButton);\nDSMenuButtonWithSchema.propTypes = DSDMenuButtonPropTypesSchema;\n\nexport { DSMenuButton, DSMenuButtonWithSchema };\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACajB;AAZN,SAAS,gBAAgB;AACzB,SAA2B,oCAAoC;AAC/D,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAClC,SAAS,yBAAyB;AAElC,MAAM,eAAe,CAA4B,UAAgC;AAC/E,QAAM,MAAM,gBAAgB,KAAK;AAEjC,SACE,oBAAC,kBAAkB,UAAlB,EAA2B,OAAO,KACjC,8BAAC,qBAAkB,GACrB;AAEJ;AAEA,aAAa,cAAc;AAC3B,MAAM,yBAAyB,SAAS,YAAY;AACpD,uBAAuB,YAAY;",
6
+ "names": []
7
+ }
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ import React2 from "react";
3
+ const defaultContext = {};
4
+ const MenuButtonContext = React2.createContext(defaultContext);
5
+ export {
6
+ MenuButtonContext
7
+ };
8
+ //# sourceMappingURL=DSMenuButtonCTX.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/DSMenuButtonCTX.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import React from 'react';\nimport type { MenuButtonT } from './react-desc-prop-types.js';\ninterface MenuButtonContextProps<T extends object = object> {\n focusedOption: string | null;\n setFocusedOption: React.Dispatch<React.SetStateAction<string | null>>;\n selectedKeys: string[];\n onSelectionChange: (selectedKeys: string[], parentId: string, item: MenuButtonT.Item) => void;\n propsWithDefault: MenuButtonT.InternalProps<T>;\n}\n\nconst defaultContext = {} as MenuButtonContextProps<object>;\n\nexport const MenuButtonContext = React.createContext(defaultContext);\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,OAAOA,YAAW;AAUlB,MAAM,iBAAiB,CAAC;AAEjB,MAAM,oBAAoBA,OAAM,cAAc,cAAc;",
6
+ "names": ["React"]
7
+ }
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+ import { useMemo, useState } from "react";
3
+ import { useMemoMergePropsWithDefault } from "@elliemae/ds-props-helpers";
4
+ import { DSDMenuButtonPropTypes, defaultProps } from "../react-desc-prop-types.js";
5
+ import { useValidateProps } from "./useValidateProps.js";
6
+ const useDSMenuButton = (propsFromUser) => {
7
+ const propsWithDefault = useMemoMergePropsWithDefault(propsFromUser, defaultProps);
8
+ useValidateProps(propsWithDefault, DSDMenuButtonPropTypes);
9
+ const { selectedKeys, onSelectionChange } = propsWithDefault;
10
+ const [focusedOption, setFocusedOption] = useState(null);
11
+ return useMemo(
12
+ () => ({
13
+ propsWithDefault,
14
+ focusedOption,
15
+ setFocusedOption,
16
+ selectedKeys,
17
+ onSelectionChange
18
+ }),
19
+ [focusedOption, propsWithDefault, selectedKeys, onSelectionChange]
20
+ );
21
+ };
22
+ export {
23
+ useDSMenuButton
24
+ };
25
+ //# sourceMappingURL=useMenuButton.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/useMenuButton.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useMemo, useState } from 'react';\nimport { useMemoMergePropsWithDefault } from '@elliemae/ds-props-helpers';\nimport { type MenuButtonT, DSDMenuButtonPropTypes, defaultProps } from '../react-desc-prop-types.js';\nimport { useValidateProps } from './useValidateProps.js';\n\nexport const useDSMenuButton = <T extends object = object>(propsFromUser: MenuButtonT.Props<T>) => {\n // =============================================================================\n // MERGE WITH DEFAULT AND VALIDATE PROPS\n // =============================================================================\n const propsWithDefault = useMemoMergePropsWithDefault<MenuButtonT.InternalProps<T>>(propsFromUser, defaultProps);\n useValidateProps(propsWithDefault, DSDMenuButtonPropTypes);\n\n // =============================================================================\n // AD HOC PER COMPONENT LOGIC\n // =============================================================================\n\n const { selectedKeys, onSelectionChange } = propsWithDefault;\n const [focusedOption, setFocusedOption] = useState<string | null>(null);\n\n return useMemo(\n () => ({\n propsWithDefault,\n focusedOption,\n setFocusedOption,\n selectedKeys,\n onSelectionChange,\n }),\n [focusedOption, propsWithDefault, selectedKeys, onSelectionChange],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,SAAS,gBAAgB;AAClC,SAAS,oCAAoC;AAC7C,SAA2B,wBAAwB,oBAAoB;AACvE,SAAS,wBAAwB;AAE1B,MAAM,kBAAkB,CAA4B,kBAAwC;AAIjG,QAAM,mBAAmB,6BAA2D,eAAe,YAAY;AAC/G,mBAAiB,kBAAkB,sBAAsB;AAMzD,QAAM,EAAE,cAAc,kBAAkB,IAAI;AAC5C,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAwB,IAAI;AAEtE,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,eAAe,kBAAkB,cAAc,iBAAiB;AAAA,EACnE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { useValidateTypescriptPropTypes } from "@elliemae/ds-props-helpers";
3
+ import { DSMenuButtonName } from "../constants/index.js";
4
+ const useValidateProps = (props, propTypes) => {
5
+ useValidateTypescriptPropTypes(props, propTypes, DSMenuButtonName);
6
+ };
7
+ export {
8
+ useValidateProps
9
+ };
10
+ //# sourceMappingURL=useValidateProps.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/config/useValidateProps.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useValidateTypescriptPropTypes } from '@elliemae/ds-props-helpers';\nimport type { WeakValidationMap } from 'react';\nimport { type MenuButtonT } from '../react-desc-prop-types.js';\nimport { DSMenuButtonName } from '../constants/index.js';\n\nexport const useValidateProps = <T extends object = object>(\n props: MenuButtonT.InternalProps<T>,\n propTypes: WeakValidationMap<unknown>,\n): void => {\n // we validate the \"required if\" via 'isRequiredIf from our custom PropTypes\n useValidateTypescriptPropTypes(props, propTypes, DSMenuButtonName);\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,sCAAsC;AAG/C,SAAS,wBAAwB;AAE1B,MAAM,mBAAmB,CAC9B,OACA,cACS;AAET,iCAA+B,OAAO,WAAW,gBAAgB;AACnE;",
6
+ "names": []
7
+ }
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ import { slotObjectToDataTestIds } from "@elliemae/ds-system";
3
+ const DSMenuButtonName = "DSMenuButton";
4
+ const MENU_BUTTON_SLOTS = {
5
+ root: "root"
6
+ };
7
+ const MENU_BUTTON_DATATEST_ID = slotObjectToDataTestIds(DSMenuButtonName, MENU_BUTTON_SLOTS);
8
+ export {
9
+ DSMenuButtonName,
10
+ MENU_BUTTON_DATATEST_ID,
11
+ MENU_BUTTON_SLOTS
12
+ };
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/constants/index.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { slotObjectToDataTestIds } from '@elliemae/ds-system';\n\nexport const DSMenuButtonName = 'DSMenuButton';\n\n// we are giving \"component_name_slots\" to avoid errors on duplicate exports variables in aggregators\nexport const MENU_BUTTON_SLOTS = {\n root: 'root',\n} as const;\n\n// we are giving \"component_name_data_testid\" to avoid errors on duplicate exports variables in aggregators\nexport const MENU_BUTTON_DATATEST_ID = slotObjectToDataTestIds(DSMenuButtonName, MENU_BUTTON_SLOTS);\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,+BAA+B;AAEjC,MAAM,mBAAmB;AAGzB,MAAM,oBAAoB;AAAA,EAC/B,MAAM;AACR;AAGO,MAAM,0BAA0B,wBAAwB,kBAAkB,iBAAiB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ import * as React from "react";
2
+ import { DSMenuButton, DSMenuButtonWithSchema } from "./DSMenuButton.js";
3
+ import { DSMenuButtonName, MENU_BUTTON_DATATEST_ID, MENU_BUTTON_SLOTS } from "./constants/index.js";
4
+ export {
5
+ DSMenuButton,
6
+ DSMenuButtonName,
7
+ DSMenuButtonWithSchema,
8
+ MENU_BUTTON_DATATEST_ID,
9
+ MENU_BUTTON_SLOTS
10
+ };
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../scripts/build/transpile/react-shim.js", "../../src/index.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "export { DSMenuButton, DSMenuButtonWithSchema } from './DSMenuButton.js';\nexport { type MenuButtonT } from './react-desc-prop-types.js';\nexport { DSMenuButtonName, MENU_BUTTON_DATATEST_ID, MENU_BUTTON_SLOTS } from './constants/index.js';\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,cAAc,8BAA8B;AAErD,SAAS,kBAAkB,yBAAyB,yBAAyB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "type": "module",
3
+ "sideEffects": [
4
+ "*.css",
5
+ "*.scss"
6
+ ]
7
+ }
@@ -0,0 +1,36 @@
1
+ import * as React from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { MenuItem, Section, Separator } from "./MenuItem.js";
4
+ const ItemFactory = ({
5
+ item,
6
+ innerRef,
7
+ onFocus,
8
+ tabIndex,
9
+ level,
10
+ selectionMode,
11
+ parentId
12
+ }) => {
13
+ if (item.type === "separator") {
14
+ return /* @__PURE__ */ jsx(Separator, {});
15
+ }
16
+ if (item.type === "section") {
17
+ return /* @__PURE__ */ jsx(Section, { item });
18
+ }
19
+ return /* @__PURE__ */ jsx(
20
+ MenuItem,
21
+ {
22
+ item,
23
+ innerRef,
24
+ onFocus,
25
+ tabIndex,
26
+ level,
27
+ parentId,
28
+ selectionMode
29
+ },
30
+ item.dsId
31
+ );
32
+ };
33
+ export {
34
+ ItemFactory
35
+ };
36
+ //# sourceMappingURL=ItemFactory.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/ItemFactory.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable import/no-cycle */\n/* eslint-disable arrow-body-style */\nimport React from 'react';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { MenuItem, Section, Separator } from './MenuItem.js';\n\nimport type { MenuButtonT } from '../react-desc-prop-types.js';\ninterface ItemFactoryProps {\n item: MenuButtonT.Item;\n level: number;\n selectionMode?: 'single' | 'multiple';\n parentId?: string;\n tabIndex: TypescriptHelpersT.WCAGTabIndex;\n onFocus: React.FocusEventHandler;\n innerRef: TypescriptHelpersT.AnyRef<HTMLElement>;\n}\n\nexport const ItemFactory: React.FC<ItemFactoryProps> = ({\n item,\n innerRef,\n onFocus,\n tabIndex,\n level,\n selectionMode,\n parentId,\n}) => {\n if (item.type === 'separator') {\n return <Separator />;\n }\n if (item.type === 'section') {\n return <Section item={item} />;\n }\n return (\n <MenuItem\n key={item.dsId}\n item={item}\n innerRef={innerRef}\n onFocus={onFocus}\n tabIndex={tabIndex}\n level={level}\n parentId={parentId}\n selectionMode={selectionMode}\n />\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;AC2BZ;AAvBX,SAAS,UAAU,SAAS,iBAAiB;AAatC,MAAM,cAA0C,CAAC;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,MAAI,KAAK,SAAS,aAAa;AAC7B,WAAO,oBAAC,aAAU;AAAA,EACpB;AACA,MAAI,KAAK,SAAS,WAAW;AAC3B,WAAO,oBAAC,WAAQ,MAAY;AAAA,EAC9B;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MAEC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IAPK,KAAK;AAAA,EAQZ;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,127 @@
1
+ import * as React from "react";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import React2, { useState, useMemo, useCallback, useContext, useRef } from "react";
4
+ import { useGetGlobalAttributes, useGetXstyledProps } from "@elliemae/ds-props-helpers";
5
+ import { SubMenu } from "./SubMenu.js";
6
+ import { MenuButtonContext } from "../DSMenuButtonCTX.js";
7
+ import { StyledMenuButtonWrapper } from "../styled.js";
8
+ function useOnClickOutside(ref, cb) {
9
+ React2.useEffect(() => {
10
+ const listener = (event) => {
11
+ if (!ref?.current || ref?.current?.contains?.(event.target)) {
12
+ return;
13
+ }
14
+ cb(event);
15
+ };
16
+ document.addEventListener("mousedown", listener);
17
+ document.addEventListener("touchstart", listener);
18
+ return () => {
19
+ document.removeEventListener("mousedown", listener);
20
+ document.removeEventListener("touchstart", listener);
21
+ };
22
+ }, [ref, cb]);
23
+ }
24
+ const MenuButtonContent = () => {
25
+ const [referenceElement, setReferenceElement] = useState(null);
26
+ const [isOpen, setIsOpen] = useState(false);
27
+ const { setFocusedOption, propsWithDefault } = useContext(MenuButtonContext);
28
+ const { items, TriggerElement, selectionMode, triggerElementProps, menuMinWidth } = propsWithDefault;
29
+ const globalProps = useGetGlobalAttributes(propsWithDefault);
30
+ const xstyledProps = useGetXstyledProps(propsWithDefault);
31
+ const firstItem = useMemo(() => {
32
+ const first = items.find((item) => item.type !== "separator");
33
+ if (first && first.type === "section") {
34
+ return first.childrens?.find((item) => item.type !== "separator");
35
+ }
36
+ return first;
37
+ }, [items]);
38
+ const handleOnKeyDown = useCallback(
39
+ (event) => {
40
+ if (event.key === "Escape") {
41
+ referenceElement?.focus();
42
+ }
43
+ if (event.key === "ArrowDown" && isOpen) {
44
+ event.preventDefault();
45
+ setFocusedOption(firstItem?.dsId || "");
46
+ }
47
+ if (event.key === "ArrowUp" && isOpen) {
48
+ event.preventDefault();
49
+ setFocusedOption(items[items.length - 1].dsId);
50
+ }
51
+ if (event.key === "Enter" && isOpen) {
52
+ event.preventDefault();
53
+ setIsOpen(false);
54
+ referenceElement?.focus();
55
+ } else if ((event.key === "Enter" || event.key === " ") && !isOpen && firstItem) {
56
+ setFocusedOption(firstItem?.dsId);
57
+ }
58
+ },
59
+ [firstItem, items, isOpen, referenceElement, setFocusedOption]
60
+ );
61
+ const handleOnTriggerOnKeyDown = useCallback(
62
+ (e) => {
63
+ if (e.key === "Enter" || e.key === " ") {
64
+ e.preventDefault();
65
+ setFocusedOption(items[0]?.dsId);
66
+ }
67
+ },
68
+ [items, setFocusedOption]
69
+ );
70
+ const handleOnClick = useCallback(() => {
71
+ setIsOpen(!isOpen);
72
+ }, [isOpen]);
73
+ const attributes = useMemo(
74
+ () => ({
75
+ "aria-haspopup": "true",
76
+ "aria-expanded": isOpen
77
+ }),
78
+ [isOpen]
79
+ );
80
+ const listeners = useMemo(
81
+ () => ({
82
+ onKeyDown: handleOnTriggerOnKeyDown
83
+ }),
84
+ [handleOnTriggerOnKeyDown]
85
+ );
86
+ const containerRef = useRef(null);
87
+ useOnClickOutside(containerRef, () => setIsOpen(false));
88
+ return /* @__PURE__ */ jsxs(
89
+ StyledMenuButtonWrapper,
90
+ {
91
+ onClick: handleOnClick,
92
+ onKeyDown: handleOnKeyDown,
93
+ innerRef: containerRef,
94
+ ...globalProps,
95
+ ...xstyledProps,
96
+ children: [
97
+ /* @__PURE__ */ jsx(
98
+ TriggerElement,
99
+ {
100
+ isOpen,
101
+ innerRef: setReferenceElement,
102
+ setIsOpen,
103
+ attributes,
104
+ listeners,
105
+ triggerElementProps
106
+ }
107
+ ),
108
+ isOpen && /* @__PURE__ */ jsx(
109
+ SubMenu,
110
+ {
111
+ level: 1,
112
+ items,
113
+ showSubMenu: isOpen,
114
+ setShowSubMenu: setIsOpen,
115
+ referenceElement,
116
+ selectionMode,
117
+ minWidth: menuMinWidth
118
+ }
119
+ )
120
+ ]
121
+ }
122
+ );
123
+ };
124
+ export {
125
+ MenuButtonContent
126
+ };
127
+ //# sourceMappingURL=MenuButtonContent.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/MenuButtonContent.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable complexity */\nimport React, { useState, useMemo, useCallback, useContext, useRef } from 'react';\nimport { useGetGlobalAttributes, useGetXstyledProps } from '@elliemae/ds-props-helpers';\nimport { SubMenu } from './SubMenu.js';\nimport { MenuButtonContext } from '../DSMenuButtonCTX.js';\n\nimport { StyledMenuButtonWrapper } from '../styled.js';\nfunction useOnClickOutside(ref: React.RefObject<HTMLElement>, cb: (event: MouseEvent | TouchEvent) => void) {\n React.useEffect(() => {\n const listener = (event: MouseEvent | TouchEvent) => {\n // Do nothing if clicking ref's element or descendent elements\n if (!ref?.current || ref?.current?.contains?.(event.target as Node)) {\n return;\n }\n cb(event);\n };\n document.addEventListener('mousedown', listener);\n document.addEventListener('touchstart', listener);\n return () => {\n document.removeEventListener('mousedown', listener);\n document.removeEventListener('touchstart', listener);\n };\n }, [ref, cb]);\n}\n\nexport const MenuButtonContent = () => {\n const [referenceElement, setReferenceElement] = useState<HTMLElement | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const { setFocusedOption, propsWithDefault } = useContext(MenuButtonContext);\n\n const { items, TriggerElement, selectionMode, triggerElementProps, menuMinWidth } = propsWithDefault;\n const globalProps = useGetGlobalAttributes(propsWithDefault);\n const xstyledProps = useGetXstyledProps(propsWithDefault);\n\n const firstItem = useMemo(() => {\n const first = items.find((item) => item.type !== 'separator');\n if (first && first.type === 'section') {\n return first.childrens?.find((item) => item.type !== 'separator');\n }\n return first;\n }, [items]);\n\n const handleOnKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === 'Escape') {\n referenceElement?.focus();\n }\n if (event.key === 'ArrowDown' && isOpen) {\n event.preventDefault();\n setFocusedOption(firstItem?.dsId || '');\n }\n if (event.key === 'ArrowUp' && isOpen) {\n event.preventDefault();\n setFocusedOption(items[items.length - 1].dsId);\n }\n\n // Enter to close the menu and focus the trigger element\n if (event.key === 'Enter' && isOpen) {\n event.preventDefault();\n setIsOpen(false);\n referenceElement?.focus();\n } else if ((event.key === 'Enter' || event.key === ' ') && !isOpen && firstItem) {\n setFocusedOption(firstItem?.dsId);\n }\n },\n [firstItem, items, isOpen, referenceElement, setFocusedOption],\n );\n\n const handleOnTriggerOnKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setFocusedOption(items[0]?.dsId);\n }\n },\n [items, setFocusedOption],\n );\n\n const handleOnClick = useCallback(() => {\n setIsOpen(!isOpen);\n }, [isOpen]);\n\n const attributes = useMemo(\n () => ({\n 'aria-haspopup': 'true',\n 'aria-expanded': isOpen,\n }),\n [isOpen],\n );\n\n const listeners = useMemo(\n () => ({\n onKeyDown: handleOnTriggerOnKeyDown,\n }),\n [handleOnTriggerOnKeyDown],\n );\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n useOnClickOutside(containerRef, () => setIsOpen(false));\n\n return (\n <StyledMenuButtonWrapper\n onClick={handleOnClick}\n onKeyDown={handleOnKeyDown}\n innerRef={containerRef}\n {...globalProps}\n {...xstyledProps}\n >\n <TriggerElement\n isOpen={isOpen}\n innerRef={setReferenceElement}\n setIsOpen={setIsOpen}\n attributes={attributes}\n listeners={listeners}\n triggerElementProps={triggerElementProps}\n />\n {isOpen && (\n <SubMenu\n level={1}\n items={items}\n showSubMenu={isOpen}\n setShowSubMenu={setIsOpen}\n referenceElement={referenceElement}\n selectionMode={selectionMode}\n minWidth={menuMinWidth}\n />\n )}\n </StyledMenuButtonWrapper>\n );\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React"]
7
+ }
@@ -0,0 +1,227 @@
1
+ import * as React from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import React2, { useState, useCallback, useMemo } from "react";
4
+ import {
5
+ TriangleUpSmall,
6
+ CheckmarkXsmall,
7
+ TriangleDownSmall,
8
+ ChevronSmallDown,
9
+ ChevronSmallRight
10
+ } from "@elliemae/ds-icons";
11
+ import { mergeRefs } from "@elliemae/ds-system";
12
+ import { Grid } from "@elliemae/ds-grid";
13
+ import { MenuButtonContext } from "../DSMenuButtonCTX.js";
14
+ import {
15
+ StyledMenuItem,
16
+ StyledMenuItemContent,
17
+ StyledLeftContent,
18
+ StyledRightContent,
19
+ StyledSeparator,
20
+ StyledSection
21
+ } from "../styled.js";
22
+ import { SubMenu } from "./SubMenu.js";
23
+ const MenuItemAddon = React2.memo(({ level, isOpen }) => {
24
+ if (level === 0)
25
+ return isOpen ? /* @__PURE__ */ jsx(TriangleUpSmall, { color: ["brand-primary", "600"] }) : /* @__PURE__ */ jsx(TriangleDownSmall, { color: ["brand-primary", "600"] });
26
+ return isOpen ? /* @__PURE__ */ jsx(ChevronSmallDown, { size: "m", color: ["brand-primary", "600"] }) : /* @__PURE__ */ jsx(ChevronSmallRight, { size: "m", color: ["brand-primary", "600"] });
27
+ });
28
+ const MenuItem = ({
29
+ innerRef,
30
+ tabIndex,
31
+ onFocus,
32
+ selectionMode,
33
+ item,
34
+ level,
35
+ parentId,
36
+ isVertical
37
+ }) => {
38
+ const {
39
+ setFocusedOption,
40
+ focusedOption,
41
+ selectedKeys,
42
+ onSelectionChange,
43
+ propsWithDefault: { ItemRenderer }
44
+ } = React2.useContext(MenuButtonContext);
45
+ const listRef = React2.useRef(null);
46
+ const [showSubMenu, setShowSubMenu] = useState(false);
47
+ const [referenceElement, setReferenceElement] = React2.useState(null);
48
+ const itemRef = useCallback(
49
+ (node) => {
50
+ if (node !== null) {
51
+ if (focusedOption === item.dsId) node.focus();
52
+ }
53
+ return node;
54
+ },
55
+ [focusedOption, item.dsId]
56
+ );
57
+ const selectionLogic = useCallback(() => {
58
+ if (selectionMode === "single") {
59
+ const newValue = item.dsId === selectedKeys[0] ? [] : [item.dsId];
60
+ onSelectionChange(newValue, parentId || "root", item);
61
+ }
62
+ if (selectionMode === "multiple") {
63
+ const newValue = selectedKeys.includes(item.dsId) ? selectedKeys.filter((key) => key !== item.dsId) : [...selectedKeys, item.dsId];
64
+ onSelectionChange(newValue, parentId || "root", item);
65
+ }
66
+ }, [item, onSelectionChange, parentId, selectedKeys, selectionMode]);
67
+ const handleOnClick = useCallback(
68
+ (e) => {
69
+ if (selectionMode === "multiple") {
70
+ e.stopPropagation();
71
+ }
72
+ selectionLogic();
73
+ },
74
+ [selectionLogic, selectionMode]
75
+ );
76
+ const onItemKeyDown = useCallback(
77
+ (event) => {
78
+ if (event.key === "Enter" || event.key === " ") {
79
+ event.preventDefault();
80
+ selectionLogic();
81
+ }
82
+ if ((event.key === "ArrowDown" && level === 0 || event.key === "ArrowRight" && level !== 0) && item.subitems) {
83
+ event.preventDefault();
84
+ event.stopPropagation();
85
+ setShowSubMenu(true);
86
+ setFocusedOption(item.subitems[0].dsId);
87
+ }
88
+ if (event.key === "ArrowLeft" && level >= 2) {
89
+ event.preventDefault();
90
+ event.stopPropagation();
91
+ if (parentId) setFocusedOption(parentId);
92
+ }
93
+ if (event.key === "Escape" && level > 0) {
94
+ if (parentId !== void 0) {
95
+ setFocusedOption(parentId);
96
+ }
97
+ }
98
+ },
99
+ [level, item.subitems, selectionLogic, setFocusedOption, parentId]
100
+ );
101
+ const handleOnLIKeyDown = useCallback(
102
+ (e) => {
103
+ if (e.key === "Enter") {
104
+ setShowSubMenu(false);
105
+ if (level === 0) {
106
+ setFocusedOption(item.dsId);
107
+ }
108
+ }
109
+ },
110
+ [item.dsId, level, setFocusedOption]
111
+ );
112
+ const handleOnMouseEnter = useCallback(() => {
113
+ setShowSubMenu(true);
114
+ setFocusedOption(item.dsId);
115
+ }, [item.dsId, setFocusedOption]);
116
+ const handleOnMouseLeave = useCallback(() => {
117
+ setShowSubMenu(false);
118
+ }, []);
119
+ const ariaExpanded = useMemo(() => {
120
+ if (item.subitems) {
121
+ return showSubMenu ? "true" : "false";
122
+ }
123
+ return void 0;
124
+ }, [item.subitems, showSubMenu]);
125
+ const role = useMemo(() => {
126
+ if (selectionMode === "single") {
127
+ return "menuitemradio";
128
+ }
129
+ if (selectionMode === "multiple") {
130
+ return "menuitemcheckbox";
131
+ }
132
+ return "menuitem";
133
+ }, [selectionMode]);
134
+ const ariaChecked = useMemo(() => {
135
+ if (selectionMode === "multiple" || selectionMode === "single") {
136
+ return selectedKeys.includes(item.dsId) ? "true" : "false";
137
+ }
138
+ return void 0;
139
+ }, [item.dsId, selectionMode, selectedKeys]);
140
+ return /* @__PURE__ */ jsxs(
141
+ StyledMenuItem,
142
+ {
143
+ role: "none",
144
+ innerRef: listRef,
145
+ onMouseEnter: handleOnMouseEnter,
146
+ onMouseLeave: handleOnMouseLeave,
147
+ onKeyDown: handleOnLIKeyDown,
148
+ isOpen: showSubMenu,
149
+ level,
150
+ isVertical,
151
+ children: [
152
+ /* @__PURE__ */ jsx(
153
+ StyledMenuItemContent,
154
+ {
155
+ role,
156
+ "aria-checked": ariaChecked,
157
+ "aria-haspopup": item.subitems ? "true" : "false",
158
+ "aria-expanded": ariaExpanded,
159
+ innerRef: mergeRefs(innerRef, itemRef, setReferenceElement),
160
+ onKeyDown: onItemKeyDown,
161
+ onClick: handleOnClick,
162
+ hasChildren: item.subitems !== void 0,
163
+ onFocus,
164
+ tabIndex,
165
+ children: ItemRenderer ? /* @__PURE__ */ jsx(ItemRenderer, { item, isSelected: selectedKeys.includes(item.dsId) }) : /* @__PURE__ */ jsx(
166
+ MenuItemContent,
167
+ {
168
+ item,
169
+ selectionMode,
170
+ selectedKeys,
171
+ showSubMenu,
172
+ level
173
+ }
174
+ )
175
+ }
176
+ ),
177
+ item.subitems && showSubMenu && /* @__PURE__ */ jsx(
178
+ SubMenu,
179
+ {
180
+ level: level + 1,
181
+ items: item.subitems,
182
+ showSubMenu,
183
+ setShowSubMenu,
184
+ referenceElement,
185
+ parentId: item.dsId,
186
+ selectionMode: item.selectionMode,
187
+ minWidth: item.minWidth
188
+ }
189
+ )
190
+ ]
191
+ }
192
+ );
193
+ };
194
+ const MenuItemContent = React2.memo(
195
+ ({
196
+ item,
197
+ selectionMode,
198
+ selectedKeys,
199
+ showSubMenu,
200
+ level
201
+ }) => /* @__PURE__ */ jsxs(Fragment, { children: [
202
+ /* @__PURE__ */ jsxs(StyledLeftContent, { children: [
203
+ /* @__PURE__ */ jsx(SelectionAddon, { selectionMode, item, selectedKeys }),
204
+ /* @__PURE__ */ jsx("span", { style: { lineHeight: 1.15 }, children: item.label })
205
+ ] }),
206
+ /* @__PURE__ */ jsx(StyledRightContent, { children: item.subitems ? /* @__PURE__ */ jsx(MenuItemAddon, { isOpen: showSubMenu, level }) : null })
207
+ ] })
208
+ );
209
+ const SelectionAddon = ({
210
+ item,
211
+ selectedKeys,
212
+ selectionMode
213
+ }) => {
214
+ if (selectionMode) {
215
+ return selectedKeys.includes(item.dsId) ? /* @__PURE__ */ jsx(Grid, { children: /* @__PURE__ */ jsx(CheckmarkXsmall, { size: "m", color: ["brand-primary", "600"] }) }) : /* @__PURE__ */ jsx("div", { style: { width: "24px" } });
216
+ }
217
+ return null;
218
+ };
219
+ const Separator = () => /* @__PURE__ */ jsx("li", { role: "none", style: { padding: "0px 16px" }, children: /* @__PURE__ */ jsx(StyledSeparator, { role: "separator" }) });
220
+ const Section = ({ item }) => /* @__PURE__ */ jsx("li", { role: "none", style: { padding: "0px 16px", minHeight: 24, display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx(StyledSection, { role: "presentation", children: item.label }) });
221
+ export {
222
+ MenuItem,
223
+ MenuItemAddon,
224
+ Section,
225
+ Separator
226
+ };
227
+ //# sourceMappingURL=MenuItem.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../scripts/build/transpile/react-shim.js", "../../../src/parts/MenuItem.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "/* eslint-disable import/no-cycle */\n/* eslint-disable @typescript-eslint/no-use-before-define */\n/* eslint-disable complexity */\n/* eslint-disable max-lines */\nimport React, { useState, useCallback, useMemo } from 'react';\nimport {\n TriangleUpSmall,\n CheckmarkXsmall,\n TriangleDownSmall,\n ChevronSmallDown,\n ChevronSmallRight,\n} from '@elliemae/ds-icons';\nimport { type TypescriptHelpersT } from '@elliemae/ds-typescript-helpers';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport { Grid } from '@elliemae/ds-grid';\nimport { MenuButtonContext } from '../DSMenuButtonCTX.js';\nimport {\n StyledMenuItem,\n StyledMenuItemContent,\n StyledLeftContent,\n StyledRightContent,\n StyledSeparator,\n StyledSection,\n} from '../styled.js';\nimport { SubMenu } from './SubMenu.js';\nimport type { MenuButtonT } from '../react-desc-prop-types.js';\n\nexport const MenuItemAddon = React.memo(({ level, isOpen }: { level: number; isOpen: boolean }) => {\n if (level === 0)\n return isOpen ? (\n <TriangleUpSmall color={['brand-primary', '600']} />\n ) : (\n <TriangleDownSmall color={['brand-primary', '600']} />\n );\n return isOpen ? (\n <ChevronSmallDown size=\"m\" color={['brand-primary', '600']} />\n ) : (\n <ChevronSmallRight size=\"m\" color={['brand-primary', '600']} />\n );\n});\n\nexport const MenuItem = ({\n innerRef,\n tabIndex,\n onFocus,\n selectionMode,\n item,\n level,\n parentId,\n isVertical,\n}: {\n selectionMode?: 'single' | 'multiple';\n item: MenuButtonT.Item;\n level: number;\n parentId: string | undefined;\n isVertical?: boolean;\n tabIndex: number;\n onFocus: React.FocusEventHandler;\n innerRef: TypescriptHelpersT.AnyRef<HTMLElement>;\n}) => {\n const {\n setFocusedOption,\n focusedOption,\n selectedKeys,\n onSelectionChange,\n propsWithDefault: { ItemRenderer },\n } = React.useContext(MenuButtonContext);\n const listRef = React.useRef(null);\n const [showSubMenu, setShowSubMenu] = useState(false);\n const [referenceElement, setReferenceElement] = React.useState<HTMLElement | null>(null);\n const itemRef = useCallback(\n (node: HTMLElement | null) => {\n if (node !== null) {\n if (focusedOption === item.dsId) node.focus();\n }\n return node;\n },\n [focusedOption, item.dsId],\n );\n\n const selectionLogic = useCallback(() => {\n if (selectionMode === 'single') {\n const newValue = item.dsId === selectedKeys[0] ? [] : [item.dsId];\n onSelectionChange(newValue, parentId || 'root', item);\n }\n if (selectionMode === 'multiple') {\n const newValue = selectedKeys.includes(item.dsId)\n ? selectedKeys.filter((key: string) => key !== item.dsId)\n : [...selectedKeys, item.dsId];\n onSelectionChange(newValue, parentId || 'root', item);\n }\n }, [item, onSelectionChange, parentId, selectedKeys, selectionMode]);\n\n const handleOnClick: React.MouseEventHandler = useCallback(\n (e) => {\n if (selectionMode === 'multiple') {\n e.stopPropagation();\n }\n selectionLogic();\n },\n [selectionLogic, selectionMode],\n );\n const onItemKeyDown: React.KeyboardEventHandler = useCallback(\n (event) => {\n // selection\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n selectionLogic();\n }\n // open submenu logic\n if (\n ((event.key === 'ArrowDown' && level === 0) || (event.key === 'ArrowRight' && level !== 0)) &&\n item.subitems\n ) {\n event.preventDefault();\n event.stopPropagation();\n setShowSubMenu(true);\n setFocusedOption(item.subitems[0].dsId);\n }\n\n // close submenu logic\n if (event.key === 'ArrowLeft' && level >= 2) {\n event.preventDefault();\n event.stopPropagation();\n if (parentId) setFocusedOption(parentId);\n }\n if (event.key === 'Escape' && level > 0) {\n if (parentId !== undefined) {\n setFocusedOption(parentId);\n }\n }\n },\n [level, item.subitems, selectionLogic, setFocusedOption, parentId],\n );\n\n const handleOnLIKeyDown: React.KeyboardEventHandler = useCallback(\n (e) => {\n // logic to close all submenus and focus on parent\n if (e.key === 'Enter') {\n setShowSubMenu(false);\n if (level === 0) {\n setFocusedOption(item.dsId);\n }\n }\n },\n [item.dsId, level, setFocusedOption],\n );\n\n const handleOnMouseEnter = useCallback(() => {\n setShowSubMenu(true);\n setFocusedOption(item.dsId);\n }, [item.dsId, setFocusedOption]);\n\n const handleOnMouseLeave = useCallback(() => {\n setShowSubMenu(false);\n }, []);\n\n const ariaExpanded = useMemo(() => {\n if (item.subitems) {\n return showSubMenu ? 'true' : 'false';\n }\n return undefined;\n }, [item.subitems, showSubMenu]);\n\n const role = useMemo(() => {\n if (selectionMode === 'single') {\n return 'menuitemradio';\n }\n if (selectionMode === 'multiple') {\n return 'menuitemcheckbox';\n }\n return 'menuitem';\n }, [selectionMode]);\n\n const ariaChecked = useMemo(() => {\n if (selectionMode === 'multiple' || selectionMode === 'single') {\n return selectedKeys.includes(item.dsId) ? 'true' : 'false';\n }\n return undefined;\n }, [item.dsId, selectionMode, selectedKeys]);\n\n return (\n <StyledMenuItem\n role=\"none\"\n innerRef={listRef}\n onMouseEnter={handleOnMouseEnter}\n onMouseLeave={handleOnMouseLeave}\n onKeyDown={handleOnLIKeyDown}\n isOpen={showSubMenu}\n level={level}\n isVertical={isVertical}\n >\n <StyledMenuItemContent\n role={role}\n aria-checked={ariaChecked}\n aria-haspopup={item.subitems ? 'true' : 'false'}\n aria-expanded={ariaExpanded}\n innerRef={mergeRefs(innerRef, itemRef, setReferenceElement)}\n onKeyDown={onItemKeyDown}\n onClick={handleOnClick}\n hasChildren={item.subitems !== undefined}\n onFocus={onFocus}\n tabIndex={tabIndex}\n >\n {ItemRenderer ? (\n <ItemRenderer item={item} isSelected={selectedKeys.includes(item.dsId)} />\n ) : (\n <MenuItemContent\n item={item}\n selectionMode={selectionMode}\n selectedKeys={selectedKeys}\n showSubMenu={showSubMenu}\n level={level}\n />\n )}\n </StyledMenuItemContent>\n {item.subitems && showSubMenu && (\n <SubMenu\n level={level + 1}\n items={item.subitems}\n showSubMenu={showSubMenu}\n setShowSubMenu={setShowSubMenu}\n referenceElement={referenceElement}\n parentId={item.dsId}\n selectionMode={item.selectionMode}\n minWidth={item.minWidth}\n />\n )}\n </StyledMenuItem>\n );\n};\n\nconst MenuItemContent = React.memo(\n ({\n item,\n selectionMode,\n selectedKeys,\n showSubMenu,\n level,\n }: {\n item: MenuButtonT.Item;\n selectionMode?: 'single' | 'multiple';\n selectedKeys: string[];\n showSubMenu: boolean;\n level: number;\n }) => (\n <>\n <StyledLeftContent>\n <SelectionAddon selectionMode={selectionMode} item={item} selectedKeys={selectedKeys} />\n <span style={{ lineHeight: 1.15 }}>{item.label}</span>\n </StyledLeftContent>\n <StyledRightContent>\n {item.subitems ? <MenuItemAddon isOpen={showSubMenu} level={level} /> : null}\n </StyledRightContent>\n </>\n ),\n);\n\nconst SelectionAddon = ({\n item,\n selectedKeys,\n selectionMode,\n}: {\n item: MenuButtonT.Item;\n selectedKeys: string[];\n selectionMode?: 'single' | 'multiple';\n}) => {\n if (selectionMode) {\n return selectedKeys.includes(item.dsId) ? (\n <Grid>\n <CheckmarkXsmall size=\"m\" color={['brand-primary', '600']} />\n </Grid>\n ) : (\n <div style={{ width: '24px' }} />\n );\n }\n return null;\n};\n\nexport const Separator = () => (\n <li role=\"none\" style={{ padding: '0px 16px' }}>\n <StyledSeparator role=\"separator\" />\n </li>\n);\n\nexport const Section = ({ item }: { item: MenuButtonT.Item }) => (\n <li role=\"none\" style={{ padding: '0px 16px', minHeight: 24, display: 'flex', alignItems: 'center' }}>\n <StyledSection role=\"presentation\">{item.label}</StyledSection>\n </li>\n);\n"],
5
+ "mappings": "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",
6
+ "names": ["React"]
7
+ }