1 | "use strict";
|
2 | 'use client';
|
3 |
|
4 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
5 | var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
6 | Object.defineProperty(exports, "__esModule", {
|
7 | value: true
|
8 | });
|
9 | exports.default = void 0;
|
10 | var React = _interopRequireWildcard(require("react"));
|
11 | var _reactIs = require("react-is");
|
12 | var _propTypes = _interopRequireDefault(require("prop-types"));
|
13 | var _ownerDocument = _interopRequireDefault(require("../utils/ownerDocument"));
|
14 | var _List = _interopRequireDefault(require("../List"));
|
15 | var _getScrollbarSize = _interopRequireDefault(require("../utils/getScrollbarSize"));
|
16 | var _useForkRef = _interopRequireDefault(require("../utils/useForkRef"));
|
17 | var _useEnhancedEffect = _interopRequireDefault(require("../utils/useEnhancedEffect"));
|
18 | var _utils = require("../utils");
|
19 | var _jsxRuntime = require("react/jsx-runtime");
|
20 | function nextItem(list, item, disableListWrap) {
|
21 | if (list === item) {
|
22 | return list.firstChild;
|
23 | }
|
24 | if (item && item.nextElementSibling) {
|
25 | return item.nextElementSibling;
|
26 | }
|
27 | return disableListWrap ? null : list.firstChild;
|
28 | }
|
29 | function previousItem(list, item, disableListWrap) {
|
30 | if (list === item) {
|
31 | return disableListWrap ? list.firstChild : list.lastChild;
|
32 | }
|
33 | if (item && item.previousElementSibling) {
|
34 | return item.previousElementSibling;
|
35 | }
|
36 | return disableListWrap ? null : list.lastChild;
|
37 | }
|
38 | function textCriteriaMatches(nextFocus, textCriteria) {
|
39 | if (textCriteria === undefined) {
|
40 | return true;
|
41 | }
|
42 | let text = nextFocus.innerText;
|
43 | if (text === undefined) {
|
44 |
|
45 | text = nextFocus.textContent;
|
46 | }
|
47 | text = text.trim().toLowerCase();
|
48 | if (text.length === 0) {
|
49 | return false;
|
50 | }
|
51 | if (textCriteria.repeating) {
|
52 | return text[0] === textCriteria.keys[0];
|
53 | }
|
54 | return text.startsWith(textCriteria.keys.join(''));
|
55 | }
|
56 | function moveFocus(list, currentFocus, disableListWrap, disabledItemsFocusable, traversalFunction, textCriteria) {
|
57 | let wrappedOnce = false;
|
58 | let nextFocus = traversalFunction(list, currentFocus, currentFocus ? disableListWrap : false);
|
59 | while (nextFocus) {
|
60 |
|
61 | if (nextFocus === list.firstChild) {
|
62 | if (wrappedOnce) {
|
63 | return false;
|
64 | }
|
65 | wrappedOnce = true;
|
66 | }
|
67 |
|
68 |
|
69 | const nextFocusDisabled = disabledItemsFocusable ? false : nextFocus.disabled || nextFocus.getAttribute('aria-disabled') === 'true';
|
70 | if (!nextFocus.hasAttribute('tabindex') || !textCriteriaMatches(nextFocus, textCriteria) || nextFocusDisabled) {
|
71 |
|
72 | nextFocus = traversalFunction(list, nextFocus, disableListWrap);
|
73 | } else {
|
74 | nextFocus.focus();
|
75 | return true;
|
76 | }
|
77 | }
|
78 | return false;
|
79 | }
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | const MenuList = React.forwardRef(function MenuList(props, ref) {
|
88 | const {
|
89 |
|
90 |
|
91 | actions,
|
92 | autoFocus = false,
|
93 | autoFocusItem = false,
|
94 | children,
|
95 | className,
|
96 | disabledItemsFocusable = false,
|
97 | disableListWrap = false,
|
98 | onKeyDown,
|
99 | variant = 'selectedMenu',
|
100 | ...other
|
101 | } = props;
|
102 | const listRef = React.useRef(null);
|
103 | const textCriteriaRef = React.useRef({
|
104 | keys: [],
|
105 | repeating: true,
|
106 | previousKeyMatched: true,
|
107 | lastTime: null
|
108 | });
|
109 | (0, _useEnhancedEffect.default)(() => {
|
110 | if (autoFocus) {
|
111 | listRef.current.focus();
|
112 | }
|
113 | }, [autoFocus]);
|
114 | React.useImperativeHandle(actions, () => ({
|
115 | adjustStyleForScrollbar: (containerElement, {
|
116 | direction
|
117 | }) => {
|
118 |
|
119 |
|
120 | const noExplicitWidth = !listRef.current.style.width;
|
121 | if (containerElement.clientHeight < listRef.current.clientHeight && noExplicitWidth) {
|
122 | const scrollbarSize = `${(0, _getScrollbarSize.default)((0, _utils.ownerWindow)(containerElement))}px`;
|
123 | listRef.current.style[direction === 'rtl' ? 'paddingLeft' : 'paddingRight'] = scrollbarSize;
|
124 | listRef.current.style.width = `calc(100% + ${scrollbarSize})`;
|
125 | }
|
126 | return listRef.current;
|
127 | }
|
128 | }), []);
|
129 | const handleKeyDown = event => {
|
130 | const list = listRef.current;
|
131 | const key = event.key;
|
132 | const isModifierKeyPressed = event.ctrlKey || event.metaKey || event.altKey;
|
133 | if (isModifierKeyPressed) {
|
134 | if (onKeyDown) {
|
135 | onKeyDown(event);
|
136 | }
|
137 | return;
|
138 | }
|
139 |
|
140 | |
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 | const currentFocus = (0, _ownerDocument.default)(list).activeElement;
|
147 | if (key === 'ArrowDown') {
|
148 |
|
149 | event.preventDefault();
|
150 | moveFocus(list, currentFocus, disableListWrap, disabledItemsFocusable, nextItem);
|
151 | } else if (key === 'ArrowUp') {
|
152 | event.preventDefault();
|
153 | moveFocus(list, currentFocus, disableListWrap, disabledItemsFocusable, previousItem);
|
154 | } else if (key === 'Home') {
|
155 | event.preventDefault();
|
156 | moveFocus(list, null, disableListWrap, disabledItemsFocusable, nextItem);
|
157 | } else if (key === 'End') {
|
158 | event.preventDefault();
|
159 | moveFocus(list, null, disableListWrap, disabledItemsFocusable, previousItem);
|
160 | } else if (key.length === 1) {
|
161 | const criteria = textCriteriaRef.current;
|
162 | const lowerKey = key.toLowerCase();
|
163 | const currTime = performance.now();
|
164 | if (criteria.keys.length > 0) {
|
165 |
|
166 | if (currTime - criteria.lastTime > 500) {
|
167 | criteria.keys = [];
|
168 | criteria.repeating = true;
|
169 | criteria.previousKeyMatched = true;
|
170 | } else if (criteria.repeating && lowerKey !== criteria.keys[0]) {
|
171 | criteria.repeating = false;
|
172 | }
|
173 | }
|
174 | criteria.lastTime = currTime;
|
175 | criteria.keys.push(lowerKey);
|
176 | const keepFocusOnCurrent = currentFocus && !criteria.repeating && textCriteriaMatches(currentFocus, criteria);
|
177 | if (criteria.previousKeyMatched && (keepFocusOnCurrent || moveFocus(list, currentFocus, false, disabledItemsFocusable, nextItem, criteria))) {
|
178 | event.preventDefault();
|
179 | } else {
|
180 | criteria.previousKeyMatched = false;
|
181 | }
|
182 | }
|
183 | if (onKeyDown) {
|
184 | onKeyDown(event);
|
185 | }
|
186 | };
|
187 | const handleRef = (0, _useForkRef.default)(listRef, ref);
|
188 |
|
189 | |
190 |
|
191 |
|
192 |
|
193 |
|
194 | let activeItemIndex = -1;
|
195 |
|
196 |
|
197 |
|
198 | React.Children.forEach(children, (child, index) => {
|
199 | if (! React.isValidElement(child)) {
|
200 | if (activeItemIndex === index) {
|
201 | activeItemIndex += 1;
|
202 | if (activeItemIndex >= children.length) {
|
203 |
|
204 | activeItemIndex = -1;
|
205 | }
|
206 | }
|
207 | return;
|
208 | }
|
209 | if (process.env.NODE_ENV !== 'production') {
|
210 | if ((0, _reactIs.isFragment)(child)) {
|
211 | console.error(["MUI: The Menu component doesn't accept a Fragment as a child.", 'Consider providing an array instead.'].join('\n'));
|
212 | }
|
213 | }
|
214 | if (!child.props.disabled) {
|
215 | if (variant === 'selectedMenu' && child.props.selected) {
|
216 | activeItemIndex = index;
|
217 | } else if (activeItemIndex === -1) {
|
218 | activeItemIndex = index;
|
219 | }
|
220 | }
|
221 | if (activeItemIndex === index && (child.props.disabled || child.props.muiSkipListHighlight || child.type.muiSkipListHighlight)) {
|
222 | activeItemIndex += 1;
|
223 | if (activeItemIndex >= children.length) {
|
224 |
|
225 | activeItemIndex = -1;
|
226 | }
|
227 | }
|
228 | });
|
229 | const items = React.Children.map(children, (child, index) => {
|
230 | if (index === activeItemIndex) {
|
231 | const newChildProps = {};
|
232 | if (autoFocusItem) {
|
233 | newChildProps.autoFocus = true;
|
234 | }
|
235 | if (child.props.tabIndex === undefined && variant === 'selectedMenu') {
|
236 | newChildProps.tabIndex = 0;
|
237 | }
|
238 | return React.cloneElement(child, newChildProps);
|
239 | }
|
240 | return child;
|
241 | });
|
242 | return (0, _jsxRuntime.jsx)(_List.default, {
|
243 | role: "menu",
|
244 | ref: handleRef,
|
245 | className: className,
|
246 | onKeyDown: handleKeyDown,
|
247 | tabIndex: autoFocus ? 0 : -1,
|
248 | ...other,
|
249 | children: items
|
250 | });
|
251 | });
|
252 | process.env.NODE_ENV !== "production" ? MenuList.propTypes = {
|
253 |
|
254 |
|
255 |
|
256 |
|
257 | |
258 |
|
259 |
|
260 |
|
261 | autoFocus: _propTypes.default.bool,
|
262 | |
263 |
|
264 |
|
265 |
|
266 |
|
267 | autoFocusItem: _propTypes.default.bool,
|
268 | |
269 |
|
270 |
|
271 | children: _propTypes.default.node,
|
272 | |
273 |
|
274 |
|
275 | className: _propTypes.default.string,
|
276 | |
277 |
|
278 |
|
279 |
|
280 | disabledItemsFocusable: _propTypes.default.bool,
|
281 | |
282 |
|
283 |
|
284 |
|
285 | disableListWrap: _propTypes.default.bool,
|
286 | |
287 |
|
288 |
|
289 | onKeyDown: _propTypes.default.func,
|
290 | |
291 |
|
292 |
|
293 |
|
294 |
|
295 | variant: _propTypes.default.oneOf(['menu', 'selectedMenu'])
|
296 | } : void 0;
|
297 | var _default = exports.default = MenuList; |
\ | No newline at end of file |