@hh.ru/magritte-ui-menu 1.0.5 → 1.0.7

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/BottomSheet.js CHANGED
@@ -5,10 +5,12 @@ import { BottomSheet } from '@hh.ru/magritte-ui-bottom-sheet';
5
5
  import { MenuContext } from './context.js';
6
6
 
7
7
  const MenuBottomSheet = (props) => {
8
- const { onClose, visible } = useContext(MenuContext);
9
- return jsx(BottomSheet, { ...props, onClose: onClose, visible: visible, withContentPaddings: "top" });
8
+ const { onAfterExit, onClose, visible } = useContext(MenuContext);
9
+ return (jsx(BottomSheet, { ...props, onAfterExit: () => {
10
+ props.onAfterExit?.();
11
+ onAfterExit();
12
+ }, onClose: onClose, visible: visible, withContentPaddings: "top" }));
10
13
  };
11
- MenuBottomSheet.displayName = 'Menu.BottomSheet';
12
14
 
13
15
  export { MenuBottomSheet };
14
16
  //# sourceMappingURL=BottomSheet.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheet.js","sources":["src/BottomSheet.tsx"],"sourcesContent":["import { useContext } from 'react';\n\nimport { type BottomSheetProps, BottomSheet } from '@hh.ru/magritte-ui-bottom-sheet';\nimport { MenuContext } from '@hh.ru/magritte-ui-menu/context';\n\nexport const MenuBottomSheet: React.FC<Omit<BottomSheetProps, 'onClose' | 'visible' | 'withContentPaddings'>> = (\n props\n) => {\n const { onClose, visible } = useContext(MenuContext);\n\n return <BottomSheet {...props} onClose={onClose} visible={visible} withContentPaddings=\"top\" />;\n};\n\nMenuBottomSheet.displayName = 'Menu.BottomSheet';\n"],"names":["_jsx"],"mappings":";;;;;AAKa,MAAA,eAAe,GAAoF,CAC5G,KAAK,KACL;IACA,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;AAErD,IAAA,OAAOA,IAAC,WAAW,EAAA,EAAA,GAAK,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAC,KAAK,GAAG,CAAC;AACpG,EAAE;AAEF,eAAe,CAAC,WAAW,GAAG,kBAAkB;;;;"}
1
+ {"version":3,"file":"BottomSheet.js","sources":["src/BottomSheet.tsx"],"sourcesContent":["import { useContext } from 'react';\n\nimport { type BottomSheetProps, BottomSheet } from '@hh.ru/magritte-ui-bottom-sheet';\nimport { MenuContext } from '@hh.ru/magritte-ui-menu/context';\n\nexport const MenuBottomSheet: React.FC<Omit<BottomSheetProps, 'onClose' | 'visible' | 'withContentPaddings'>> = (\n props\n) => {\n const { onAfterExit, onClose, visible } = useContext(MenuContext);\n\n return (\n <BottomSheet\n {...props}\n onAfterExit={() => {\n props.onAfterExit?.();\n onAfterExit();\n }}\n onClose={onClose}\n visible={visible}\n withContentPaddings=\"top\"\n />\n );\n};\n"],"names":["_jsx"],"mappings":";;;;;AAKa,MAAA,eAAe,GAAoF,CAC5G,KAAK,KACL;AACA,IAAA,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IAElE,QACIA,IAAC,WAAW,EAAA,EAAA,GACJ,KAAK,EACT,WAAW,EAAE,MAAK;AACd,YAAA,KAAK,CAAC,WAAW,IAAI,CAAC;AACtB,YAAA,WAAW,EAAE,CAAC;AAClB,SAAC,EACD,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,mBAAmB,EAAC,KAAK,EAAA,CAC3B,EACJ;AACN;;;;"}
package/Divider.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import { type DividerProps } from '@hh.ru/magritte-ui-divider';
2
- export declare const MenuDivider: React.FC<DividerProps>;
2
+ export declare const MenuDivider: React.FC<Omit<DividerProps, 'marginTop' | 'marginBottom' | 'mode'>>;
package/Divider.js CHANGED
@@ -5,7 +5,6 @@ import { Divider } from '@hh.ru/magritte-ui-divider';
5
5
  const MenuDivider = (props) => {
6
6
  return jsx(Divider, { marginTop: 4, marginBottom: 4, ...props });
7
7
  };
8
- MenuDivider.displayName = 'Menu.Divider';
9
8
 
10
9
  export { MenuDivider };
11
10
  //# sourceMappingURL=Divider.js.map
package/Divider.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Divider.js","sources":["src/Divider.tsx"],"sourcesContent":["import { type DividerProps, Divider } from '@hh.ru/magritte-ui-divider';\n\nexport const MenuDivider: React.FC<DividerProps> = (props) => {\n return <Divider marginTop={4} marginBottom={4} {...props} />;\n};\n\nMenuDivider.displayName = 'Menu.Divider';\n"],"names":["_jsx"],"mappings":";;;AAEa,MAAA,WAAW,GAA2B,CAAC,KAAK,KAAI;AACzD,IAAA,OAAOA,GAAC,CAAA,OAAO,EAAC,EAAA,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAM,GAAA,KAAK,GAAI,CAAC;AACjE,EAAE;AAEF,WAAW,CAAC,WAAW,GAAG,cAAc;;;;"}
1
+ {"version":3,"file":"Divider.js","sources":["src/Divider.tsx"],"sourcesContent":["import { type DividerProps, Divider } from '@hh.ru/magritte-ui-divider';\n\nexport const MenuDivider: React.FC<Omit<DividerProps, 'marginTop' | 'marginBottom' | 'mode'>> = (props) => {\n return <Divider marginTop={4} marginBottom={4} {...props} />;\n};\n"],"names":["_jsx"],"mappings":";;;AAEa,MAAA,WAAW,GAAwE,CAAC,KAAK,KAAI;AACtG,IAAA,OAAOA,GAAC,CAAA,OAAO,EAAC,EAAA,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAM,GAAA,KAAK,GAAI,CAAC;AACjE;;;;"}
package/Drop.js CHANGED
@@ -12,10 +12,12 @@ const DROP_PROPS = {
12
12
  role: 'menu',
13
13
  };
14
14
  const MenuDrop = (props) => {
15
- const { activatorRef, onClose, placement, setDropContainer, visible } = useContext(MenuContext);
16
- return (jsx(Drop, { ...props, ...DROP_PROPS, activatorRef: activatorRef, onClose: onClose, placement: placement, ref: setDropContainer, visible: visible }));
15
+ const { activatorRef, onAfterExit, onClose, placement, setDropContainer, visible } = useContext(MenuContext);
16
+ return (jsx(Drop, { ...props, ...DROP_PROPS, activatorRef: activatorRef, onAfterExit: () => {
17
+ props.onAfterExit?.();
18
+ onAfterExit();
19
+ }, onClose: onClose, placement: placement, ref: setDropContainer, visible: visible }));
17
20
  };
18
- MenuDrop.displayName = 'Menu.Drop';
19
21
 
20
22
  export { DROP_PROPS, MenuDrop };
21
23
  //# sourceMappingURL=Drop.js.map
