1 | import _extends from "@babel/runtime/helpers/esm/extends";
|
2 | import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
3 | import * as React from 'react';
|
4 | import { isFragment } from 'react-is';
|
5 | import PropTypes from 'prop-types';
|
6 | import clsx from 'clsx';
|
7 | import { HTMLElementType } from '@material-ui/utils';
|
8 | import withStyles from '../styles/withStyles';
|
9 | import Popover from '../Popover';
|
10 | import MenuList from '../MenuList';
|
11 | import * as ReactDOM from 'react-dom';
|
12 | import setRef from '../utils/setRef';
|
13 | import useTheme from '../styles/useTheme';
|
14 | import deprecatedPropType from '../utils/deprecatedPropType';
|
15 | const RTL_ORIGIN = {
|
16 | vertical: 'top',
|
17 | horizontal: 'right'
|
18 | };
|
19 | const LTR_ORIGIN = {
|
20 | vertical: 'top',
|
21 | horizontal: 'left'
|
22 | };
|
23 | export const styles = {
|
24 |
|
25 | paper: {
|
26 |
|
27 |
|
28 |
|
29 | maxHeight: 'calc(100% - 96px)',
|
30 |
|
31 | WebkitOverflowScrolling: 'touch'
|
32 | },
|
33 |
|
34 |
|
35 | list: {
|
36 |
|
37 | outline: 0
|
38 | }
|
39 | };
|
40 | const Menu = React.forwardRef(function Menu(props, ref) {
|
41 | const {
|
42 | autoFocus = true,
|
43 | children,
|
44 | classes,
|
45 | disableAutoFocusItem = false,
|
46 | MenuListProps = {},
|
47 | onClose,
|
48 | onEntering: onEnteringProp,
|
49 | open,
|
50 | PaperProps = {},
|
51 | PopoverClasses,
|
52 | transitionDuration = 'auto',
|
53 | TransitionProps: {
|
54 | onEntering
|
55 | } = {},
|
56 | variant = 'selectedMenu'
|
57 | } = props,
|
58 | TransitionProps = _objectWithoutPropertiesLoose(props.TransitionProps, ["onEntering"]),
|
59 | other = _objectWithoutPropertiesLoose(props, ["autoFocus", "children", "classes", "disableAutoFocusItem", "MenuListProps", "onClose", "onEntering", "open", "PaperProps", "PopoverClasses", "transitionDuration", "TransitionProps", "variant"]);
|
60 |
|
61 | const theme = useTheme();
|
62 | const autoFocusItem = autoFocus && !disableAutoFocusItem && open;
|
63 | const menuListActionsRef = React.useRef(null);
|
64 | const contentAnchorRef = React.useRef(null);
|
65 |
|
66 | const getContentAnchorEl = () => contentAnchorRef.current;
|
67 |
|
68 | const handleEntering = (element, isAppearing) => {
|
69 | if (menuListActionsRef.current) {
|
70 | menuListActionsRef.current.adjustStyleForScrollbar(element, theme);
|
71 | }
|
72 |
|
73 | if (onEnteringProp) {
|
74 | onEnteringProp(element, isAppearing);
|
75 | }
|
76 |
|
77 | if (onEntering) {
|
78 | onEntering(element, isAppearing);
|
79 | }
|
80 | };
|
81 |
|
82 | const handleListKeyDown = event => {
|
83 | if (event.key === 'Tab') {
|
84 | event.preventDefault();
|
85 |
|
86 | if (onClose) {
|
87 | onClose(event, 'tabKeyDown');
|
88 | }
|
89 | }
|
90 | };
|
91 | |
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 | let activeItemIndex = -1;
|
99 |
|
100 |
|
101 |
|
102 | React.Children.map(children, (child, index) => {
|
103 | if (! React.isValidElement(child)) {
|
104 | return;
|
105 | }
|
106 |
|
107 | if (process.env.NODE_ENV !== 'production') {
|
108 | if (isFragment(child)) {
|
109 | console.error(["Material-UI: The Menu component doesn't accept a Fragment as a child.", 'Consider providing an array instead.'].join('\n'));
|
110 | }
|
111 | }
|
112 |
|
113 | if (!child.props.disabled) {
|
114 | if (variant !== "menu" && child.props.selected) {
|
115 | activeItemIndex = index;
|
116 | } else if (activeItemIndex === -1) {
|
117 | activeItemIndex = index;
|
118 | }
|
119 | }
|
120 | });
|
121 | const items = React.Children.map(children, (child, index) => {
|
122 | if (index === activeItemIndex) {
|
123 | return React.cloneElement(child, {
|
124 | ref: instance => {
|
125 |
|
126 | contentAnchorRef.current = ReactDOM.findDOMNode(instance);
|
127 | setRef(child.ref, instance);
|
128 | }
|
129 | });
|
130 | }
|
131 |
|
132 | return child;
|
133 | });
|
134 | return React.createElement(Popover, _extends({
|
135 | getContentAnchorEl: getContentAnchorEl,
|
136 | classes: PopoverClasses,
|
137 | onClose: onClose,
|
138 | TransitionProps: _extends({
|
139 | onEntering: handleEntering
|
140 | }, TransitionProps),
|
141 | anchorOrigin: theme.direction === 'rtl' ? RTL_ORIGIN : LTR_ORIGIN,
|
142 | transformOrigin: theme.direction === 'rtl' ? RTL_ORIGIN : LTR_ORIGIN,
|
143 | PaperProps: _extends({}, PaperProps, {
|
144 | classes: _extends({}, PaperProps.classes, {
|
145 | root: classes.paper
|
146 | })
|
147 | }),
|
148 | open: open,
|
149 | ref: ref,
|
150 | transitionDuration: transitionDuration
|
151 | }, other), React.createElement(MenuList, _extends({
|
152 | onKeyDown: handleListKeyDown,
|
153 | actions: menuListActionsRef,
|
154 | autoFocus: autoFocus && (activeItemIndex === -1 || disableAutoFocusItem),
|
155 | autoFocusItem: autoFocusItem,
|
156 | variant: variant
|
157 | }, MenuListProps, {
|
158 | className: clsx(classes.list, MenuListProps.className)
|
159 | }), items));
|
160 | });
|
161 | process.env.NODE_ENV !== "production" ? Menu.propTypes = {
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 | |
168 |
|
169 |
|
170 |
|
171 | anchorEl: PropTypes
|
172 |
|
173 | .oneOfType([HTMLElementType, PropTypes.func]),
|
174 |
|
175 | |
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 | autoFocus: PropTypes.bool,
|
182 |
|
183 | |
184 |
|
185 |
|
186 | children: PropTypes.node,
|
187 |
|
188 | |
189 |
|
190 |
|
191 |
|
192 | classes: PropTypes.object,
|
193 |
|
194 | |
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | disableAutoFocusItem: PropTypes.bool,
|
201 |
|
202 | |
203 |
|
204 |
|
205 | MenuListProps: PropTypes.object,
|
206 |
|
207 | |
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 | onClose: PropTypes.func,
|
214 |
|
215 | |
216 |
|
217 |
|
218 |
|
219 | onEnter: deprecatedPropType(PropTypes.func, 'Use the `TransitionProps` prop instead.'),
|
220 |
|
221 | |
222 |
|
223 |
|
224 |
|
225 | onEntered: deprecatedPropType(PropTypes.func, 'Use the `TransitionProps` prop instead.'),
|
226 |
|
227 | |
228 |
|
229 |
|
230 |
|
231 | onEntering: deprecatedPropType(PropTypes.func, 'Use the `TransitionProps` prop instead.'),
|
232 |
|
233 | |
234 |
|
235 |
|
236 |
|
237 | onExit: deprecatedPropType(PropTypes.func, 'Use the `TransitionProps` prop instead.'),
|
238 |
|
239 | |
240 |
|
241 |
|
242 |
|
243 | onExited: deprecatedPropType(PropTypes.func, 'Use the `TransitionProps` prop instead.'),
|
244 |
|
245 | |
246 |
|
247 |
|
248 |
|
249 | onExiting: deprecatedPropType(PropTypes.func, 'Use the `TransitionProps` prop instead.'),
|
250 |
|
251 | |
252 |
|
253 |
|
254 | open: PropTypes.bool.isRequired,
|
255 |
|
256 | |
257 |
|
258 |
|
259 | PaperProps: PropTypes.object,
|
260 |
|
261 | |
262 |
|
263 |
|
264 | PopoverClasses: PropTypes.object,
|
265 |
|
266 | |
267 |
|
268 |
|
269 | transitionDuration: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.shape({
|
270 | appear: PropTypes.number,
|
271 | enter: PropTypes.number,
|
272 | exit: PropTypes.number
|
273 | })]),
|
274 |
|
275 | |
276 |
|
277 |
|
278 |
|
279 | TransitionProps: PropTypes.object,
|
280 |
|
281 | |
282 |
|
283 |
|
284 |
|
285 | variant: PropTypes.oneOf(['menu', 'selectedMenu'])
|
286 | } : void 0;
|
287 | export default withStyles(styles, {
|
288 | name: 'MuiMenu'
|
289 | })(Menu); |
\ | No newline at end of file |