carbon-react 153.8.0 → 154.1.0
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/components/text-editor/__internal__/helpers.js +1 -1
- package/esm/components/text-editor/__internal__/plugins/EditorRef/editor-ref.plugin.d.ts +5 -0
- package/esm/components/text-editor/__internal__/plugins/EditorRef/editor-ref.plugin.js +17 -0
- package/esm/components/text-editor/__internal__/plugins/EditorRef/index.d.ts +1 -0
- package/esm/components/text-editor/__internal__/plugins/EditorRef/index.js +1 -0
- package/esm/components/text-editor/__internal__/plugins/Toolbar/toolbar.component.js +0 -1
- package/esm/components/text-editor/text-editor.component.d.ts +5 -1
- package/esm/components/text-editor/text-editor.component.js +19 -11
- package/esm/components/vertical-menu/index.d.ts +1 -0
- package/esm/components/vertical-menu/index.js +2 -1
- package/esm/components/vertical-menu/responsive-vertical-menu/__internal__/depth.context.d.ts +16 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/__internal__/depth.context.js +47 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/__internal__/focus.context.d.ts +24 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/__internal__/focus.context.js +206 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/index.d.ts +7 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/index.js +4 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/index.d.ts +2 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/index.js +1 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.component.d.ts +6 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.component.js +19 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.style.d.ts +8 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.style.js +13 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/index.d.ts +2 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/index.js +1 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.component.d.ts +23 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.component.js +307 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.style.d.ts +31 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.style.js +217 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.component.d.ts +14 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.component.js +186 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.context.d.ts +28 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.context.js +32 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.style.d.ts +20 -0
- package/esm/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.style.js +95 -0
- package/lib/components/text-editor/__internal__/helpers.js +1 -1
- package/lib/components/text-editor/__internal__/plugins/EditorRef/editor-ref.plugin.d.ts +5 -0
- package/lib/components/text-editor/__internal__/plugins/EditorRef/editor-ref.plugin.js +24 -0
- package/lib/components/text-editor/__internal__/plugins/EditorRef/index.d.ts +1 -0
- package/lib/components/text-editor/__internal__/plugins/EditorRef/index.js +13 -0
- package/lib/components/text-editor/__internal__/plugins/EditorRef/package.json +6 -0
- package/lib/components/text-editor/__internal__/plugins/Toolbar/toolbar.component.js +0 -1
- package/lib/components/text-editor/text-editor.component.d.ts +5 -1
- package/lib/components/text-editor/text-editor.component.js +19 -11
- package/lib/components/vertical-menu/index.d.ts +1 -0
- package/lib/components/vertical-menu/index.js +19 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/__internal__/depth.context.d.ts +16 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/__internal__/depth.context.js +58 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/__internal__/focus.context.d.ts +24 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/__internal__/focus.context.js +217 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/index.d.ts +7 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/index.js +33 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/package.json +6 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/index.d.ts +2 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/index.js +13 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/package.json +6 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.component.d.ts +6 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.component.js +27 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.style.d.ts +8 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-divider/responsive-vertical-menu-divider.style.js +20 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/index.d.ts +2 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/index.js +13 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/package.json +6 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.component.d.ts +23 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.component.js +316 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.style.d.ts +31 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu-item/responsive-vertical-menu-item.style.js +226 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.component.d.ts +14 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.component.js +196 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.context.d.ts +28 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.context.js +42 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.style.d.ts +20 -0
- package/lib/components/vertical-menu/responsive-vertical-menu/responsive-vertical-menu.style.js +104 -0
- package/package.json +1 -1
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React, { createContext, forwardRef, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { StyledIcon, StyledMenuItemContent, StyledNestedMenu, StyledResponsiveMenuAction, StyledResponsiveMenuItem } from "./responsive-vertical-menu-item.style";
|
|
4
|
+
import { IncreaseDepth, useDepth } from "../__internal__/depth.context";
|
|
5
|
+
import { useMenuFocus } from "../__internal__/focus.context";
|
|
6
|
+
import { useResponsiveVerticalMenu } from "../responsive-vertical-menu.context";
|
|
7
|
+
import Icon from "../../../icon";
|
|
8
|
+
import guid from "../../../../__internal__/utils/helpers/guid";
|
|
9
|
+
|
|
10
|
+
// Standard TS pattern for overriding props
|
|
11
|
+
|
|
12
|
+
// Context to hold the parent item ID
|
|
13
|
+
const ParentItemContext = /*#__PURE__*/createContext(undefined);
|
|
14
|
+
// Renders the actual content of the menu item
|
|
15
|
+
const MenuItemContent = ({
|
|
16
|
+
customIcon,
|
|
17
|
+
depth,
|
|
18
|
+
hasChildren,
|
|
19
|
+
icon,
|
|
20
|
+
label,
|
|
21
|
+
responsive
|
|
22
|
+
}) => {
|
|
23
|
+
// If a custom icon is provided, render it with the label
|
|
24
|
+
// Otherwise, render the provided icon with the label.
|
|
25
|
+
// If no icon is provided, render the label only.
|
|
26
|
+
return customIcon ? /*#__PURE__*/React.createElement(StyledMenuItemContent, {
|
|
27
|
+
"data-component": "responsive-vertical-menu-custom-icon",
|
|
28
|
+
"data-role": "responsive-vertical-menu-custom-icon",
|
|
29
|
+
depth: depth,
|
|
30
|
+
hasChildren: hasChildren,
|
|
31
|
+
icon: true,
|
|
32
|
+
responsive: responsive
|
|
33
|
+
}, customIcon, label) : /*#__PURE__*/React.createElement(StyledMenuItemContent, {
|
|
34
|
+
"data-component": "responsive-vertical-menu-icon",
|
|
35
|
+
"data-role": "responsive-vertical-menu-icon",
|
|
36
|
+
depth: depth,
|
|
37
|
+
hasChildren: hasChildren,
|
|
38
|
+
icon: !!icon,
|
|
39
|
+
responsive: responsive
|
|
40
|
+
}, icon && /*#__PURE__*/React.createElement(Icon, {
|
|
41
|
+
type: icon
|
|
42
|
+
}), label);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Base component for the menu item
|
|
46
|
+
const BaseItem = /*#__PURE__*/forwardRef(({
|
|
47
|
+
children,
|
|
48
|
+
customIcon,
|
|
49
|
+
icon,
|
|
50
|
+
id,
|
|
51
|
+
href,
|
|
52
|
+
label,
|
|
53
|
+
...rest
|
|
54
|
+
}, ref) => {
|
|
55
|
+
const {
|
|
56
|
+
activeMenuItem,
|
|
57
|
+
containerRef,
|
|
58
|
+
responsiveMode,
|
|
59
|
+
setActiveMenuItem,
|
|
60
|
+
reducedMotion
|
|
61
|
+
} = useResponsiveVerticalMenu();
|
|
62
|
+
const {
|
|
63
|
+
expandItem,
|
|
64
|
+
focusItem,
|
|
65
|
+
getRegisteredItems,
|
|
66
|
+
moveFocus,
|
|
67
|
+
registerMenuItem
|
|
68
|
+
} = useMenuFocus();
|
|
69
|
+
const depth = useDepth();
|
|
70
|
+
const isActive = activeMenuItem?.id === id;
|
|
71
|
+
const hasChildren = React.Children.count(children) > 0;
|
|
72
|
+
const parentId = useContext(ParentItemContext);
|
|
73
|
+
const responsiveDisplay = useMemo(() => responsiveMode && depth === 0, [depth, responsiveMode]);
|
|
74
|
+
const [expanded, setExpanded] = useState(responsiveDisplay && hasChildren);
|
|
75
|
+
|
|
76
|
+
// Register the menu item with the focus context
|
|
77
|
+
// We can do this here as well as in the wrapping component to ensure
|
|
78
|
+
// that the item is registered even if it is used as-is (as opposed to
|
|
79
|
+
// via ResponsiveVerticalMenuItem).
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
registerMenuItem(id, ref, parentId);
|
|
82
|
+
}, [id, parentId, ref, registerMenuItem]);
|
|
83
|
+
|
|
84
|
+
// Handle keyboard navigation
|
|
85
|
+
const handleKeyDown = e => {
|
|
86
|
+
// Store a list of siblings
|
|
87
|
+
let siblings;
|
|
88
|
+
let siblingsAtDepth;
|
|
89
|
+
switch (e.key) {
|
|
90
|
+
case "Tab":
|
|
91
|
+
siblingsAtDepth = containerRef.current?.querySelectorAll(`[data-depth="${depth}"]`) || /* istanbul ignore next */[];
|
|
92
|
+
siblings = Array.from(siblingsAtDepth);
|
|
93
|
+
|
|
94
|
+
// Primary-level menu items
|
|
95
|
+
if (depth === 0 && hasChildren && activeMenuItem?.id === id) {
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
// If the item is active and has children, move focus to the first/last child, based on whether the Shift key is pressed or not
|
|
98
|
+
moveFocus(!e.shiftKey ? "firstChild" : "lastChild");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Secondary-level menu items
|
|
102
|
+
if (depth === 1) {
|
|
103
|
+
const currentIndex = siblings.findIndex(el => el.id === id);
|
|
104
|
+
const isLastSibling = currentIndex === siblings.length - 1;
|
|
105
|
+
const isFirstSibling = currentIndex === 0;
|
|
106
|
+
|
|
107
|
+
// If the item is the last sibling and has no children (or it does but isn't expanded), move focus to the parent when forward-tabbing
|
|
108
|
+
/* istanbul ignore else */
|
|
109
|
+
if (isLastSibling && (!hasChildren || hasChildren && !expanded)) {
|
|
110
|
+
if (!e.shiftKey) {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
moveFocus("parent");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// If the item is the first sibling and shift is pressed, move focus to the parent
|
|
117
|
+
if (isFirstSibling && e.shiftKey) {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
moveFocus("parent");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Tertiary-level menu items
|
|
124
|
+
if (depth === 2) {
|
|
125
|
+
const currentIndex = siblings.findIndex(el => el.id === id);
|
|
126
|
+
const isLastSibling = currentIndex === siblings.length - 1;
|
|
127
|
+
|
|
128
|
+
/* istanbul ignore else */
|
|
129
|
+
if (isLastSibling) {
|
|
130
|
+
// If the item is the last sibling, find the grand-parent in the menu hierarchy
|
|
131
|
+
const allMenuItems = getRegisteredItems();
|
|
132
|
+
const parent = allMenuItems.find(item => item.id === parentId);
|
|
133
|
+
const grandParent = allMenuItems.find(item => item.id === parent?.parentId);
|
|
134
|
+
|
|
135
|
+
/* istanbul ignore else */
|
|
136
|
+
if (grandParent) {
|
|
137
|
+
// Check if the parent is the last sibling under the grand-parent
|
|
138
|
+
const parentSiblings = Array.from(containerRef.current?.querySelectorAll(`[data-depth="${depth - 1}"]`) || /* istanbul ignore next */[]);
|
|
139
|
+
const parentIsLastSibling = parentSiblings.findIndex(el => el.id === parentId) === parentSiblings.length - 1;
|
|
140
|
+
|
|
141
|
+
// If the parent is the last sibling and shift is not pressed, move focus to the grand-parent
|
|
142
|
+
if (parentIsLastSibling && !e.shiftKey) {
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
focusItem(grandParent.id);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
|
|
151
|
+
// Handle activation keys
|
|
152
|
+
case "Enter":
|
|
153
|
+
case " ":
|
|
154
|
+
e.preventDefault();
|
|
155
|
+
|
|
156
|
+
// If in responsive mode, do not toggle the menu
|
|
157
|
+
/* istanbul ignore if */
|
|
158
|
+
if (responsiveDisplay) return;
|
|
159
|
+
|
|
160
|
+
/* istanbul ignore else */
|
|
161
|
+
if (hasChildren) {
|
|
162
|
+
// Toggle expanded state if not in responsive mode
|
|
163
|
+
if (depth === 0 && !responsiveMode) {
|
|
164
|
+
const itemToggled = activeMenuItem?.id === id;
|
|
165
|
+
const newActiveMenuItem = itemToggled ? null : {
|
|
166
|
+
id,
|
|
167
|
+
label,
|
|
168
|
+
children
|
|
169
|
+
};
|
|
170
|
+
// Set the active menu item
|
|
171
|
+
setActiveMenuItem(newActiveMenuItem);
|
|
172
|
+
} else {
|
|
173
|
+
// Expand the menu
|
|
174
|
+
setExpanded(!expanded);
|
|
175
|
+
expandItem(id, !expanded);
|
|
176
|
+
}
|
|
177
|
+
} else if (href && e.key === "Enter") {
|
|
178
|
+
// If no children, navigate to the href. Can only be activated with Enter key,
|
|
179
|
+
// as per accessibility guidelines.
|
|
180
|
+
window.location.href = href;
|
|
181
|
+
}
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const handleClick = () => {
|
|
188
|
+
// If in responsive mode, do not toggle the menu
|
|
189
|
+
if (responsiveDisplay) return;
|
|
190
|
+
|
|
191
|
+
// Mimic the behavior of the Enter key as defined in the handleKeyDown function
|
|
192
|
+
if (depth === 0 && !responsiveMode) {
|
|
193
|
+
const itemToggled = activeMenuItem?.id === id;
|
|
194
|
+
const newActiveMenuItem = itemToggled ? null : {
|
|
195
|
+
id,
|
|
196
|
+
label,
|
|
197
|
+
children
|
|
198
|
+
};
|
|
199
|
+
setActiveMenuItem(newActiveMenuItem);
|
|
200
|
+
} else {
|
|
201
|
+
setExpanded(!expanded);
|
|
202
|
+
expandItem(id, !expanded);
|
|
203
|
+
}
|
|
204
|
+
// Focus the clicked item
|
|
205
|
+
focusItem(id);
|
|
206
|
+
};
|
|
207
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, hasChildren ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(StyledResponsiveMenuItem, _extends({
|
|
208
|
+
active: isActive,
|
|
209
|
+
"aria-expanded": isActive || expanded,
|
|
210
|
+
"data-component": `responsive-vertical-menu-item-${id}`,
|
|
211
|
+
"data-depth": depth,
|
|
212
|
+
"data-role": `responsive-vertical-menu-item-${id}`,
|
|
213
|
+
depth: depth,
|
|
214
|
+
hasIcon: !!icon || !!customIcon,
|
|
215
|
+
id: id,
|
|
216
|
+
onClick: handleClick,
|
|
217
|
+
onKeyDown: e => {
|
|
218
|
+
/* istanbul ignore else */
|
|
219
|
+
if (!responsiveMode) {
|
|
220
|
+
handleKeyDown(e);
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
onFocus: () => focusItem(id),
|
|
224
|
+
ref: ref,
|
|
225
|
+
responsive: responsiveMode,
|
|
226
|
+
tabIndex: responsiveDisplay ? -1 : 0,
|
|
227
|
+
type: "button"
|
|
228
|
+
}, rest), /*#__PURE__*/React.createElement(MenuItemContent, {
|
|
229
|
+
customIcon: customIcon,
|
|
230
|
+
depth: depth,
|
|
231
|
+
hasChildren: true,
|
|
232
|
+
icon: icon,
|
|
233
|
+
label: label,
|
|
234
|
+
responsive: responsiveMode
|
|
235
|
+
}), !responsiveDisplay && /*#__PURE__*/React.createElement(StyledIcon, {
|
|
236
|
+
"data-component": "responsive-vertical-menu-expander-icon",
|
|
237
|
+
"data-role": "responsive-vertical-menu-expander-icon",
|
|
238
|
+
depth: depth,
|
|
239
|
+
expanded: expanded || isActive,
|
|
240
|
+
reduceMotion: !!reducedMotion,
|
|
241
|
+
type: depth >= 1 ? "chevron_down_thick" : "chevron_right_thick"
|
|
242
|
+
})), expanded && /*#__PURE__*/React.createElement(StyledNestedMenu, {
|
|
243
|
+
"data-component": `${id}-nested-menu`,
|
|
244
|
+
"data-role": `${id}-nested-menu`,
|
|
245
|
+
depth: depth,
|
|
246
|
+
hasIcon: !!icon || !!customIcon,
|
|
247
|
+
id: `${id}-nested-menu`,
|
|
248
|
+
responsive: responsiveMode
|
|
249
|
+
}, /*#__PURE__*/React.createElement(ParentItemContext.Provider, {
|
|
250
|
+
value: id
|
|
251
|
+
}, children))) : /*#__PURE__*/React.createElement(StyledResponsiveMenuAction, _extends({
|
|
252
|
+
"data-component": `responsive-vertical-menu-item-${id}`,
|
|
253
|
+
"data-depth": depth,
|
|
254
|
+
"data-role": `responsive-vertical-menu-item-${id}`,
|
|
255
|
+
depth: depth,
|
|
256
|
+
href: href,
|
|
257
|
+
id: id,
|
|
258
|
+
onFocus: () => focusItem(id),
|
|
259
|
+
onKeyDown: e => {
|
|
260
|
+
/* istanbul ignore else */
|
|
261
|
+
if (!responsiveMode) {
|
|
262
|
+
handleKeyDown(e);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
ref: ref,
|
|
266
|
+
responsive: responsiveMode,
|
|
267
|
+
tabIndex: 0
|
|
268
|
+
}, rest), /*#__PURE__*/React.createElement(MenuItemContent, {
|
|
269
|
+
customIcon: customIcon,
|
|
270
|
+
depth: depth,
|
|
271
|
+
hasChildren: false,
|
|
272
|
+
icon: icon,
|
|
273
|
+
label: label,
|
|
274
|
+
responsive: responsiveMode
|
|
275
|
+
})));
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Main component for the responsive vertical menu item
|
|
279
|
+
export const ResponsiveVerticalMenuItem = ({
|
|
280
|
+
children,
|
|
281
|
+
id,
|
|
282
|
+
label,
|
|
283
|
+
...props
|
|
284
|
+
}) => {
|
|
285
|
+
const depth = useDepth();
|
|
286
|
+
const itemRef = useRef(null);
|
|
287
|
+
const {
|
|
288
|
+
registerMenuItem
|
|
289
|
+
} = useMenuFocus();
|
|
290
|
+
const parentId = useContext(ParentItemContext);
|
|
291
|
+
const uniqueId = useRef(id || guid());
|
|
292
|
+
|
|
293
|
+
// Register the menu item with the focus context
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
registerMenuItem(uniqueId.current, itemRef, parentId);
|
|
296
|
+
}, [id, registerMenuItem, parentId]);
|
|
297
|
+
return /*#__PURE__*/React.createElement(BaseItem, _extends({
|
|
298
|
+
id: uniqueId.current,
|
|
299
|
+
label: label
|
|
300
|
+
}, props, {
|
|
301
|
+
"data-depth": depth,
|
|
302
|
+
ref: itemRef
|
|
303
|
+
}), children && /*#__PURE__*/React.createElement(ParentItemContext.Provider, {
|
|
304
|
+
value: id
|
|
305
|
+
}, /*#__PURE__*/React.createElement(IncreaseDepth, null, children)));
|
|
306
|
+
};
|
|
307
|
+
export default ResponsiveVerticalMenuItem;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
interface StyledResponsiveMenuItemProps {
|
|
3
|
+
active?: boolean;
|
|
4
|
+
depth: number;
|
|
5
|
+
hasIcon?: boolean;
|
|
6
|
+
responsive?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface StyledMenuItemContentProps {
|
|
9
|
+
customIcon?: boolean;
|
|
10
|
+
depth: number;
|
|
11
|
+
hasChildren?: boolean;
|
|
12
|
+
icon?: boolean;
|
|
13
|
+
responsive?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare const StyledMenuItemContent: import("styled-components").StyledComponent<"span", any, StyledMenuItemContentProps, never>;
|
|
16
|
+
export declare const StyledResponsiveMenuItem: import("styled-components").StyledComponent<"button", any, StyledResponsiveMenuItemProps, never>;
|
|
17
|
+
export declare const StyledResponsiveMenuAction: import("styled-components").StyledComponent<"a", any, {
|
|
18
|
+
depth: number;
|
|
19
|
+
responsive?: boolean | undefined;
|
|
20
|
+
}, never>;
|
|
21
|
+
export declare const StyledNestedMenu: import("styled-components").StyledComponent<"div", any, {
|
|
22
|
+
depth: number;
|
|
23
|
+
hasIcon?: boolean | undefined;
|
|
24
|
+
responsive?: boolean | undefined;
|
|
25
|
+
}, never>;
|
|
26
|
+
export declare const StyledIcon: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../../../icon").IconProps & import("react").RefAttributes<HTMLSpanElement>>, any, {
|
|
27
|
+
depth: number;
|
|
28
|
+
expanded: boolean;
|
|
29
|
+
reduceMotion: boolean;
|
|
30
|
+
}, never>;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import styled, { css } from "styled-components";
|
|
2
|
+
import { margin, padding } from "styled-system";
|
|
3
|
+
import Icon from "../../../icon";
|
|
4
|
+
import addFocusStyling from "../../../../style/utils/add-focus-styling";
|
|
5
|
+
const BASE_ACTION_WIDTH = 92;
|
|
6
|
+
const RESPONSIVE_ACTION_WIDTH_NO_NESTED_MENU = BASE_ACTION_WIDTH - 14;
|
|
7
|
+
const RESPONSIVE_ACTION_WIDTH_NESTED_MENU = BASE_ACTION_WIDTH - 20;
|
|
8
|
+
const getRotationData = (depth, expanded) => {
|
|
9
|
+
if (!depth || !expanded) {
|
|
10
|
+
return "0deg";
|
|
11
|
+
}
|
|
12
|
+
return "180deg";
|
|
13
|
+
};
|
|
14
|
+
export const StyledMenuItemContent = styled.span`
|
|
15
|
+
align-items: center;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: row;
|
|
18
|
+
gap: var(--spacing100);
|
|
19
|
+
|
|
20
|
+
svg {
|
|
21
|
+
margin-right: var(--spacing100);
|
|
22
|
+
max-width: var(--sizing300);
|
|
23
|
+
min-width: var(--sizing300);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
${({
|
|
27
|
+
customIcon,
|
|
28
|
+
depth,
|
|
29
|
+
hasChildren,
|
|
30
|
+
icon,
|
|
31
|
+
responsive
|
|
32
|
+
}) => {
|
|
33
|
+
if (depth > 0) {
|
|
34
|
+
if (responsive) {
|
|
35
|
+
return css`
|
|
36
|
+
width: 100%;
|
|
37
|
+
`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (depth === 0 && hasChildren && responsive) {
|
|
41
|
+
return css`
|
|
42
|
+
color: #ffffffcc;
|
|
43
|
+
cursor: default;
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
if (customIcon || icon) {
|
|
47
|
+
return css`
|
|
48
|
+
width: 81%;
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
return css`
|
|
52
|
+
width: 92%;
|
|
53
|
+
`;
|
|
54
|
+
}}
|
|
55
|
+
`;
|
|
56
|
+
export const StyledResponsiveMenuItem = styled.button`
|
|
57
|
+
align-items: center;
|
|
58
|
+
background-color: transparent;
|
|
59
|
+
border: none;
|
|
60
|
+
border-radius: var(--borderRadius100);
|
|
61
|
+
color: var(--colorsUtilityYang100);
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: row;
|
|
65
|
+
font-size: 14px;
|
|
66
|
+
font-weight: 500;
|
|
67
|
+
justify-content: space-between;
|
|
68
|
+
min-height: var(--sizing500);
|
|
69
|
+
padding: 0 15px;
|
|
70
|
+
width: 100%;
|
|
71
|
+
max-width: 340px;
|
|
72
|
+
|
|
73
|
+
${margin}
|
|
74
|
+
${padding}
|
|
75
|
+
|
|
76
|
+
${({
|
|
77
|
+
depth,
|
|
78
|
+
responsive
|
|
79
|
+
}) => depth > 0 && responsive && css`
|
|
80
|
+
cursor: default;
|
|
81
|
+
justify-content: space-around;
|
|
82
|
+
width: 80%;
|
|
83
|
+
`}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
${({
|
|
87
|
+
depth,
|
|
88
|
+
responsive
|
|
89
|
+
}) => depth === 0 && responsive && css`
|
|
90
|
+
padding: 0;
|
|
91
|
+
`}
|
|
92
|
+
|
|
93
|
+
&:hover {
|
|
94
|
+
background-color: var(--colorsActionMajor500);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
${({
|
|
98
|
+
active,
|
|
99
|
+
responsive
|
|
100
|
+
}) => active && !responsive && css`
|
|
101
|
+
background-color: var(--colorsGray850);
|
|
102
|
+
`}
|
|
103
|
+
|
|
104
|
+
[data-component="icon"] {
|
|
105
|
+
color: var(--colorsUtilityYang100);
|
|
106
|
+
margin-right: var(--spacing100);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&:focus {
|
|
110
|
+
${addFocusStyling(true)}
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
export const StyledResponsiveMenuAction = styled.a`
|
|
114
|
+
align-items: center;
|
|
115
|
+
background-color: transparent;
|
|
116
|
+
border: none;
|
|
117
|
+
border-radius: var(--borderRadius100);
|
|
118
|
+
color: var(--colorsUtilityYang100);
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
display: flex;
|
|
121
|
+
flex-direction: row;
|
|
122
|
+
font-size: 14px;
|
|
123
|
+
font-weight: 500;
|
|
124
|
+
justify-content: space-between;
|
|
125
|
+
min-height: var(--sizing500);
|
|
126
|
+
padding: 0 var(--spacing200);
|
|
127
|
+
text-decoration: none;
|
|
128
|
+
width: 92%;
|
|
129
|
+
max-width: 92%;
|
|
130
|
+
|
|
131
|
+
${({
|
|
132
|
+
depth,
|
|
133
|
+
responsive
|
|
134
|
+
}) => depth > 0 && responsive && css`
|
|
135
|
+
cursor: default;
|
|
136
|
+
justify-content: space-around;
|
|
137
|
+
width: ${depth === 1 ? `${RESPONSIVE_ACTION_WIDTH_NO_NESTED_MENU}%` : `${RESPONSIVE_ACTION_WIDTH_NESTED_MENU}%`};
|
|
138
|
+
`}
|
|
139
|
+
|
|
140
|
+
${margin}
|
|
141
|
+
${padding}
|
|
142
|
+
|
|
143
|
+
&:hover {
|
|
144
|
+
background-color: var(--colorsActionMajor500);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
[data-component="icon"] {
|
|
148
|
+
color: var(--colorsUtilityYang100);
|
|
149
|
+
margin-right: var(--spacing100);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
&:focus {
|
|
153
|
+
${addFocusStyling(true)}
|
|
154
|
+
}
|
|
155
|
+
`;
|
|
156
|
+
export const StyledNestedMenu = styled.div`
|
|
157
|
+
width: ${({
|
|
158
|
+
responsive
|
|
159
|
+
}) => responsive ? "72%" : "92%"};
|
|
160
|
+
${({
|
|
161
|
+
hasIcon
|
|
162
|
+
}) => hasIcon && css`
|
|
163
|
+
margin-left: 80px;
|
|
164
|
+
width: 100%;
|
|
165
|
+
`};
|
|
166
|
+
|
|
167
|
+
${({
|
|
168
|
+
responsive
|
|
169
|
+
}) => responsive && css`
|
|
170
|
+
align-items: center
|
|
171
|
+
display: flex;
|
|
172
|
+
flex-direction: column;
|
|
173
|
+
width: 100%;
|
|
174
|
+
|
|
175
|
+
`}
|
|
176
|
+
|
|
177
|
+
a {
|
|
178
|
+
font-weight: 400;
|
|
179
|
+
${({
|
|
180
|
+
hasIcon
|
|
181
|
+
}) => hasIcon && `width: 81%;`};
|
|
182
|
+
|
|
183
|
+
${({
|
|
184
|
+
depth,
|
|
185
|
+
responsive
|
|
186
|
+
}) => responsive && css`
|
|
187
|
+
font-weight: 500;
|
|
188
|
+
width: 70%;
|
|
189
|
+
|
|
190
|
+
${depth && depth >= 1 && css`
|
|
191
|
+
font-weight: 400;
|
|
192
|
+
margin-left: var(--spacing200);
|
|
193
|
+
margin-right: var(--spacing200);
|
|
194
|
+
width: 63%;
|
|
195
|
+
`}
|
|
196
|
+
`}
|
|
197
|
+
}
|
|
198
|
+
`;
|
|
199
|
+
export const StyledIcon = styled(Icon)`
|
|
200
|
+
rotate: ${({
|
|
201
|
+
depth,
|
|
202
|
+
expanded
|
|
203
|
+
}) => getRotationData(depth, expanded)};
|
|
204
|
+
transition: rotate ${({
|
|
205
|
+
reduceMotion
|
|
206
|
+
}) => reduceMotion ? 0 : "0.2s"}
|
|
207
|
+
ease-in;
|
|
208
|
+
|
|
209
|
+
${({
|
|
210
|
+
depth,
|
|
211
|
+
expanded,
|
|
212
|
+
reduceMotion
|
|
213
|
+
}) => expanded && css`
|
|
214
|
+
rotate: ${getRotationData(depth, expanded)};
|
|
215
|
+
transition: rotate ${reduceMotion ? 0 : "0.2s"} ease-out;
|
|
216
|
+
`};
|
|
217
|
+
`;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
import { TagProps } from "../../../__internal__/utils/helpers/tags";
|
|
3
|
+
export interface ResponsiveVerticalMenuProps extends TagProps {
|
|
4
|
+
/** The content of the menu */
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
/** The height of the primary and secondary menus */
|
|
7
|
+
height?: string;
|
|
8
|
+
/** The value (in pixels) at which the ResponsiveVerticalMenu will become responsive/modal */
|
|
9
|
+
responsiveBreakpoint?: number;
|
|
10
|
+
/** The width of the primary and secondary menus when in default mode */
|
|
11
|
+
width?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const ResponsiveVerticalMenu: ({ children, ...props }: ResponsiveVerticalMenuProps) => React.JSX.Element;
|
|
14
|
+
export default ResponsiveVerticalMenu;
|