package/Drop.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Drop.js","sources":["src/Drop.tsx"],"sourcesContent":["import { useContext } from 'react';\n\nimport { type DropProps, Drop } from '@hh.ru/magritte-ui-drop';\nimport { MenuContext } from '@hh.ru/magritte-ui-menu/context';\n\nexport const DROP_PROPS: Partial<DropProps> = {\n paddingTop: 12,\n paddingRight: 0,\n paddingBottom: 12,\n paddingLeft: 0,\n role: 'menu',\n};\n\nexport const MenuDrop: React.FC<\n Omit<\n DropProps,\n | 'activatorRef'\n | 'onClose'\n | 'padding'\n | 'paddingTop'\n | 'paddingRight'\n | 'paddingBottom'\n | 'paddingLeft'\n | 'placement'\n | 'role'\n | 'visible'\n >\n> = (props) => {\n const { activatorRef, onClose, placement, setDropContainer, visible } = useContext(MenuContext);\n\n return (\n <Drop\n {...props}\n {...DROP_PROPS}\n activatorRef={activatorRef}\n onClose={onClose}\n placement={placement}\n ref={setDropContainer}\n visible={visible}\n />\n );\n};\n\nMenuDrop.displayName = 'Menu.Drop';\n"],"names":["_jsx"],"mappings":";;;;;AAKa,MAAA,UAAU,GAAuB;AAC1C,IAAA,UAAU,EAAE,EAAE;AACd,IAAA,YAAY,EAAE,CAAC;AACf,IAAA,aAAa,EAAE,EAAE;AACjB,IAAA,WAAW,EAAE,CAAC;AACd,IAAA,IAAI,EAAE,MAAM;EACd;AAEW,MAAA,QAAQ,GAcjB,CAAC,KAAK,KAAI;AACV,IAAA,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;AAEhG,IAAA,QACIA,GAAA,CAAC,IAAI,EAAA,EAAA,GACG,KAAK,EAAA,GACL,UAAU,EACd,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,OAAO,EAAA,CAClB,EACJ;AACN,EAAE;AAEF,QAAQ,CAAC,WAAW,GAAG,WAAW;;;;"}
1
+ {"version":3,"file":"Drop.js","sources":["src/Drop.tsx"],"sourcesContent":["import { useContext } from 'react';\n\nimport { type DropProps, Drop } from '@hh.ru/magritte-ui-drop';\nimport { MenuContext } from '@hh.ru/magritte-ui-menu/context';\n\nexport const DROP_PROPS: Partial<DropProps> = {\n paddingTop: 12,\n paddingRight: 0,\n paddingBottom: 12,\n paddingLeft: 0,\n role: 'menu',\n};\n\nexport const MenuDrop: React.FC<\n Omit<\n DropProps,\n | 'activatorRef'\n | 'onClose'\n | 'padding'\n | 'paddingTop'\n | 'paddingRight'\n | 'paddingBottom'\n | 'paddingLeft'\n | 'placement'\n | 'role'\n | 'visible'\n >\n> = (props) => {\n const { activatorRef, onAfterExit, onClose, placement, setDropContainer, visible } = useContext(MenuContext);\n\n return (\n <Drop\n {...props}\n {...DROP_PROPS}\n activatorRef={activatorRef}\n onAfterExit={() => {\n props.onAfterExit?.();\n onAfterExit();\n }}\n onClose={onClose}\n placement={placement}\n ref={setDropContainer}\n visible={visible}\n />\n );\n};\n"],"names":["_jsx"],"mappings":";;;;;AAKa,MAAA,UAAU,GAAuB;AAC1C,IAAA,UAAU,EAAE,EAAE;AACd,IAAA,YAAY,EAAE,CAAC;AACf,IAAA,aAAa,EAAE,EAAE;AACjB,IAAA,WAAW,EAAE,CAAC;AACd,IAAA,IAAI,EAAE,MAAM;EACd;AAEW,MAAA,QAAQ,GAcjB,CAAC,KAAK,KAAI;AACV,IAAA,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;AAE7G,IAAA,QACIA,GAAA,CAAC,IAAI,EAAA,EAAA,GACG,KAAK,EACL,GAAA,UAAU,EACd,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAK;AACd,YAAA,KAAK,CAAC,WAAW,IAAI,CAAC;AACtB,YAAA,WAAW,EAAE,CAAC;AAClB,SAAC,EACD,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,SAAS,EACpB,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,OAAO,EAAA,CAClB,EACJ;AACN;;;;"}
package/Item.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import './index.css';
2
- import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { forwardRef, useContext, useRef, useState, useEffect, cloneElement } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import classnames from 'classnames';
6
- import { throttle } from '@hh.ru/magritte-common-func-utils';
7
6
  import { keyboardMatches, keyboardKeys } from '@hh.ru/magritte-common-keyboard';
