carbon-react 114.13.1 → 114.13.2
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/esm/__internal__/input-icon-toggle/input-icon-toggle.component.js +2 -1
- package/esm/components/link/link.component.d.ts +2 -0
- package/esm/components/link/link.component.js +7 -1
- package/esm/components/menu/__internal__/keyboard-navigation/index.d.ts +4 -2
- package/esm/components/menu/__internal__/keyboard-navigation/index.js +16 -15
- package/esm/components/menu/__internal__/locators.d.ts +6 -0
- package/esm/components/menu/__internal__/locators.js +6 -0
- package/esm/components/menu/__internal__/submenu/submenu.component.js +109 -108
- package/esm/components/menu/menu-full-screen/menu-full-screen.component.js +1 -2
- package/esm/components/menu/menu-item/index.js +0 -1
- package/esm/components/menu/menu-item/menu-item.component.js +77 -51
- package/esm/components/menu/menu-item/menu-item.d.ts +7 -3
- package/esm/components/menu/menu.component.js +33 -37
- package/esm/components/menu/menu.context.d.ts +2 -2
- package/esm/components/menu/menu.context.js +2 -2
- package/esm/components/menu/scrollable-block/scrollable-block.component.js +6 -24
- package/lib/__internal__/input-icon-toggle/input-icon-toggle.component.js +2 -1
- package/lib/components/link/link.component.d.ts +2 -0
- package/lib/components/link/link.component.js +7 -1
- package/lib/components/menu/__internal__/keyboard-navigation/index.d.ts +4 -2
- package/lib/components/menu/__internal__/keyboard-navigation/index.js +16 -15
- package/lib/components/menu/__internal__/locators.d.ts +6 -0
- package/lib/components/menu/__internal__/locators.js +18 -0
- package/lib/components/menu/__internal__/submenu/submenu.component.js +111 -113
- package/lib/components/menu/menu-full-screen/menu-full-screen.component.js +1 -2
- package/lib/components/menu/menu-item/menu-item.component.js +76 -52
- package/lib/components/menu/menu-item/menu-item.d.ts +7 -3
- package/lib/components/menu/menu.component.js +33 -37
- package/lib/components/menu/menu.context.d.ts +2 -2
- package/lib/components/menu/menu.context.js +2 -2
- package/lib/components/menu/scrollable-block/scrollable-block.component.js +6 -25
- package/package.json +1 -1
|
@@ -19,16 +19,16 @@ var _events = _interopRequireDefault(require("../../../../__internal__/utils/hel
|
|
|
19
19
|
|
|
20
20
|
var _menu = _interopRequireDefault(require("../../menu.context"));
|
|
21
21
|
|
|
22
|
-
var _menuItem2 = _interopRequireDefault(require("../../menu-item"));
|
|
23
|
-
|
|
24
22
|
var _keyboardNavigation = require("../keyboard-navigation");
|
|
25
23
|
|
|
26
|
-
var _scrollableBlock = _interopRequireDefault(require("../../scrollable-block"));
|
|
27
|
-
|
|
28
24
|
var _submenu2 = _interopRequireDefault(require("./submenu.context"));
|
|
29
25
|
|
|
30
26
|
var _useClickAwayListener = _interopRequireDefault(require("../../../../hooks/__internal__/useClickAwayListener"));
|
|
31
27
|
|
|
28
|
+
var _guid = _interopRequireDefault(require("../../../../__internal__/utils/helpers/guid"));
|
|
29
|
+
|
|
30
|
+
var _locators = require("../locators");
|
|
31
|
+
|
|
32
32
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
33
33
|
|
|
34
34
|
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
@@ -53,50 +53,44 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
53
53
|
onSubmenuOpen,
|
|
54
54
|
onSubmenuClose,
|
|
55
55
|
onClick,
|
|
56
|
-
indexInMenu,
|
|
57
56
|
...rest
|
|
58
57
|
}, ref) => {
|
|
59
|
-
const
|
|
58
|
+
const submenuRef = (0, _react.useRef)(null);
|
|
59
|
+
const submenuId = (0, _react.useRef)((0, _guid.default)());
|
|
60
60
|
const menuContext = (0, _react.useContext)(_menu.default);
|
|
61
61
|
const {
|
|
62
62
|
inFullscreenView,
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
openSubmenuId,
|
|
64
|
+
setOpenSubmenuId
|
|
65
65
|
} = menuContext;
|
|
66
66
|
const [submenuOpen, setSubmenuOpen] = (0, _react.useState)(false);
|
|
67
|
-
const [
|
|
67
|
+
const [submenuFocusId, setSubmenuFocusId] = (0, _react.useState)(null);
|
|
68
|
+
const [submenuItemIds, setSubmenuItemIds] = (0, _react.useState)([]);
|
|
68
69
|
const [characterString, setCharacterString] = (0, _react.useState)("");
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return child;
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const arrayOfFormattedChildren = _react.default.Children.toArray(formattedChildren);
|
|
85
|
-
|
|
86
|
-
const numberOfChildren = (0, _react.useMemo)(() => _react.default.Children.count(formattedChildren), [formattedChildren]);
|
|
70
|
+
const shiftTabPressed = (0, _react.useRef)(false);
|
|
71
|
+
const registerItem = (0, _react.useCallback)(id => {
|
|
72
|
+
setSubmenuItemIds(prevState => {
|
|
73
|
+
return [...prevState, id];
|
|
74
|
+
});
|
|
75
|
+
}, []);
|
|
76
|
+
const unregisterItem = (0, _react.useCallback)(id => {
|
|
77
|
+
setSubmenuItemIds(prevState => {
|
|
78
|
+
return prevState.filter(itemId => itemId !== id);
|
|
79
|
+
});
|
|
80
|
+
}, []);
|
|
81
|
+
const numberOfChildren = submenuItemIds.length;
|
|
87
82
|
const blockIndex = (0, _react.useMemo)(() => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const childrenArray = _react.default.Children.toArray(children);
|
|
83
|
+
if (submenuOpen && numberOfChildren) {
|
|
84
|
+
var _submenuRef$current, _submenuRef$current2;
|
|
91
85
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
index
|
|
86
|
+
const childrenArray = Array.from((_submenuRef$current = submenuRef.current) === null || _submenuRef$current === void 0 ? void 0 : _submenuRef$current.querySelectorAll(_locators.BLOCK_INDEX_SELECTOR));
|
|
87
|
+
const scrollableBlock = (_submenuRef$current2 = submenuRef.current) === null || _submenuRef$current2 === void 0 ? void 0 : _submenuRef$current2.querySelector(`[data-component='${_locators.SCROLLABLE_BLOCK}']`);
|
|
88
|
+
const index = childrenArray.indexOf(scrollableBlock);
|
|
89
|
+
return scrollableBlock !== null && scrollableBlock !== void 0 && scrollableBlock.querySelector(`[data-component='${_locators.SCROLLABLE_BLOCK_PARENT}']`) ? index + 1 : index;
|
|
96
90
|
}
|
|
97
91
|
|
|
98
|
-
return
|
|
99
|
-
}, [
|
|
92
|
+
return -1;
|
|
93
|
+
}, [submenuOpen, numberOfChildren]);
|
|
100
94
|
const characterTimer = (0, _react.useRef)();
|
|
101
95
|
const startCharacterTimeout = (0, _react.useCallback)(() => {
|
|
102
96
|
characterTimer.current = setTimeout(() => {
|
|
@@ -109,83 +103,88 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
109
103
|
}, [startCharacterTimeout]);
|
|
110
104
|
const openSubmenu = (0, _react.useCallback)(() => {
|
|
111
105
|
setSubmenuOpen(true);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
106
|
+
setOpenSubmenuId(submenuId.current);
|
|
107
|
+
|
|
108
|
+
if (onSubmenuOpen) {
|
|
109
|
+
onSubmenuOpen();
|
|
110
|
+
}
|
|
111
|
+
}, [onSubmenuOpen, setOpenSubmenuId]);
|
|
115
112
|
const closeSubmenu = (0, _react.useCallback)(() => {
|
|
113
|
+
shiftTabPressed.current = false;
|
|
116
114
|
setSubmenuOpen(false);
|
|
115
|
+
setSubmenuFocusId(null);
|
|
117
116
|
|
|
118
|
-
if (
|
|
119
|
-
|
|
117
|
+
if (onSubmenuClose) {
|
|
118
|
+
onSubmenuClose();
|
|
120
119
|
}
|
|
121
120
|
|
|
122
|
-
if (onSubmenuClose) onSubmenuClose();
|
|
123
|
-
setSubmenuFocusIndex(undefined);
|
|
124
|
-
setBlockDoubleFocus(false);
|
|
125
121
|
setCharacterString("");
|
|
126
|
-
}, [onSubmenuClose
|
|
122
|
+
}, [onSubmenuClose]);
|
|
127
123
|
(0, _react.useEffect)(() => {
|
|
128
|
-
if (
|
|
124
|
+
if (openSubmenuId && openSubmenuId !== submenuId.current) {
|
|
129
125
|
closeSubmenu();
|
|
130
126
|
}
|
|
131
|
-
}, [
|
|
132
|
-
const
|
|
127
|
+
}, [openSubmenuId, closeSubmenu]);
|
|
128
|
+
const findCurrentIndex = (0, _react.useCallback)(id => {
|
|
129
|
+
const index = submenuItemIds.findIndex(itemId => itemId === id);
|
|
130
|
+
return index === -1 ? 0 : index;
|
|
131
|
+
}, [submenuItemIds]);
|
|
132
|
+
const handleKeyDown = (0, _react.useCallback)(event => {
|
|
133
133
|
if (!submenuOpen) {
|
|
134
134
|
if (_events.default.isEnterKey(event) || _events.default.isSpaceKey(event) || _events.default.isDownKey(event) || _events.default.isUpKey(event)) {
|
|
135
135
|
event.preventDefault();
|
|
136
136
|
openSubmenu();
|
|
137
|
-
|
|
138
|
-
if (!href) {
|
|
139
|
-
setSubmenuFocusIndex(0);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (!event.defaultPrevented) {
|
|
144
|
-
menuContext.handleKeyDown(event);
|
|
145
137
|
}
|
|
146
138
|
}
|
|
147
139
|
|
|
148
140
|
if (submenuOpen) {
|
|
141
|
+
const index = findCurrentIndex(submenuFocusId);
|
|
149
142
|
let nextIndex = index;
|
|
150
143
|
|
|
144
|
+
if (href && !submenuFocusId) {
|
|
145
|
+
if (_events.default.isDownKey(event) || _events.default.isUpKey(event) || _events.default.isTabKey(event) && !_events.default.isShiftKey(event)) {
|
|
146
|
+
event.preventDefault();
|
|
147
|
+
setSubmenuFocusId(submenuItemIds[0]);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
151
152
|
if (_events.default.isTabKey(event) && !_events.default.isShiftKey(event)) {
|
|
152
|
-
if (
|
|
153
|
+
if (nextIndex === numberOfChildren - 1) {
|
|
153
154
|
closeSubmenu();
|
|
154
155
|
return;
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
shiftTabPressed.current = false;
|
|
159
|
+
nextIndex += 1;
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
if (_events.default.isTabKey(event) && _events.default.isShiftKey(event)) {
|
|
162
|
-
if (
|
|
163
|
+
if (nextIndex === 0) {
|
|
163
164
|
closeSubmenu();
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
shiftTabPressed.current = true;
|
|
169
|
+
nextIndex -= 1;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
if (_events.default.isDownKey(event)) {
|
|
172
173
|
event.preventDefault();
|
|
174
|
+
shiftTabPressed.current = false;
|
|
173
175
|
|
|
174
|
-
if (
|
|
175
|
-
nextIndex
|
|
176
|
+
if (nextIndex < numberOfChildren - 1) {
|
|
177
|
+
nextIndex += 1;
|
|
176
178
|
}
|
|
177
|
-
|
|
178
|
-
setBlockDoubleFocus(false);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
if (_events.default.isUpKey(event)) {
|
|
182
182
|
event.preventDefault();
|
|
183
|
+
shiftTabPressed.current = false;
|
|
183
184
|
|
|
184
|
-
if (
|
|
185
|
-
nextIndex
|
|
185
|
+
if (nextIndex > 0) {
|
|
186
|
+
nextIndex -= 1;
|
|
186
187
|
}
|
|
187
|
-
|
|
188
|
-
setBlockDoubleFocus(false);
|
|
189
188
|
}
|
|
190
189
|
|
|
191
190
|
if (_events.default.isEscKey(event)) {
|
|
@@ -196,16 +195,19 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
196
195
|
|
|
197
196
|
if (_events.default.isHomeKey(event)) {
|
|
198
197
|
event.preventDefault();
|
|
198
|
+
shiftTabPressed.current = false;
|
|
199
199
|
nextIndex = 0;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
if (_events.default.isEndKey(event)) {
|
|
203
203
|
event.preventDefault();
|
|
204
|
+
shiftTabPressed.current = false;
|
|
204
205
|
nextIndex = numberOfChildren - 1;
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
if (event.key.length === 1) {
|
|
208
209
|
event.stopPropagation();
|
|
210
|
+
shiftTabPressed.current = false;
|
|
209
211
|
|
|
210
212
|
if (characterTimer.current) {
|
|
211
213
|
restartCharacterTimeout();
|
|
@@ -224,31 +226,21 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
224
226
|
setTimeout(() => closeSubmenu());
|
|
225
227
|
}
|
|
226
228
|
|
|
227
|
-
if (href &&
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (_events.default.isSpaceKey(event) || _events.default.isDownKey(event) || _events.default.isUpKey(event) || _events.default.isTabKey(event)) {
|
|
234
|
-
nextIndex = 0;
|
|
235
|
-
}
|
|
236
|
-
} // Defensive check in case an unhandled key event from a child component
|
|
237
|
-
// has bubbled up
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (!nextIndex && nextIndex !== 0) return; // Check that next index contains a MenuItem
|
|
241
|
-
// If not, call handleKeyDown again
|
|
242
|
-
|
|
243
|
-
const nextChild = arrayOfFormattedChildren[nextIndex];
|
|
229
|
+
if (href && _events.default.isEnterKey(event)) {
|
|
230
|
+
closeSubmenu();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
244
233
|
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
} else {
|
|
248
|
-
handleKeyDown(event, nextIndex);
|
|
234
|
+
if (nextIndex !== index) {
|
|
235
|
+
setSubmenuFocusId(submenuItemIds[nextIndex]);
|
|
249
236
|
}
|
|
250
237
|
}
|
|
251
|
-
}, [
|
|
238
|
+
}, [submenuItemIds, submenuOpen, href, numberOfChildren, submenuFocusId, findCurrentIndex, openSubmenu, closeSubmenu, onKeyDown, characterString, restartCharacterTimeout, startCharacterTimeout]);
|
|
239
|
+
(0, _react.useEffect)(() => {
|
|
240
|
+
if (submenuOpen && !href && !submenuFocusId && submenuItemIds.length) {
|
|
241
|
+
setSubmenuFocusId(submenuItemIds[0]);
|
|
242
|
+
}
|
|
243
|
+
}, [submenuOpen, href, submenuFocusId, submenuItemIds]);
|
|
252
244
|
|
|
253
245
|
const handleClickAway = () => {
|
|
254
246
|
document.removeEventListener("click", handleClickAway);
|
|
@@ -265,11 +257,16 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
265
257
|
|
|
266
258
|
(0, _react.useEffect)(() => {
|
|
267
259
|
if (characterString !== "") {
|
|
268
|
-
|
|
269
|
-
setSubmenuFocusIndex(nextIndex);
|
|
270
|
-
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
260
|
+
var _submenuRef$current3;
|
|
271
261
|
|
|
272
|
-
|
|
262
|
+
const submenuChildren = Array.from((_submenuRef$current3 = submenuRef.current) === null || _submenuRef$current3 === void 0 ? void 0 : _submenuRef$current3.querySelectorAll(_locators.ALL_CHILDREN_SELECTOR));
|
|
263
|
+
const nextItem = (0, _keyboardNavigation.characterNavigation)(characterString, submenuChildren);
|
|
264
|
+
|
|
265
|
+
if (nextItem) {
|
|
266
|
+
setSubmenuFocusId(nextItem.id);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}, [characterString, submenuItemIds]);
|
|
273
270
|
const handleClickInside = (0, _useClickAwayListener.default)(handleClickAway);
|
|
274
271
|
|
|
275
272
|
if (inFullscreenView) {
|
|
@@ -293,15 +290,17 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
293
290
|
"data-component": "submenu",
|
|
294
291
|
variant: variant,
|
|
295
292
|
menuType: menuContext.menuType,
|
|
296
|
-
inFullscreenView: inFullscreenView
|
|
297
|
-
|
|
293
|
+
inFullscreenView: inFullscreenView,
|
|
294
|
+
ref: submenuRef
|
|
295
|
+
}, /*#__PURE__*/_react.default.createElement(_submenu2.default.Provider, {
|
|
298
296
|
value: {
|
|
299
|
-
isFocused: submenuFocusIndex === index,
|
|
300
|
-
focusIndex: submenuFocusIndex,
|
|
301
297
|
handleKeyDown,
|
|
302
|
-
blockIndex
|
|
298
|
+
blockIndex,
|
|
299
|
+
registerItem,
|
|
300
|
+
unregisterItem,
|
|
301
|
+
updateFocusId: setSubmenuFocusId
|
|
303
302
|
}
|
|
304
|
-
},
|
|
303
|
+
}, children)));
|
|
305
304
|
}
|
|
306
305
|
|
|
307
306
|
return /*#__PURE__*/_react.default.createElement(_submenu.StyledSubmenuWrapper, {
|
|
@@ -309,7 +308,8 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
309
308
|
onMouseOver: !clickToOpen ? () => openSubmenu() : undefined,
|
|
310
309
|
onMouseLeave: () => closeSubmenu(),
|
|
311
310
|
isSubmenuOpen: submenuOpen,
|
|
312
|
-
onClick: handleClickInside
|
|
311
|
+
onClick: handleClickInside,
|
|
312
|
+
ref: submenuRef
|
|
313
313
|
}, /*#__PURE__*/_react.default.createElement(_menuItem.default, _extends({}, rest, {
|
|
314
314
|
className: className,
|
|
315
315
|
menuType: menuContext.menuType,
|
|
@@ -333,16 +333,17 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
333
333
|
variant: variant,
|
|
334
334
|
menuType: menuContext.menuType,
|
|
335
335
|
role: blockIndex === 0 ? "presentation" : "list"
|
|
336
|
-
},
|
|
336
|
+
}, /*#__PURE__*/_react.default.createElement(_submenu2.default.Provider, {
|
|
337
337
|
value: {
|
|
338
|
-
|
|
339
|
-
focusIndex: submenuFocusIndex,
|
|
338
|
+
submenuFocusId,
|
|
340
339
|
handleKeyDown,
|
|
341
340
|
blockIndex,
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
registerItem,
|
|
342
|
+
unregisterItem,
|
|
343
|
+
updateFocusId: setSubmenuFocusId,
|
|
344
|
+
shiftTabPressed: shiftTabPressed.current
|
|
344
345
|
}
|
|
345
|
-
},
|
|
346
|
+
}, children)));
|
|
346
347
|
});
|
|
347
348
|
|
|
348
349
|
Submenu.propTypes = {
|
|
@@ -393,10 +394,7 @@ Submenu.propTypes = {
|
|
|
393
394
|
onSubmenuClose: _propTypes.default.func,
|
|
394
395
|
|
|
395
396
|
/** Callback triggered when the top-level menu item is clicked */
|
|
396
|
-
onClick: _propTypes.default.func
|
|
397
|
-
|
|
398
|
-
/** index of child in the parent menu */
|
|
399
|
-
indexInMenu: _propTypes.default.number
|
|
397
|
+
onClick: _propTypes.default.func
|
|
400
398
|
};
|
|
401
399
|
var _default = Submenu;
|
|
402
400
|
exports.default = _default;
|
|
@@ -109,8 +109,7 @@ const MenuFullscreen = ({
|
|
|
109
109
|
value: {
|
|
110
110
|
inFullscreenView: true,
|
|
111
111
|
menuType,
|
|
112
|
-
inMenu: true
|
|
113
|
-
setOpenSubmenuIndex: () => {}
|
|
112
|
+
inMenu: true
|
|
114
113
|
}
|
|
115
114
|
}, _react.default.Children.map(children, (child, index) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, child, index < _react.default.Children.count(children) - 1 && /*#__PURE__*/_react.default.createElement(_menuDivider.default, null))))))))));
|
|
116
115
|
};
|
|
@@ -27,7 +27,7 @@ var _submenu2 = _interopRequireDefault(require("../__internal__/submenu/submenu.
|
|
|
27
27
|
|
|
28
28
|
var _menu2 = require("../menu.style");
|
|
29
29
|
|
|
30
|
-
var
|
|
30
|
+
var _guid = _interopRequireDefault(require("../../../__internal__/utils/helpers/guid"));
|
|
31
31
|
|
|
32
32
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
33
33
|
|
|
@@ -57,43 +57,70 @@ const MenuItem = ({
|
|
|
57
57
|
onSubmenuClose,
|
|
58
58
|
overrideColor,
|
|
59
59
|
rel,
|
|
60
|
-
isFocused,
|
|
61
60
|
...rest
|
|
62
61
|
}) => {
|
|
63
|
-
|
|
62
|
+
var _ref$current, _ref$current2;
|
|
63
|
+
|
|
64
|
+
const {
|
|
65
|
+
inFullscreenView,
|
|
66
|
+
registerItem,
|
|
67
|
+
unregisterItem,
|
|
68
|
+
focusId,
|
|
69
|
+
menuType,
|
|
70
|
+
openSubmenuId
|
|
71
|
+
} = (0, _react.useContext)(_menu.default);
|
|
72
|
+
const menuItemId = (0, _react.useRef)((0, _guid.default)());
|
|
64
73
|
const submenuContext = (0, _react.useContext)(_submenu2.default);
|
|
65
|
-
const ref = (0, _react.useRef)(null);
|
|
66
|
-
const focusFromMenu = isFocused;
|
|
67
|
-
const focusFromSubmenu = submenuContext.isFocused;
|
|
68
|
-
const isChildSearch = (0, _react.useRef)(false);
|
|
69
|
-
const childRef = (0, _react.useRef)();
|
|
70
74
|
const {
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
registerItem: registerSubmenuItem,
|
|
76
|
+
unregisterItem: unregisterSubmenuItem,
|
|
77
|
+
submenuFocusId,
|
|
78
|
+
updateFocusId: updateSubmenuFocusId,
|
|
79
|
+
handleKeyDown: handleSubmenuKeyDown,
|
|
80
|
+
shiftTabPressed
|
|
81
|
+
} = submenuContext;
|
|
82
|
+
const ref = (0, _react.useRef)(null);
|
|
83
|
+
const focusFromMenu = focusId === menuItemId.current;
|
|
84
|
+
const focusFromSubmenu = submenuFocusId ? submenuFocusId === menuItemId.current : undefined;
|
|
85
|
+
const inputRef = (0, _react.useRef)(null);
|
|
86
|
+
const inputIcon = (0, _react.useRef)(null);
|
|
87
|
+
inputIcon.current = (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.querySelector("[data-element='input-icon-toggle']");
|
|
88
|
+
inputRef.current = (_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.querySelector("[data-element='input']");
|
|
89
|
+
const focusRef = inputRef.current ? inputRef : ref;
|
|
90
|
+
(0, _react.useEffect)(() => {
|
|
91
|
+
const id = menuItemId.current;
|
|
73
92
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
if (registerSubmenuItem) {
|
|
94
|
+
registerSubmenuItem(id);
|
|
95
|
+
} else if (registerItem) {
|
|
96
|
+
registerItem(id);
|
|
77
97
|
}
|
|
78
98
|
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
return () => {
|
|
100
|
+
if (unregisterSubmenuItem) {
|
|
101
|
+
unregisterSubmenuItem(id);
|
|
102
|
+
} else if (unregisterItem) {
|
|
103
|
+
unregisterItem(id);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}, [registerSubmenuItem, registerItem, unregisterSubmenuItem, unregisterItem]);
|
|
83
107
|
(0, _react.useEffect)(() => {
|
|
84
|
-
|
|
108
|
+
var _inputIcon$current;
|
|
109
|
+
|
|
110
|
+
if (!openSubmenuId && focusFromSubmenu === undefined && focusFromMenu) {
|
|
85
111
|
focusRef.current.focus();
|
|
86
|
-
} else if (focusFromSubmenu) {
|
|
112
|
+
} else if (focusFromSubmenu && !(shiftTabPressed && ((_inputIcon$current = inputIcon.current) === null || _inputIcon$current === void 0 ? void 0 : _inputIcon$current.getAttribute("tabindex")) === "0")) {
|
|
87
113
|
focusRef.current.focus();
|
|
88
114
|
}
|
|
89
|
-
}, [focusFromMenu, focusFromSubmenu, focusRef]);
|
|
115
|
+
}, [openSubmenuId, focusFromMenu, focusFromSubmenu, inputIcon, shiftTabPressed, focusRef]);
|
|
90
116
|
const updateFocusOnClick = (0, _react.useCallback)(() => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
submenuContext.updateFocusIndex(submenuContext.itemIndex);
|
|
117
|
+
if (updateSubmenuFocusId) {
|
|
118
|
+
updateSubmenuFocusId(menuItemId.current);
|
|
94
119
|
}
|
|
95
|
-
}, [
|
|
120
|
+
}, [updateSubmenuFocusId]);
|
|
96
121
|
const handleKeyDown = (0, _react.useCallback)(event => {
|
|
122
|
+
var _inputIcon$current2, _inputRef$current;
|
|
123
|
+
|
|
97
124
|
if (onKeyDown) {
|
|
98
125
|
onKeyDown(event);
|
|
99
126
|
}
|
|
@@ -102,16 +129,16 @@ const MenuItem = ({
|
|
|
102
129
|
ref.current.focus();
|
|
103
130
|
}
|
|
104
131
|
|
|
105
|
-
|
|
106
|
-
var _focusRef$current;
|
|
132
|
+
const shouldFocusIcon = ((_inputIcon$current2 = inputIcon.current) === null || _inputIcon$current2 === void 0 ? void 0 : _inputIcon$current2.getAttribute("tabindex")) === "0" && document.activeElement === inputRef.current && ((_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.value); // let natural tab order move focus if input icon is tabbable
|
|
107
133
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
} else {
|
|
112
|
-
menuContext.handleKeyDown(event);
|
|
134
|
+
if (_events.default.isTabKey(event) && (!_events.default.isShiftKey(event) && shouldFocusIcon || _events.default.isShiftKey(event) && document.activeElement === inputIcon.current)) {
|
|
135
|
+
return;
|
|
113
136
|
}
|
|
114
|
-
|
|
137
|
+
|
|
138
|
+
if (handleSubmenuKeyDown) {
|
|
139
|
+
handleSubmenuKeyDown(event);
|
|
140
|
+
}
|
|
141
|
+
}, [onKeyDown, handleSubmenuKeyDown, inputIcon]);
|
|
115
142
|
const classes = (0, _react.useMemo)(() => (0, _classnames.default)({
|
|
116
143
|
"carbon-menu-item--has-link": href || onClick
|
|
117
144
|
}), [href, onClick]);
|
|
@@ -120,7 +147,7 @@ const MenuItem = ({
|
|
|
120
147
|
href,
|
|
121
148
|
target,
|
|
122
149
|
rel,
|
|
123
|
-
onClick: onClick || (
|
|
150
|
+
onClick: onClick || (inputRef.current ? updateFocusOnClick : undefined),
|
|
124
151
|
icon,
|
|
125
152
|
selected,
|
|
126
153
|
variant,
|
|
@@ -128,11 +155,8 @@ const MenuItem = ({
|
|
|
128
155
|
overrideColor,
|
|
129
156
|
ref
|
|
130
157
|
};
|
|
131
|
-
const clonedChildren = isChildSearch.current ? childrenItems.map(child => /*#__PURE__*/_react.default.cloneElement(child, {
|
|
132
|
-
ref: childRef
|
|
133
|
-
})) : children;
|
|
134
158
|
|
|
135
|
-
const getTitle = title => maxWidth && typeof title === "string" ? title :
|
|
159
|
+
const getTitle = title => maxWidth && typeof title === "string" ? title : undefined;
|
|
136
160
|
|
|
137
161
|
const itemMaxWidth = !inFullscreenView ? maxWidth : undefined;
|
|
138
162
|
const asPassiveItem = !(onClick || href);
|
|
@@ -140,13 +164,14 @@ const MenuItem = ({
|
|
|
140
164
|
if (submenu) {
|
|
141
165
|
return /*#__PURE__*/_react.default.createElement(_menu2.StyledMenuItem, _extends({
|
|
142
166
|
"data-component": "menu-item",
|
|
143
|
-
menuType:
|
|
167
|
+
menuType: menuType,
|
|
144
168
|
display: "inline-block",
|
|
145
169
|
title: getTitle(submenu),
|
|
146
170
|
maxWidth: itemMaxWidth,
|
|
147
171
|
onClick: updateFocusOnClick
|
|
148
172
|
}, rest, {
|
|
149
|
-
inFullscreenView: inFullscreenView
|
|
173
|
+
inFullscreenView: inFullscreenView,
|
|
174
|
+
id: menuItemId.current
|
|
150
175
|
}), /*#__PURE__*/_react.default.createElement(_submenu.default, _extends({}, typeof submenu !== "boolean" && {
|
|
151
176
|
title: submenu
|
|
152
177
|
}, {
|
|
@@ -158,29 +183,31 @@ const MenuItem = ({
|
|
|
158
183
|
ariaLabel: ariaLabel,
|
|
159
184
|
onSubmenuOpen: onSubmenuOpen,
|
|
160
185
|
onSubmenuClose: onSubmenuClose
|
|
161
|
-
}, elementProps, rest),
|
|
186
|
+
}, elementProps, rest), children));
|
|
162
187
|
}
|
|
163
188
|
|
|
164
189
|
return /*#__PURE__*/_react.default.createElement(_menu2.StyledMenuItem, _extends({
|
|
165
190
|
"data-component": "menu-item",
|
|
166
|
-
menuType:
|
|
167
|
-
inSubmenu:
|
|
191
|
+
menuType: menuType,
|
|
192
|
+
inSubmenu: !!handleSubmenuKeyDown,
|
|
168
193
|
display: "inline-block",
|
|
169
194
|
title: getTitle(children),
|
|
170
195
|
maxWidth: itemMaxWidth
|
|
171
196
|
}, rest, {
|
|
172
197
|
inFullscreenView: inFullscreenView && !Object.keys(submenuContext).length,
|
|
173
|
-
menuOpen: menuOpen
|
|
198
|
+
menuOpen: menuOpen,
|
|
199
|
+
id: menuItemId.current
|
|
174
200
|
}), /*#__PURE__*/_react.default.createElement(_menuItem.default, _extends({
|
|
175
|
-
as:
|
|
176
|
-
isSearch:
|
|
177
|
-
menuType:
|
|
201
|
+
as: inputRef.current ? "div" : _link.default,
|
|
202
|
+
isSearch: inputRef.current,
|
|
203
|
+
menuType: menuType
|
|
178
204
|
}, elementProps, {
|
|
179
205
|
ariaLabel: ariaLabel,
|
|
180
206
|
maxWidth: maxWidth,
|
|
181
207
|
inFullscreenView: inFullscreenView,
|
|
182
|
-
asPassiveItem: asPassiveItem
|
|
183
|
-
|
|
208
|
+
asPassiveItem: asPassiveItem,
|
|
209
|
+
placeholderTabIndex: asPassiveItem
|
|
210
|
+
}), children));
|
|
184
211
|
};
|
|
185
212
|
|
|
186
213
|
MenuItem.propTypes = {
|
|
@@ -269,10 +296,7 @@ MenuItem.propTypes = {
|
|
|
269
296
|
overrideColor: _propTypes.default.bool,
|
|
270
297
|
|
|
271
298
|
/** @ignore @private */
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
/** @ignore @private */
|
|
275
|
-
indexInMenu: _propTypes.default.number
|
|
299
|
+
"data-component": _propTypes.default.string
|
|
276
300
|
};
|
|
277
301
|
MenuItem.displayName = "MenuItem";
|
|
278
302
|
var _default = MenuItem;
|
|
@@ -31,10 +31,14 @@ export interface MenuItemBaseProps extends LayoutProps, FlexboxProps {
|
|
|
31
31
|
onSubmenuOpen?: () => void;
|
|
32
32
|
/** Callback triggered when submenu closes. Only valid with submenu prop */
|
|
33
33
|
onSubmenuClose?: () => void;
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
/**
|
|
35
|
+
@ignore @private
|
|
36
|
+
private prop, used inside ScrollableBlock to ensure the MenuItem's color variant overrides the CSS
|
|
37
|
+
for other MenuItems inside the block
|
|
38
|
+
*/
|
|
37
39
|
overrideColor?: boolean;
|
|
40
|
+
/** @private @ignore */
|
|
41
|
+
"data-component"?: string;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
export interface MenuWithChildren extends MenuItemBaseProps {
|