8
7
  import { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';
9
8
  import { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';
@@ -13,10 +12,13 @@ import { CheckOutlinedSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte
13
12
  import { DisabledWrapper } from './DisabledWrapper.js';
14
13
  import { DROP_PROPS } from './Drop.js';
15
14
  import { MenuContext } from './context.js';
15
+ import { useSubmenuSafeZone } from './useSubmenuSafeZone.js';
16
16
  import { isSwitchComponent } from '@hh.ru/magritte-ui-switch';
17
17
  import { Text } from '@hh.ru/magritte-ui-typography';
18
- import { s as styles } from './menu-ChEsgmKq.js';
18
+ import { s as styles } from './menu-DKXKF84l.js';
19
19
  import '@hh.ru/magritte-common-use-disabled';
20
+ import '@hh.ru/magritte-common-func-utils';
21
+ import './safeZone.js';
20
22
 
21
23
  const DEFAULT_ICON_PROPS = {
22
24
  neutral: {},
@@ -38,165 +40,96 @@ const SUBMENU_DROP_PLACEMENT = [
38
40
  'left-bottom',
39
41
  'left-center',
40
42
  ];
41
- const SUBMENU_CLOSE_DELAY_MS = 500;
42
- const MOUSE_MOVE_THROTTLE_MS = 50;
43
- const MIN_MOUSE_MOVE_SQUARED = 16;
44
- const sign = (P, A, B) => {
45
- return (A.x - B.x) * (P.y - B.y) >= (P.x - B.x) * (A.y - B.y);
46
- };
47
- const isPointInsideTriangle = (P, A, B, C) => {
48
- const values = [sign(P, A, B), sign(P, B, C), sign(P, C, A)];
49
- return (values[0] && values[1] && values[2]) || (!values[0] && !values[1] && !values[2]);
50
- };
51
- const findNearestSubmenuEdge = (dropCoords, submenuCoords) => {
52
- if (submenuCoords.right > dropCoords.right) {
53
- return [
54
- { x: submenuCoords.left, y: submenuCoords.top },
55
- { x: submenuCoords.left, y: submenuCoords.bottom },
56
- ];
57
- }
58
- return [
59
- { x: submenuCoords.right, y: submenuCoords.top },
60
- { x: submenuCoords.right, y: submenuCoords.bottom },
61
- ];
62
- };
63
43
  const MenuItem = forwardRef(({ children, className, disabled = false, icon, subitems, selected, style = 'neutral', rightContent, subtitle, tag, ...props }, ref) => {
64
44
  const { isMobile } = useBreakpoint();
65
45
  const contextValue = useContext(MenuContext);
66
- const { dropContainer, itemWithVisibleSubmenu, mobileSubmenuContainer, mobileTitleContainer, setItemWithVisibleSubmenu, submenuAllowed, } = contextValue;
46
+ const { dropContainer, itemWithVisibleSubmenu, mobileSubmenuContainer, mobileTitleContainer, setItemWithVisibleSubmenu, submenuAllowed, visible, } = contextValue;
67
47
  const itemRef = useRef(null);
68
48
  const itemRefCallback = useMultipleRefs(itemRef, ref);
69
49
  const submenuRef = useRef(null);
70
50
  const [hasHover, setHover] = useState(false);
71
51
  const [submenuVisible, setSubmenuVisible] = useState(false);
72
- const submenuCloseTimeoutRef = useRef(null);
73
52
  const hasSwitch = !selected && isSwitchComponent(rightContent);
74
53
  const hasSubmenu = !selected && !isSwitchComponent(rightContent) && submenuAllowed && subitems;
54
+ const { trackPointer, cancelPendingClose } = useSubmenuSafeZone({
55
+ active: submenuVisible,
56
+ dropContainer: dropContainer ?? null,
57
+ itemRef,
58
+ submenuRef,
59
+ onClose: () => setSubmenuVisible(false),
60
+ });
75
61
  const showSubmenu = () => {
76
- if (submenuCloseTimeoutRef.current !== null) {
77
- clearTimeout(submenuCloseTimeoutRef.current);
78
- submenuCloseTimeoutRef.current = null;
79
- }
62
+ cancelPendingClose();
80
63
  setSubmenuVisible(true);
81
64
  setItemWithVisibleSubmenu?.(itemRef.current);
82
65
  };
83
- const stateRef = useRef({
84
- dropCoords: null,
85
- isMouseOutsideItem: null,
86
- prevMouseCoords: null,
87
- submenuCoords: null,
88
- });
89
66
  useEffect(() => {
90
67
  if (itemWithVisibleSubmenu !== itemRef.current) {
91
- if (submenuCloseTimeoutRef.current !== null) {
92
- clearTimeout(submenuCloseTimeoutRef.current);
93
- submenuCloseTimeoutRef.current = null;
94
- }
68
+ cancelPendingClose();
95
69
  setSubmenuVisible(false);
96
70
  }
97
- }, [itemWithVisibleSubmenu]);
98
- useEffect(() => {
99
- if (!dropContainer || !itemRef.current || !submenuVisible || !submenuRef.current) {
100
- return void 0;
101
- }
102
- const checkIfMouseIsMovingTowardsSubmenu = throttle((event) => {
103
- const currentMouseCoords = { x: event.clientX, y: event.clientY };
104
- if (stateRef.current.dropCoords !== null &&
105
- stateRef.current.isMouseOutsideItem &&
106
- stateRef.current.prevMouseCoords !== null &&
107
- stateRef.current.submenuCoords !== null) {
108
- const deltaX = currentMouseCoords.x - stateRef.current.prevMouseCoords.x;
109
- const deltaY = currentMouseCoords.y - stateRef.current.prevMouseCoords.y;
110
- if (deltaX * deltaX + deltaY * deltaY < MIN_MOUSE_MOVE_SQUARED) {
111
- return;
112
- }
113
- const nearestSubmenuEdge = findNearestSubmenuEdge(stateRef.current.dropCoords, stateRef.current.submenuCoords);
114
- const isMouseMovingTowardsSubmenu = isPointInsideTriangle(currentMouseCoords, stateRef.current.prevMouseCoords, nearestSubmenuEdge[0], nearestSubmenuEdge[1]);
115
- if (isMouseMovingTowardsSubmenu && submenuCloseTimeoutRef.current !== null) {
116
- clearTimeout(submenuCloseTimeoutRef.current);
117
- submenuCloseTimeoutRef.current = null;
118
- }
119
- if (!isMouseMovingTowardsSubmenu && submenuCloseTimeoutRef.current === null) {
120
- submenuCloseTimeoutRef.current = setTimeout(() => {
121
- submenuCloseTimeoutRef.current = null;
122
- setSubmenuVisible(false);
123
- }, SUBMENU_CLOSE_DELAY_MS);
124
- }
125
- }
126
- stateRef.current.prevMouseCoords = currentMouseCoords;
127
- }, MOUSE_MOVE_THROTTLE_MS);
128
- document.addEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);
129
- dropContainer.addEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);
130
- stateRef.current.dropCoords = dropContainer.getBoundingClientRect();
131
- stateRef.current.submenuCoords = submenuRef.current.getBoundingClientRect();
132
- return () => {
133
- document.removeEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);
134
- dropContainer.removeEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);
135
- checkIfMouseIsMovingTowardsSubmenu.cancel();
136
- if (submenuCloseTimeoutRef.current !== null) {
137
- clearTimeout(submenuCloseTimeoutRef.current);
138
- submenuCloseTimeoutRef.current = null;
139
- }
140
- stateRef.current = {
141
- dropCoords: null,
142
- isMouseOutsideItem: null,
143
- prevMouseCoords: null,
144
- submenuCoords: null,
145
- };
146
- };
147
- }, [dropContainer, submenuVisible, setSubmenuVisible]);
148
- return (jsx(DisabledWrapper, { disabled: disabled, children: jsxs("div", { ...props, "aria-disabled": disabled, className: classnames(className, { [styles.disabled]: disabled }, styles.dropContentMargin, styles.item, styles[style]), onClick: (event) => {
149
- props.onClick?.(event);
150
- if (hasSwitch) {
151
- rightContent.props.onClick?.();
152
- }
153
- if (hasSubmenu) {
154
- showSubmenu();
155
- }
156
- }, onKeyDown: (event) => {
157
- props.onKeyDown?.(event);
158
- if (keyboardMatches(event, [keyboardKeys.Enter, keyboardKeys.Space])) {
159
- event.preventDefault();
160
- if (hasSwitch) {
161
- rightContent.props.onClick?.();
162
- }
163
- else if (hasSubmenu) {
164
- showSubmenu();
165
- }
166
- else {
167
- event.target.click();
168
- }
169
- }
170
- }, onMouseEnter: (event) => {
171
- props.onMouseEnter?.(event);
172
- if (!isMobile) {
173
- setHover(true);
174
- if (hasSubmenu &&
175
- !(submenuVisible && submenuRef.current?.contains(event.target))) {
176
- showSubmenu();
177
- stateRef.current.isMouseOutsideItem = false;
178
- }
179
- }
180
- }, onMouseLeave: (event) => {
181
- props.onMouseLeave?.(event);
182
- if (!isMobile) {
183
- setHover(false);
184
- if (hasSubmenu) {
185
- stateRef.current.isMouseOutsideItem = true;
186
- }
187
- }
188
- }, onMouseMove: (event) => {
189
- props.onMouseMove?.(event);
190
- if (hasSubmenu &&
191
- !(submenuVisible && submenuRef.current?.contains(event.target))) {
192
- showSubmenu();
193
- stateRef.current.isMouseOutsideItem = false;
194
- }
195
- }, ref: itemRefCallback, role: "menuitem", tabIndex: disabled ? -1 : 0, children: [icon && (jsx("div", { className: styles.itemIcon, children: jsx(IconDefaultPropsContext, { props: DEFAULT_ICON_PROPS[style], children: icon }) })), jsxs("div", { className: styles.itemText, children: [jsx(Text, { ellipsis: true, style: TEXT_STYLE[style], typography: isMobile ? 'label-2-regular' : 'label-3-regular', children: children }), subtitle && (jsx(Text, { ellipsis: true, style: SECONDARY_TEXT_STYLE[style], typography: "label-3-regular", children: subtitle }))] }), tag && (jsx("div", { className: styles.itemTag, children: cloneElement(tag, { onSurface: hasHover }) })), selected && (jsx("div", { className: styles.itemRightContent, children: jsx(CheckOutlinedSize24, { initialColor: "secondary" }) })), hasSwitch && (jsx("div", { className: styles.itemRightContent, onClick: (event) => event.stopPropagation(), children: rightContent })), hasSubmenu && (jsxs(MenuContext.Provider, { value: { ...contextValue, submenuAllowed: false }, children: [jsxs("div", { className: styles.itemRightContent, children: [jsx(Text, { ellipsis: true, style: SECONDARY_TEXT_STYLE[style], typography: "label-3-regular", children: rightContent }), jsx(ChevronRightOutlinedSize24, { initialColor: "secondary" })] }), jsx(Drop, { ...DROP_PROPS, activatorRef: itemRef, onClose: () => setSubmenuVisible(false), placement: SUBMENU_DROP_PLACEMENT, ref: submenuRef, visible: submenuVisible, children: subitems }), mobileSubmenuContainer &&
196
- createPortal(submenuVisible ? subitems : null, mobileSubmenuContainer), mobileTitleContainer &&
197
- createPortal(submenuVisible ? children : null, mobileTitleContainer)] }))] }) }));
71
+ }, [itemWithVisibleSubmenu, cancelPendingClose]);
72
+ return (jsxs(Fragment, { children: [jsx(DisabledWrapper, { disabled: disabled, children: jsxs("div", { ...props, "aria-disabled": disabled, className: classnames(className, { [styles.disabled]: disabled }, styles.dropContentMargin, styles.item, styles[style]), onClick: (event) => {
73
+ if (disabled) {
74
+ return;
75
+ }
76
+ props.onClick?.(event);
77
+ if (hasSwitch) {
78
+ rightContent.props.onClick?.();
79
+ }
80
+ if (hasSubmenu) {
81
+ showSubmenu();
82
+ }
83
+ }, onKeyDown: (event) => {
84
+ if (disabled) {
85
+ return;
86
+ }
87
+ props.onKeyDown?.(event);
88
+ if (keyboardMatches(event, [keyboardKeys.Enter, keyboardKeys.Space])) {
89
+ event.preventDefault();
90
+ if (hasSwitch) {
91
+ rightContent.props.onClick?.();
92
+ }
93
+ else if (hasSubmenu) {
94
+ showSubmenu();
95
+ }
96
+ else {
97
+ event.target.click();
98
+ }
99
+ }
100
+ }, onMouseEnter: (event) => {
101
+ if (!disabled) {
102
+ props.onMouseEnter?.(event);
103
+ if (!isMobile) {
104
+ setHover(true);
105
+ trackPointer({ x: event.clientX, y: event.clientY });
106
+ if (hasSubmenu && !submenuVisible) {
107
+ showSubmenu();
108
+ }
109
+ }
110
+ }
111
+ }, onMouseLeave: (event) => {
112
+ if (!disabled) {
113
+ props.onMouseLeave?.(event);
114
+ }
115
+ if (!isMobile) {
116
+ setHover(false);
117
+ }
118
+ }, onMouseMove: (event) => {
119
+ if (!disabled) {
120
+ props.onMouseMove?.(event);
121
+ if (!isMobile) {
122
+ setHover(true);
123
+ trackPointer({ x: event.clientX, y: event.clientY });
124
+ if (hasSubmenu && !submenuVisible) {
125
+ showSubmenu();
126
+ }
127
+ }
128
+ }
129
+ }, ref: itemRefCallback, role: "menuitem", tabIndex: disabled ? -1 : 0, children: [icon && (jsx("div", { className: styles.itemIcon, children: jsx(IconDefaultPropsContext, { props: DEFAULT_ICON_PROPS[style], children: icon }) })), jsxs("div", { className: styles.itemText, children: [jsx(Text, { ellipsis: true, style: TEXT_STYLE[style], typography: isMobile ? 'label-2-regular' : 'label-3-regular', children: children }), subtitle && (jsx(Text, { ellipsis: true, style: SECONDARY_TEXT_STYLE[style], typography: "label-3-regular", children: subtitle }))] }), tag && (jsx("div", { className: styles.itemTag, children: cloneElement(tag, { onSurface: hasHover }) })), selected && (jsx("div", { className: styles.itemRightContent, children: jsx(CheckOutlinedSize24, { initialColor: "secondary" }) })), hasSwitch && (jsx("div", { className: styles.itemRightContent, onClick: (event) => event.stopPropagation(), children: rightContent })), hasSubmenu && (jsxs("div", { className: styles.itemRightContent, children: [jsx(Text, { ellipsis: true, style: SECONDARY_TEXT_STYLE[style], typography: "label-3-regular", children: rightContent }), jsx(ChevronRightOutlinedSize24, { initialColor: "secondary" })] }))] }) }), hasSubmenu && (jsxs(MenuContext.Provider, { value: { ...contextValue, submenuAllowed: false }, children: [jsx(Drop, { ...DROP_PROPS, activatorRef: itemRef, lockPlacement: true, onClose: () => setSubmenuVisible(false), placement: SUBMENU_DROP_PLACEMENT, ref: submenuRef, visible: visible && submenuVisible, children: subitems }), mobileSubmenuContainer &&
130
+ createPortal(submenuVisible ? subitems : null, mobileSubmenuContainer), mobileTitleContainer && createPortal(submenuVisible ? children : null, mobileTitleContainer)] }))] }));
198
131
  });
199
- MenuItem.displayName = 'Menu.Item';
132
+ MenuItem.displayName = 'MenuItem';
200
133
 
201
134
  export { MenuItem };
202
135
  //# sourceMappingURL=Item.js.map
package/Item.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Item.js","sources":["src/Item.tsx"],"sourcesContent":["import { cloneElement, forwardRef, useContext, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport classnames from 'classnames';\n\nimport { throttle } from '@hh.ru/magritte-common-func-utils';\nimport { keyboardKeys, keyboardMatches } from '@hh.ru/magritte-common-keyboard';\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { type DropProps, Drop } from '@hh.ru/magritte-ui-drop';\nimport { type IconProps, IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';\nimport { CheckOutlinedSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { DisabledWrapper } from '@hh.ru/magritte-ui-menu/DisabledWrapper';\nimport { DROP_PROPS } from '@hh.ru/magritte-ui-menu/Drop';\nimport { MenuContext } from '@hh.ru/magritte-ui-menu/context';\nimport { type MenuItemProps } from '@hh.ru/magritte-ui-menu/types';\nimport { isSwitchComponent } from '@hh.ru/magritte-ui-switch';\nimport { type TagProps } from '@hh.ru/magritte-ui-tag';\nimport { type TextStyle, Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './menu.less';\n\nconst DEFAULT_ICON_PROPS: Record<NonNullable<MenuItemProps['style']>, Partial<IconProps>> = {\n neutral: {},\n negative: { initialColor: 'negative' },\n};\n\nconst TEXT_STYLE: Record<NonNullable<MenuItemProps['style']>, TextStyle> = {\n neutral: 'primary',\n negative: 'negative',\n};\n\nconst SECONDARY_TEXT_STYLE: Record<NonNullable<MenuItemProps['style']>, TextStyle> = {\n neutral: 'secondary',\n negative: 'negative-secondary',\n};\n\nconst SUBMENU_DROP_PLACEMENT: DropProps['placement'] = [\n 'right-top',\n 'right-bottom',\n 'right-center',\n 'left-top',\n 'left-bottom',\n 'left-center',\n];\n\nconst SUBMENU_CLOSE_DELAY_MS = 500;\n\nconst MOUSE_MOVE_THROTTLE_MS = 50;\nconst MIN_MOUSE_MOVE_SQUARED = 16;\n\ntype Point = { x: number; y: number };\n\nconst sign = (P: Point, A: Point, B: Point): boolean => {\n return (A.x - B.x) * (P.y - B.y) >= (P.x - B.x) * (A.y - B.y);\n};\n\nconst isPointInsideTriangle = (P: Point, A: Point, B: Point, C: Point): boolean => {\n const values = [sign(P, A, B), sign(P, B, C), sign(P, C, A)];\n return (values[0] && values[1] && values[2]) || (!values[0] && !values[1] && !values[2]);\n};\n\nconst findNearestSubmenuEdge = (dropCoords: DOMRect, submenuCoords: DOMRect): [Point, Point] => {\n if (submenuCoords.right > dropCoords.right) {\n return [\n { x: submenuCoords.left, y: submenuCoords.top },\n { x: submenuCoords.left, y: submenuCoords.bottom },\n ];\n }\n return [\n { x: submenuCoords.right, y: submenuCoords.top },\n { x: submenuCoords.right, y: submenuCoords.bottom },\n ];\n};\n\nexport const MenuItem = forwardRef<HTMLDivElement, MenuItemProps>(\n (\n {\n children,\n className,\n disabled = false,\n icon,\n subitems,\n selected,\n style = 'neutral',\n rightContent,\n subtitle,\n tag,\n ...props\n },\n ref\n ) => {\n const { isMobile } = useBreakpoint();\n const contextValue = useContext(MenuContext);\n const {\n dropContainer,\n itemWithVisibleSubmenu,\n mobileSubmenuContainer,\n mobileTitleContainer,\n setItemWithVisibleSubmenu,\n submenuAllowed,\n } = contextValue;\n const itemRef = useRef<HTMLDivElement>(null);\n const itemRefCallback = useMultipleRefs(itemRef, ref);\n const submenuRef = useRef<HTMLDivElement>(null);\n const [hasHover, setHover] = useState(false);\n const [submenuVisible, setSubmenuVisible] = useState(false);\n const submenuCloseTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const hasSwitch = !selected && isSwitchComponent(rightContent);\n const hasSubmenu = !selected && !isSwitchComponent(rightContent) && submenuAllowed && subitems;\n\n const showSubmenu = () => {\n if (submenuCloseTimeoutRef.current !== null) {\n clearTimeout(submenuCloseTimeoutRef.current);\n submenuCloseTimeoutRef.current = null;\n }\n setSubmenuVisible(true);\n setItemWithVisibleSubmenu?.(itemRef.current);\n };\n\n const stateRef = useRef<{\n dropCoords: DOMRect | null;\n isMouseOutsideItem: boolean | null;\n prevMouseCoords: Point | null;\n submenuCoords: DOMRect | null;\n }>({\n dropCoords: null,\n isMouseOutsideItem: null,\n prevMouseCoords: null,\n submenuCoords: null,\n });\n\n useEffect(() => {\n if (itemWithVisibleSubmenu !== itemRef.current) {\n if (submenuCloseTimeoutRef.current !== null) {\n clearTimeout(submenuCloseTimeoutRef.current);\n submenuCloseTimeoutRef.current = null;\n }\n setSubmenuVisible(false);\n }\n }, [itemWithVisibleSubmenu]);\n\n useEffect(() => {\n if (!dropContainer || !itemRef.current || !submenuVisible || !submenuRef.current) {\n return void 0;\n }\n\n const checkIfMouseIsMovingTowardsSubmenu = throttle((event: MouseEvent) => {\n const currentMouseCoords: Point = { x: event.clientX, y: event.clientY };\n\n if (\n stateRef.current.dropCoords !== null &&\n stateRef.current.isMouseOutsideItem &&\n stateRef.current.prevMouseCoords !== null &&\n stateRef.current.submenuCoords !== null\n ) {\n const deltaX = currentMouseCoords.x - stateRef.current.prevMouseCoords.x;\n const deltaY = currentMouseCoords.y - stateRef.current.prevMouseCoords.y;\n if (deltaX * deltaX + deltaY * deltaY < MIN_MOUSE_MOVE_SQUARED) {\n return;\n }\n\n const nearestSubmenuEdge = findNearestSubmenuEdge(\n stateRef.current.dropCoords,\n stateRef.current.submenuCoords\n );\n\n const isMouseMovingTowardsSubmenu = isPointInsideTriangle(\n currentMouseCoords,\n stateRef.current.prevMouseCoords,\n nearestSubmenuEdge[0],\n nearestSubmenuEdge[1]\n );\n\n if (isMouseMovingTowardsSubmenu && submenuCloseTimeoutRef.current !== null) {\n clearTimeout(submenuCloseTimeoutRef.current);\n submenuCloseTimeoutRef.current = null;\n }\n\n if (!isMouseMovingTowardsSubmenu && submenuCloseTimeoutRef.current === null) {\n submenuCloseTimeoutRef.current = setTimeout(() => {\n submenuCloseTimeoutRef.current = null;\n setSubmenuVisible(false);\n }, SUBMENU_CLOSE_DELAY_MS);\n }\n }\n\n stateRef.current.prevMouseCoords = currentMouseCoords;\n }, MOUSE_MOVE_THROTTLE_MS);\n\n document.addEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);\n dropContainer.addEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);\n\n stateRef.current.dropCoords = dropContainer.getBoundingClientRect();\n stateRef.current.submenuCoords = submenuRef.current.getBoundingClientRect();\n\n return () => {\n document.removeEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);\n dropContainer.removeEventListener('mousemove', checkIfMouseIsMovingTowardsSubmenu);\n checkIfMouseIsMovingTowardsSubmenu.cancel();\n\n if (submenuCloseTimeoutRef.current !== null) {\n clearTimeout(submenuCloseTimeoutRef.current);\n submenuCloseTimeoutRef.current = null;\n }\n\n stateRef.current = {\n dropCoords: null,\n isMouseOutsideItem: null,\n prevMouseCoords: null,\n submenuCoords: null,\n };\n };\n }, [dropContainer, submenuVisible, setSubmenuVisible]);\n\n return (\n <DisabledWrapper disabled={disabled}>\n <div\n {...props}\n aria-disabled={disabled}\n className={classnames(\n className,\n { [styles.disabled]: disabled },\n styles.dropContentMargin,\n styles.item,\n styles[style]\n )}\n onClick={(event) => {\n props.onClick?.(event);\n if (hasSwitch) {\n rightContent.props.onClick?.();\n }\n if (hasSubmenu) {\n showSubmenu();\n }\n }}\n onKeyDown={(event) => {\n props.onKeyDown?.(event);\n if (keyboardMatches(event, [keyboardKeys.Enter, keyboardKeys.Space])) {\n event.preventDefault();\n if (hasSwitch) {\n rightContent.props.onClick?.();\n } else if (hasSubmenu) {\n showSubmenu();\n } else {\n (event.target as HTMLElement).click();\n }\n }\n }}\n onMouseEnter={(event) => {\n props.onMouseEnter?.(event);\n if (!isMobile) {\n setHover(true);\n if (\n hasSubmenu &&\n !(submenuVisible && submenuRef.current?.contains(event.target as HTMLElement))\n ) {\n showSubmenu();\n stateRef.current.isMouseOutsideItem = false;\n }\n }\n }}\n onMouseLeave={(event) => {\n props.onMouseLeave?.(event);\n if (!isMobile) {\n setHover(false);\n if (hasSubmenu) {\n stateRef.current.isMouseOutsideItem = true;\n }\n }\n }}\n onMouseMove={(event) => {\n props.onMouseMove?.(event);\n if (\n hasSubmenu &&\n !(submenuVisible && submenuRef.current?.contains(event.target as HTMLElement))\n ) {\n showSubmenu();\n stateRef.current.isMouseOutsideItem = false;\n }\n }}\n ref={itemRefCallback}\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n >\n {icon && (\n <div className={styles.itemIcon}>\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS[style]}>{icon}</IconDefaultPropsContext>\n </div>\n )}\n <div className={styles.itemText}>\n <Text\n ellipsis\n style={TEXT_STYLE[style]}\n typography={isMobile ? 'label-2-regular' : 'label-3-regular'}\n >\n {children}\n </Text>\n {subtitle && (\n <Text ellipsis style={SECONDARY_TEXT_STYLE[style]} typography=\"label-3-regular\">\n {subtitle}\n </Text>\n )}\n </div>\n {tag && (\n <div className={styles.itemTag}>\n {cloneElement(tag as React.ReactElement<TagProps>, { onSurface: hasHover })}\n </div>\n )}\n {selected && (\n <div className={styles.itemRightContent}>\n <CheckOutlinedSize24 initialColor=\"secondary\" />\n </div>\n )}\n {hasSwitch && (\n <div className={styles.itemRightContent} onClick={(event) => event.stopPropagation()}>\n {rightContent}\n </div>\n )}\n {hasSubmenu && (\n <MenuContext.Provider value={{ ...contextValue, submenuAllowed: false }}>\n <div className={styles.itemRightContent}>\n <Text ellipsis style={SECONDARY_TEXT_STYLE[style]} typography=\"label-3-regular\">\n {rightContent}\n </Text>\n <ChevronRightOutlinedSize24 initialColor=\"secondary\" />\n </div>\n <Drop\n {...DROP_PROPS}\n activatorRef={itemRef}\n onClose={() => setSubmenuVisible(false)}\n placement={SUBMENU_DROP_PLACEMENT}\n ref={submenuRef}\n visible={submenuVisible}\n >\n {subitems}\n </Drop>\n {mobileSubmenuContainer &&\n createPortal(submenuVisible ? subitems : null, mobileSubmenuContainer)}\n {mobileTitleContainer &&\n createPortal(submenuVisible ? children : null, mobileTitleContainer)}\n </MenuContext.Provider>\n )}\n </div>\n </DisabledWrapper>\n );\n }\n);\n\nMenuItem.displayName = 'Menu.Item';\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Item.js","sources":["src/Item.tsx"],"sourcesContent":["import { cloneElement, forwardRef, useContext, useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport classnames from 'classnames';\n\nimport { keyboardKeys, keyboardMatches } from '@hh.ru/magritte-common-keyboard';\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { type DropProps, Drop } from '@hh.ru/magritte-ui-drop';\nimport { type IconProps, IconDefaultPropsContext } from '@hh.ru/magritte-ui-icon';\nimport { CheckOutlinedSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { DisabledWrapper } from '@hh.ru/magritte-ui-menu/DisabledWrapper';\nimport { DROP_PROPS } from '@hh.ru/magritte-ui-menu/Drop';\nimport { MenuContext } from '@hh.ru/magritte-ui-menu/context';\nimport { type MenuItemProps } from '@hh.ru/magritte-ui-menu/types';\nimport { useSubmenuSafeZone } from '@hh.ru/magritte-ui-menu/useSubmenuSafeZone';\nimport { isSwitchComponent } from '@hh.ru/magritte-ui-switch';\nimport { type TagProps } from '@hh.ru/magritte-ui-tag';\nimport { type TextStyle, Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './menu.less';\n\nconst DEFAULT_ICON_PROPS: Record<NonNullable<MenuItemProps['style']>, Partial<IconProps>> = {\n neutral: {},\n negative: { initialColor: 'negative' },\n};\n\nconst TEXT_STYLE: Record<NonNullable<MenuItemProps['style']>, TextStyle> = {\n neutral: 'primary',\n negative: 'negative',\n};\n\nconst SECONDARY_TEXT_STYLE: Record<NonNullable<MenuItemProps['style']>, TextStyle> = {\n neutral: 'secondary',\n negative: 'negative-secondary',\n};\n\nconst SUBMENU_DROP_PLACEMENT: DropProps['placement'] = [\n 'right-top',\n 'right-bottom',\n 'right-center',\n 'left-top',\n 'left-bottom',\n 'left-center',\n];\n\nexport const MenuItem = forwardRef<HTMLDivElement, MenuItemProps>(\n (\n {\n children,\n className,\n disabled = false,\n icon,\n subitems,\n selected,\n style = 'neutral',\n rightContent,\n subtitle,\n tag,\n ...props\n },\n ref\n ) => {\n const { isMobile } = useBreakpoint();\n const contextValue = useContext(MenuContext);\n const {\n dropContainer,\n itemWithVisibleSubmenu,\n mobileSubmenuContainer,\n mobileTitleContainer,\n setItemWithVisibleSubmenu,\n submenuAllowed,\n visible,\n } = contextValue;\n const itemRef = useRef<HTMLDivElement>(null);\n const itemRefCallback = useMultipleRefs(itemRef, ref);\n const submenuRef = useRef<HTMLDivElement>(null);\n const [hasHover, setHover] = useState(false);\n const [submenuVisible, setSubmenuVisible] = useState(false);\n\n const hasSwitch = !selected && isSwitchComponent(rightContent);\n const hasSubmenu = !selected && !isSwitchComponent(rightContent) && submenuAllowed && subitems;\n\n const { trackPointer, cancelPendingClose } = useSubmenuSafeZone({\n active: submenuVisible,\n dropContainer: dropContainer ?? null,\n itemRef,\n submenuRef,\n onClose: () => setSubmenuVisible(false),\n });\n\n const showSubmenu = () => {\n cancelPendingClose();\n setSubmenuVisible(true);\n setItemWithVisibleSubmenu?.(itemRef.current);\n };\n\n useEffect(() => {\n if (itemWithVisibleSubmenu !== itemRef.current) {\n cancelPendingClose();\n setSubmenuVisible(false);\n }\n }, [itemWithVisibleSubmenu, cancelPendingClose]);\n\n return (\n <>\n <DisabledWrapper disabled={disabled}>\n <div\n {...props}\n aria-disabled={disabled}\n className={classnames(\n className,\n { [styles.disabled]: disabled },\n styles.dropContentMargin,\n styles.item,\n styles[style]\n )}\n onClick={(event) => {\n if (disabled) {\n return;\n }\n props.onClick?.(event);\n if (hasSwitch) {\n rightContent.props.onClick?.();\n }\n if (hasSubmenu) {\n showSubmenu();\n }\n }}\n onKeyDown={(event) => {\n if (disabled) {\n return;\n }\n props.onKeyDown?.(event);\n if (keyboardMatches(event, [keyboardKeys.Enter, keyboardKeys.Space])) {\n event.preventDefault();\n if (hasSwitch) {\n rightContent.props.onClick?.();\n } else if (hasSubmenu) {\n showSubmenu();\n } else {\n (event.target as HTMLElement).click();\n }\n }\n }}\n onMouseEnter={(event) => {\n if (!disabled) {\n props.onMouseEnter?.(event);\n if (!isMobile) {\n setHover(true);\n trackPointer({ x: event.clientX, y: event.clientY });\n\n if (hasSubmenu && !submenuVisible) {\n showSubmenu();\n }\n }\n }\n }}\n onMouseLeave={(event) => {\n if (!disabled) {\n props.onMouseLeave?.(event);\n }\n if (!isMobile) {\n setHover(false);\n }\n }}\n onMouseMove={(event) => {\n if (!disabled) {\n props.onMouseMove?.(event);\n if (!isMobile) {\n setHover(true);\n trackPointer({ x: event.clientX, y: event.clientY });\n\n if (hasSubmenu && !submenuVisible) {\n showSubmenu();\n }\n }\n }\n }}\n ref={itemRefCallback}\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n >\n {icon && (\n <div className={styles.itemIcon}>\n <IconDefaultPropsContext props={DEFAULT_ICON_PROPS[style]}>\n {icon}\n </IconDefaultPropsContext>\n </div>\n )}\n <div className={styles.itemText}>\n <Text\n ellipsis\n style={TEXT_STYLE[style]}\n typography={isMobile ? 'label-2-regular' : 'label-3-regular'}\n >\n {children}\n </Text>\n {subtitle && (\n <Text ellipsis style={SECONDARY_TEXT_STYLE[style]} typography=\"label-3-regular\">\n {subtitle}\n </Text>\n )}\n </div>\n {tag && (\n <div className={styles.itemTag}>\n {cloneElement(tag as React.ReactElement<TagProps>, { onSurface: hasHover })}\n </div>\n )}\n {selected && (\n <div className={styles.itemRightContent}>\n <CheckOutlinedSize24 initialColor=\"secondary\" />\n </div>\n )}\n {hasSwitch && (\n <div className={styles.itemRightContent} onClick={(event) => event.stopPropagation()}>\n {rightContent}\n </div>\n )}\n {hasSubmenu && (\n <div className={styles.itemRightContent}>\n <Text ellipsis style={SECONDARY_TEXT_STYLE[style]} typography=\"label-3-regular\">\n {rightContent}\n </Text>\n <ChevronRightOutlinedSize24 initialColor=\"secondary\" />\n </div>\n )}\n </div>\n </DisabledWrapper>\n {hasSubmenu && (\n <MenuContext.Provider value={{ ...contextValue, submenuAllowed: false }}>\n <Drop\n {...DROP_PROPS}\n activatorRef={itemRef}\n lockPlacement\n onClose={() => setSubmenuVisible(false)}\n placement={SUBMENU_DROP_PLACEMENT}\n ref={submenuRef}\n visible={visible && submenuVisible}\n >\n {subitems}\n </Drop>\n {mobileSubmenuContainer &&\n createPortal(submenuVisible ? subitems : null, mobileSubmenuContainer)}\n {mobileTitleContainer && createPortal(submenuVisible ? children : null, mobileTitleContainer)}\n </MenuContext.Provider>\n )}\n </>\n );\n }\n);\n\nMenuItem.displayName = 'MenuItem';\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
package/Menu.d.ts CHANGED
@@ -6,7 +6,7 @@ import { MenuQuickAction } from '@hh.ru/magritte-ui-menu/QuickAction';
6
6
  import { MenuQuickActions } from '@hh.ru/magritte-ui-menu/QuickActions';
7
7
  import { MenuSectionHeader } from '@hh.ru/magritte-ui-menu/SectionHeader';
8
8
  import { type MenuProps } from '@hh.ru/magritte-ui-menu/types';
9
- export declare const Menu: React.FC<MenuProps> & {
9
+ interface MenuComponents {
10
10
  BottomSheet: typeof MenuBottomSheet;
11
11
  Divider: typeof MenuDivider;
12
12
  Drop: typeof MenuDrop;
@@ -14,4 +14,6 @@ export declare const Menu: React.FC<MenuProps> & {
14
14
  QuickAction: typeof MenuQuickAction;
15
15
  QuickActions: typeof MenuQuickActions;
16
16
  SectionHeader: typeof MenuSectionHeader;
17
- };
17
+ }
18
+ export declare const Menu: React.FC<MenuProps> & MenuComponents;
19
+ export {};
package/Menu.js CHANGED
@@ -13,22 +13,24 @@ import { MenuQuickActions } from './QuickActions.js';
13
13
  import { MenuSectionHeader } from './SectionHeader.js';
14
14
  import { MenuContext } from './context.js';
15
15
  import { NavBar } from '@hh.ru/magritte-ui-nav-bar';
16
- import { s as styles } from './menu-ChEsgmKq.js';
16
+ import { s as styles } from './menu-DKXKF84l.js';
17
17
  import '@hh.ru/magritte-ui-bottom-sheet';
18
18
  import '@hh.ru/magritte-ui-divider';
19
19
  import '@hh.ru/magritte-ui-drop';
20
20
  import 'react-dom';
21
- import '@hh.ru/magritte-common-func-utils';
22
21
  import '@hh.ru/magritte-common-keyboard';
23
22
  import '@hh.ru/magritte-common-use-multiple-refs';
24
23
  import '@hh.ru/magritte-ui-icon';
25
24
  import './DisabledWrapper.js';
26
25
  import '@hh.ru/magritte-common-use-disabled';
27
26
  import '@hh.ru/magritte-ui-typography';
27
+ import './useSubmenuSafeZone.js';
28
+ import '@hh.ru/magritte-common-func-utils';
29
+ import './safeZone.js';
28
30
  import '@hh.ru/magritte-ui-switch';
29
31
  import '@hh.ru/magritte-ui-section-header';
30
32
 
31
- const Menu = ({ activatorRef, children, onClose, placement, visible, render }) => {
33
+ const Menu = ({ activatorRef, children, onClose, placement, visible, render, }) => {
32
34
  const { isMobile } = useBreakpoint();
33
35
  const mobileMenuContainerRef = useRef(null);
34
36
  const [mobileSubmenuContainer, setMobileSubmenuContainer] = useState(null);
@@ -41,10 +43,10 @@ const Menu = ({ activatorRef, children, onClose, placement, visible, render }) =
41
43
  itemWithVisibleSubmenu,
42
44
  mobileSubmenuContainer,
43
45
  mobileTitleContainer,
44
- onClose: () => {
46
+ onAfterExit: () => {
45
47
  setItemWithVisibleSubmenu(null);
46
- onClose();
47
48
  },
49
+ onClose,
48
50
  placement,
49
51
  setDropContainer,
50
52
  setItemWithVisibleSubmenu,
@@ -57,7 +59,9 @@ const Menu = ({ activatorRef, children, onClose, placement, visible, render }) =
57
59
  return;
58
60
  }
59
61
  mobileMenuContainer.style.height =
60
- itemWithVisibleSubmenu !== null ? `${mobileSubmenuContainer?.offsetHeight ?? 0}px` : ``;
62
+ itemWithVisibleSubmenu !== null && mobileSubmenuContainer !== null
63
+ ? `${mobileSubmenuContainer.offsetHeight}px`
64
+ : ``;
61
65
  }, [itemWithVisibleSubmenu, mobileSubmenuContainer]);
62
66
  if (isMobile) {
63
67
  const mobileChildren = (jsxs("div", { className: classnames(styles.mobileMenuContainer, {
package/Menu.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.js","sources":["src/Menu.tsx"],"sourcesContent":["import { useLayoutEffect, useRef, useState } from 'react';\nimport classnames from 'classnames';\n\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { ChevronLeftOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { MenuBottomSheet } from '@hh.ru/magritte-ui-menu/BottomSheet';\nimport { MenuDivider } from '@hh.ru/magritte-ui-menu/Divider';\nimport { MenuDrop } from '@hh.ru/magritte-ui-menu/Drop';\nimport { MenuItem } from '@hh.ru/magritte-ui-menu/Item';\nimport { MenuQuickAction } from '@hh.ru/magritte-ui-menu/QuickAction';\nimport { MenuQuickActions } from '@hh.ru/magritte-ui-menu/QuickActions';\nimport { MenuSectionHeader } from '@hh.ru/magritte-ui-menu/SectionHeader';\nimport { type MenuContextProps, MenuContext } from '@hh.ru/magritte-ui-menu/context';\nimport { type MenuProps } from '@hh.ru/magritte-ui-menu/types';\nimport { NavBar } from '@hh.ru/magritte-ui-nav-bar';\n\nimport styles from './menu.less';\n\nexport const Menu: React.FC<MenuProps> & {\n BottomSheet: typeof MenuBottomSheet;\n Divider: typeof MenuDivider;\n Drop: typeof MenuDrop;\n Item: typeof MenuItem;\n QuickAction: typeof MenuQuickAction;\n QuickActions: typeof MenuQuickActions;\n SectionHeader: typeof MenuSectionHeader;\n} = ({ activatorRef, children, onClose, placement, visible, render }) => {\n const { isMobile } = useBreakpoint();\n const mobileMenuContainerRef = useRef<HTMLDivElement>(null);\n const [mobileSubmenuContainer, setMobileSubmenuContainer] = useState<HTMLDivElement | null>(null);\n const [mobileTitleContainer, setMobileTitleContainer] = useState<HTMLDivElement | null>(null);\n const [itemWithVisibleSubmenu, setItemWithVisibleSubmenu] = useState<HTMLDivElement | null>(null);\n const [dropContainer, setDropContainer] = useState<HTMLDivElement | null>(null);\n\n const contextValue: MenuContextProps = {\n activatorRef,\n dropContainer,\n itemWithVisibleSubmenu,\n mobileSubmenuContainer,\n mobileTitleContainer,\n onClose: () => {\n setItemWithVisibleSubmenu(null);\n onClose();\n },\n placement,\n setDropContainer,\n setItemWithVisibleSubmenu,\n submenuAllowed: true,\n visible,\n };\n\n useLayoutEffect(() => {\n const mobileMenuContainer = mobileMenuContainerRef.current;\n if (!mobileMenuContainer) {\n return;\n }\n\n mobileMenuContainer.style.height =\n itemWithVisibleSubmenu !== null ? `${mobileSubmenuContainer?.offsetHeight ?? 0}px` : ``;\n }, [itemWithVisibleSubmenu, mobileSubmenuContainer]);\n\n if (isMobile) {\n const mobileChildren = (\n <div\n className={classnames(styles.mobileMenuContainer, {\n [styles.mobileMenuContainerSlide]: itemWithVisibleSubmenu !== null,\n })}\n ref={mobileMenuContainerRef}\n >\n <div className={styles.mobileMainMenuContainer}>{children}</div>\n <div className={styles.mobileSubmenuContainer} ref={setMobileSubmenuContainer} />\n </div>\n );\n\n const closeMobileSubmenu = () => setItemWithVisibleSubmenu(null);\n\n return (\n <MenuContext.Provider value={contextValue}>\n {render ? (\n render({\n children: mobileChildren,\n closeMobileSubmenu,\n mobileSubmenuVisible: itemWithVisibleSubmenu !== null,\n })\n ) : (\n <Menu.BottomSheet\n header={\n itemWithVisibleSubmenu !== null && (\n <NavBar>\n <NavBar.Actions\n centered\n left={<ChevronLeftOutlinedSize24 onClick={closeMobileSubmenu} />}\n >\n <NavBar.TitleContainer centered title={<div ref={setMobileTitleContainer} />} />\n </NavBar.Actions>\n </NavBar>\n )\n }\n >\n {mobileChildren}\n </Menu.BottomSheet>\n )}\n </MenuContext.Provider>\n );\n }\n\n return (\n <MenuContext.Provider value={contextValue}>\n {render ? render({ children }) : <Menu.Drop>{children}</Menu.Drop>}\n </MenuContext.Provider>\n );\n};\n\nMenu.BottomSheet = MenuBottomSheet;\nMenu.Divider = MenuDivider;\nMenu.Drop = MenuDrop;\nMenu.Item = MenuItem;\nMenu.QuickAction = MenuQuickAction;\nMenu.QuickActions = MenuQuickActions;\nMenu.SectionHeader = MenuSectionHeader;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Menu.js","sources":["src/Menu.tsx"],"sourcesContent":["import { useLayoutEffect, useRef, useState } from 'react';\nimport classnames from 'classnames';\n\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { ChevronLeftOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { MenuBottomSheet } from '@hh.ru/magritte-ui-menu/BottomSheet';\nimport { MenuDivider } from '@hh.ru/magritte-ui-menu/Divider';\nimport { MenuDrop } from '@hh.ru/magritte-ui-menu/Drop';\nimport { MenuItem } from '@hh.ru/magritte-ui-menu/Item';\nimport { MenuQuickAction } from '@hh.ru/magritte-ui-menu/QuickAction';\nimport { MenuQuickActions } from '@hh.ru/magritte-ui-menu/QuickActions';\nimport { MenuSectionHeader } from '@hh.ru/magritte-ui-menu/SectionHeader';\nimport { type MenuContextProps, MenuContext } from '@hh.ru/magritte-ui-menu/context';\nimport { type MenuProps } from '@hh.ru/magritte-ui-menu/types';\nimport { NavBar } from '@hh.ru/magritte-ui-nav-bar';\n\nimport styles from './menu.less';\n\ninterface MenuComponents {\n BottomSheet: typeof MenuBottomSheet;\n Divider: typeof MenuDivider;\n Drop: typeof MenuDrop;\n Item: typeof MenuItem;\n QuickAction: typeof MenuQuickAction;\n QuickActions: typeof MenuQuickActions;\n SectionHeader: typeof MenuSectionHeader;\n}\n\nexport const Menu: React.FC<MenuProps> & MenuComponents = ({\n activatorRef,\n children,\n onClose,\n placement,\n visible,\n render,\n}) => {\n const { isMobile } = useBreakpoint();\n const mobileMenuContainerRef = useRef<HTMLDivElement>(null);\n const [mobileSubmenuContainer, setMobileSubmenuContainer] = useState<HTMLDivElement | null>(null);\n const [mobileTitleContainer, setMobileTitleContainer] = useState<HTMLDivElement | null>(null);\n const [itemWithVisibleSubmenu, setItemWithVisibleSubmenu] = useState<HTMLDivElement | null>(null);\n const [dropContainer, setDropContainer] = useState<HTMLDivElement | null>(null);\n\n const contextValue: MenuContextProps = {\n activatorRef,\n dropContainer,\n itemWithVisibleSubmenu,\n mobileSubmenuContainer,\n mobileTitleContainer,\n onAfterExit: () => {\n setItemWithVisibleSubmenu(null);\n },\n onClose,\n placement,\n setDropContainer,\n setItemWithVisibleSubmenu,\n submenuAllowed: true,\n visible,\n };\n\n useLayoutEffect(() => {\n const mobileMenuContainer = mobileMenuContainerRef.current;\n if (!mobileMenuContainer) {\n return;\n }\n\n mobileMenuContainer.style.height =\n itemWithVisibleSubmenu !== null && mobileSubmenuContainer !== null\n ? `${mobileSubmenuContainer.offsetHeight}px`\n : ``;\n }, [itemWithVisibleSubmenu, mobileSubmenuContainer]);\n\n if (isMobile) {\n const mobileChildren = (\n <div\n className={classnames(styles.mobileMenuContainer, {\n [styles.mobileMenuContainerSlide]: itemWithVisibleSubmenu !== null,\n })}\n ref={mobileMenuContainerRef}\n >\n <div className={styles.mobileMainMenuContainer}>{children}</div>\n <div className={styles.mobileSubmenuContainer} ref={setMobileSubmenuContainer} />\n </div>\n );\n\n const closeMobileSubmenu = () => setItemWithVisibleSubmenu(null);\n\n return (\n <MenuContext.Provider value={contextValue}>\n {render ? (\n render({\n children: mobileChildren,\n closeMobileSubmenu,\n mobileSubmenuVisible: itemWithVisibleSubmenu !== null,\n })\n ) : (\n <Menu.BottomSheet\n header={\n itemWithVisibleSubmenu !== null && (\n <NavBar>\n <NavBar.Actions\n centered\n left={<ChevronLeftOutlinedSize24 onClick={closeMobileSubmenu} />}\n >\n <NavBar.TitleContainer centered title={<div ref={setMobileTitleContainer} />} />\n </NavBar.Actions>\n </NavBar>\n )\n }\n >\n {mobileChildren}\n </Menu.BottomSheet>\n )}\n </MenuContext.Provider>\n );\n }\n\n return (\n <MenuContext.Provider value={contextValue}>\n {render ? render({ children }) : <Menu.Drop>{children}</Menu.Drop>}\n </MenuContext.Provider>\n );\n};\n\nMenu.BottomSheet = MenuBottomSheet;\nMenu.Divider = MenuDivider;\nMenu.Drop = MenuDrop;\nMenu.Item = MenuItem;\nMenu.QuickAction = MenuQuickAction;\nMenu.QuickActions = MenuQuickActions;\nMenu.SectionHeader = MenuSectionHeader;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
package/QuickAction.js CHANGED
@@ -4,14 +4,14 @@ import { forwardRef } from 'react';
4
4
  import classnames from 'classnames';
5
5
  import { DisabledWrapper } from './DisabledWrapper.js';
6
6
  import { Text } from '@hh.ru/magritte-ui-typography';
7
- import { s as styles } from './menu-ChEsgmKq.js';
7
+ import { s as styles } from './menu-DKXKF84l.js';
8
8
  import '@hh.ru/magritte-common-use-disabled';
9
9
  import '@hh.ru/magritte-ui-icon';
10
10
 
11
11
  const MenuQuickAction = forwardRef(({ children, className, disabled = false, icon, ...props }, ref) => {
12
12
  return (jsx(DisabledWrapper, { disabled: disabled, children: jsxs("button", { ...props, "aria-disabled": disabled, className: classnames(className, { [styles.disabled]: disabled }, styles.quickAction), disabled: disabled, ref: ref, role: "menuitem", tabIndex: disabled ? -1 : 0, type: "button", children: [icon, jsx("span", { className: styles.quickActionText, children: jsx(Text, { ellipsis: true, typography: "label-4-regular", children: children }) })] }) }));
13
13
  });
14
- MenuQuickAction.displayName = 'Menu.QuickAction';
14
+ MenuQuickAction.displayName = 'MenuQuickAction';
15
15
 
16
16
  export { MenuQuickAction };
17
17
  //# sourceMappingURL=QuickAction.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QuickAction.js","sources":["src/QuickAction.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport classnames from 'classnames';\n\nimport { DisabledWrapper } from '@hh.ru/magritte-ui-menu/DisabledWrapper';\nimport { type MenuQuickActionProps } from '@hh.ru/magritte-ui-menu/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './menu.less';\n\nexport const MenuQuickAction = forwardRef<HTMLButtonElement, MenuQuickActionProps>(\n ({ children, className, disabled = false, icon, ...props }, ref) => {\n return (\n <DisabledWrapper disabled={disabled}>\n <button\n {...props}\n aria-disabled={disabled}\n className={classnames(className, { [styles.disabled]: disabled }, styles.quickAction)}\n disabled={disabled}\n ref={ref}\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n type=\"button\"\n >\n {icon}\n <span className={styles.quickActionText}>\n <Text ellipsis typography=\"label-4-regular\">\n {children}\n </Text>\n </span>\n </button>\n </DisabledWrapper>\n );\n }\n);\n\nMenuQuickAction.displayName = 'Menu.QuickAction';\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;;AASa,MAAA,eAAe,GAAG,UAAU,CACrC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAI;AAC/D,IAAA,QACIA,GAAC,CAAA,eAAe,IAAC,QAAQ,EAAE,QAAQ,EAC/B,QAAA,EAAAC,IAAA,CAAA,QAAA,EAAA,EAAA,GACQ,KAAK,EAAA,eAAA,EACM,QAAQ,EACvB,SAAS,EAAE,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,EACrF,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,UAAU,EACf,QAAQ,EAAE,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,EAC3B,IAAI,EAAC,QAAQ,EAAA,QAAA,EAAA,CAEZ,IAAI,EACLD,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,MAAM,CAAC,eAAe,YACnCA,GAAC,CAAA,IAAI,IAAC,QAAQ,EAAA,IAAA,EAAC,UAAU,EAAC,iBAAiB,YACtC,QAAQ,EAAA,CACN,GACJ,CACF,EAAA,CAAA,EAAA,CACK,EACpB;AACN,CAAC,EACH;AAEF,eAAe,CAAC,WAAW,GAAG,kBAAkB;;;;"}
1
+ {"version":3,"file":"QuickAction.js","sources":["src/QuickAction.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport classnames from 'classnames';\n\nimport { DisabledWrapper } from '@hh.ru/magritte-ui-menu/DisabledWrapper';\nimport { type MenuQuickActionProps } from '@hh.ru/magritte-ui-menu/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './menu.less';\n\nexport const MenuQuickAction = forwardRef<HTMLButtonElement, MenuQuickActionProps>(\n ({ children, className, disabled = false, icon, ...props }, ref) => {\n return (\n <DisabledWrapper disabled={disabled}>\n <button\n {...props}\n aria-disabled={disabled}\n className={classnames(className, { [styles.disabled]: disabled }, styles.quickAction)}\n disabled={disabled}\n ref={ref}\n role=\"menuitem\"\n tabIndex={disabled ? -1 : 0}\n type=\"button\"\n >\n {icon}\n <span className={styles.quickActionText}>\n <Text ellipsis typography=\"label-4-regular\">\n {children}\n </Text>\n </span>\n </button>\n </DisabledWrapper>\n );\n }\n);\n\nMenuQuickAction.displayName = 'MenuQuickAction';\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;;AASa,MAAA,eAAe,GAAG,UAAU,CACrC,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAI;AAC/D,IAAA,QACIA,GAAC,CAAA,eAAe,IAAC,QAAQ,EAAE,QAAQ,EAC/B,QAAA,EAAAC,IAAA,CAAA,QAAA,EAAA,EAAA,GACQ,KAAK,EAAA,eAAA,EACM,QAAQ,EACvB,SAAS,EAAE,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,EACrF,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,UAAU,EACf,QAAQ,EAAE,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,EAC3B,IAAI,EAAC,QAAQ,EAAA,QAAA,EAAA,CAEZ,IAAI,EACLD,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,MAAM,CAAC,eAAe,YACnCA,GAAC,CAAA,IAAI,IAAC,QAAQ,EAAA,IAAA,EAAC,UAAU,EAAC,iBAAiB,YACtC,QAAQ,EAAA,CACN,GACJ,CACF,EAAA,CAAA,EAAA,CACK,EACpB;AACN,CAAC,EACH;AAEF,eAAe,CAAC,WAAW,GAAG,iBAAiB;;;;"}
package/QuickActions.js CHANGED
@@ -2,12 +2,12 @@ import './index.css';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { forwardRef } from 'react';
4
4
  import classnames from 'classnames';
5
- import { s as styles } from './menu-ChEsgmKq.js';
5
+ import { s as styles } from './menu-DKXKF84l.js';
6
6
 
7
7
  const MenuQuickActions = forwardRef(({ children, className, ...props }, ref) => {
8
8
  return (jsx("div", { ...props, className: classnames(className, styles.quickActions), ref: ref, children: children }));
9
9
  });
10
- MenuQuickActions.displayName = 'Menu.QuickActions';
10
+ MenuQuickActions.displayName = 'MenuQuickActions';
11
11
 
12
12
  export { MenuQuickActions };
13
13
  //# sourceMappingURL=QuickActions.js.map