@launchpad-ui/menu 0.4.8 → 0.5.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/dist/Menu.d.ts +3 -3
- package/dist/Menu.d.ts.map +1 -1
- package/dist/MenuBase.d.ts +2 -2
- package/dist/MenuBase.d.ts.map +1 -1
- package/dist/MenuDivider.d.ts +2 -2
- package/dist/MenuDivider.d.ts.map +1 -1
- package/dist/MenuItem.d.ts +8 -8
- package/dist/MenuItem.d.ts.map +1 -1
- package/dist/MenuItemList.d.ts +2 -2
- package/dist/MenuItemList.d.ts.map +1 -1
- package/dist/index.es.js +233 -270
- package/dist/index.es.js.map +1 -7
- package/dist/index.js +263 -325
- package/dist/index.js.map +1 -7
- package/dist/style.css +222 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/styles/Menu.css +0 -2
- package/dist/styles/Menu.css.map +0 -1
package/dist/index.js
CHANGED
@@ -1,82 +1,53 @@
|
|
1
|
+
require('./style.css');
|
1
2
|
"use strict";
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
MenuSearch: () => MenuSearch,
|
30
|
-
MenuSize: () => MenuSize
|
3
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
4
|
+
const classix = require("classix");
|
5
|
+
const react = require("react");
|
6
|
+
const jsxRuntime = require("react/jsx-runtime");
|
7
|
+
const separator = require("@react-aria/separator");
|
8
|
+
const icons = require("@launchpad-ui/icons");
|
9
|
+
const tooltip = require("@launchpad-ui/tooltip");
|
10
|
+
const reactSlot = require("@radix-ui/react-slot");
|
11
|
+
const focus = require("@react-aria/focus");
|
12
|
+
const reactRouterDom = require("react-router-dom");
|
13
|
+
const form = require("@launchpad-ui/form");
|
14
|
+
const reactVirtual = require("react-virtual");
|
15
|
+
const Menu$1 = "";
|
16
|
+
const MenuBase = react.forwardRef(({
|
17
|
+
children,
|
18
|
+
size,
|
19
|
+
isVirtual,
|
20
|
+
...props
|
21
|
+
}, ref) => {
|
22
|
+
const classes = classix.cx("Menu", isVirtual && "Menu--isVirtual", size && `MenuSize--${size}`);
|
23
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", {
|
24
|
+
...props,
|
25
|
+
role: "menu",
|
26
|
+
className: classes,
|
27
|
+
ref,
|
28
|
+
children
|
29
|
+
});
|
31
30
|
});
|
32
|
-
module.exports = __toCommonJS(src_exports);
|
33
|
-
|
34
|
-
// src/MenuBase.tsx
|
35
|
-
var import_classix = require("classix");
|
36
|
-
var import_react = require("react");
|
37
|
-
var import_Menu = require("./styles/Menu.css");
|
38
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
39
|
-
var MenuBase = (0, import_react.forwardRef)(
|
40
|
-
({ children, size, isVirtual, ...props }, ref) => {
|
41
|
-
const classes = (0, import_classix.cx)("Menu", isVirtual && "Menu--isVirtual", size && `MenuSize--${size}`);
|
42
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
43
|
-
...props,
|
44
|
-
role: "menu",
|
45
|
-
className: classes,
|
46
|
-
ref,
|
47
|
-
children
|
48
|
-
});
|
49
|
-
}
|
50
|
-
);
|
51
31
|
MenuBase.displayName = "MenuBase";
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
32
|
+
const MenuDivider = ({
|
33
|
+
elementType = "div",
|
34
|
+
orientation,
|
35
|
+
innerRef
|
36
|
+
}) => {
|
37
|
+
const {
|
38
|
+
separatorProps
|
39
|
+
} = separator.useSeparator({
|
59
40
|
orientation,
|
60
41
|
elementType
|
61
42
|
});
|
62
|
-
return /* @__PURE__ */
|
43
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", {
|
63
44
|
...separatorProps,
|
64
45
|
ref: innerRef,
|
65
46
|
className: "Menu-divider"
|
66
47
|
});
|
67
48
|
};
|
68
|
-
|
69
|
-
|
70
|
-
var import_icons = require("@launchpad-ui/icons");
|
71
|
-
var import_tooltip = require("@launchpad-ui/tooltip");
|
72
|
-
var import_react_slot = require("@radix-ui/react-slot");
|
73
|
-
var import_focus = require("@react-aria/focus");
|
74
|
-
var import_classix2 = require("classix");
|
75
|
-
var import_react_router_dom = require("react-router-dom");
|
76
|
-
var import_Menu3 = require("./styles/Menu.css");
|
77
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
78
|
-
var defaultElement = "button";
|
79
|
-
var MenuItem = ({
|
49
|
+
const defaultElement = "button";
|
50
|
+
const MenuItem = ({
|
80
51
|
...props
|
81
52
|
}) => {
|
82
53
|
const {
|
@@ -89,7 +60,7 @@ var MenuItem = ({
|
|
89
60
|
item,
|
90
61
|
disabled,
|
91
62
|
className,
|
92
|
-
tooltip,
|
63
|
+
tooltip: tooltip$1,
|
93
64
|
role = "menuitem",
|
94
65
|
tooltipPlacement,
|
95
66
|
onKeyDown,
|
@@ -97,39 +68,32 @@ var MenuItem = ({
|
|
97
68
|
asChild,
|
98
69
|
...rest
|
99
70
|
} = props;
|
100
|
-
const Component = component || (asChild ?
|
101
|
-
const renderedItem = /* @__PURE__ */
|
71
|
+
const Component = component || (asChild ? reactSlot.Slot : defaultElement);
|
72
|
+
const renderedItem = /* @__PURE__ */ jsxRuntime.jsx(focus.FocusRing, {
|
102
73
|
focusRingClass: "has-focus",
|
103
|
-
children: /* @__PURE__ */
|
74
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Component, {
|
104
75
|
...rest,
|
105
76
|
disabled,
|
106
77
|
"aria-disabled": disabled ? disabled : void 0,
|
107
|
-
className: (
|
108
|
-
"Menu-item",
|
109
|
-
className,
|
110
|
-
isHighlighted && "is-highlighted",
|
111
|
-
nested && "Menu-item--nested",
|
112
|
-
groupHeader && "Menu-item--header"
|
113
|
-
),
|
78
|
+
className: classix.cx("Menu-item", className, isHighlighted && "is-highlighted", nested && "Menu-item--nested", groupHeader && "Menu-item--header"),
|
114
79
|
role,
|
115
80
|
onKeyDown,
|
116
|
-
children: asChild ? children : /* @__PURE__ */
|
117
|
-
children: [
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
}),
|
124
|
-
children
|
125
|
-
]
|
81
|
+
children: asChild ? children : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
82
|
+
children: [Icon && /* @__PURE__ */ jsxRuntime.jsx("span", {
|
83
|
+
className: "Menu-item-icon",
|
84
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
|
85
|
+
size: icons.IconSize.SMALL
|
86
|
+
})
|
87
|
+
}), children]
|
126
88
|
})
|
127
89
|
})
|
128
90
|
});
|
129
|
-
if (tooltip) {
|
130
|
-
return /* @__PURE__ */
|
131
|
-
content: tooltip,
|
132
|
-
rootElementStyle: {
|
91
|
+
if (tooltip$1) {
|
92
|
+
return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip, {
|
93
|
+
content: tooltip$1,
|
94
|
+
rootElementStyle: {
|
95
|
+
display: "block"
|
96
|
+
},
|
133
97
|
allowBoundaryElementOverflow: true,
|
134
98
|
placement: tooltipPlacement ? tooltipPlacement : "bottom",
|
135
99
|
...tooltipOptions || {},
|
@@ -138,7 +102,7 @@ var MenuItem = ({
|
|
138
102
|
}
|
139
103
|
return renderedItem;
|
140
104
|
};
|
141
|
-
|
105
|
+
const MenuItemLink = ({
|
142
106
|
to,
|
143
107
|
disabled = false,
|
144
108
|
useHistory = true,
|
@@ -149,22 +113,20 @@ var MenuItemLink = ({
|
|
149
113
|
const finalProps = {
|
150
114
|
...props,
|
151
115
|
disabled,
|
152
|
-
component: useHistory ?
|
116
|
+
component: useHistory ? reactRouterDom.Link : "a",
|
153
117
|
[useHistory ? "to" : "href"]: disabled ? "" : to,
|
154
118
|
rel: newTab ? "noopener noreferrer" : void 0,
|
155
119
|
target: newTab ? "_blank" : void 0
|
156
120
|
};
|
157
|
-
return /* @__PURE__ */
|
121
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MenuItem, {
|
158
122
|
...finalProps,
|
159
123
|
children
|
160
124
|
});
|
161
125
|
};
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
167
|
-
var MenuItemList = (0, import_react2.forwardRef)(({ children, ...rest }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
126
|
+
const MenuItemList = react.forwardRef(({
|
127
|
+
children,
|
128
|
+
...rest
|
129
|
+
}, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", {
|
168
130
|
...rest,
|
169
131
|
ref,
|
170
132
|
"data-test-id": "menu-item-list",
|
@@ -172,17 +134,15 @@ var MenuItemList = (0, import_react2.forwardRef)(({ children, ...rest }, ref) =>
|
|
172
134
|
children
|
173
135
|
}));
|
174
136
|
MenuItemList.displayName = "MenuItemList";
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
const { ariaLabel, placeholder, ...finalProps } = props;
|
183
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
137
|
+
const MenuSearch = react.forwardRef((props, ref) => {
|
138
|
+
const {
|
139
|
+
ariaLabel,
|
140
|
+
placeholder,
|
141
|
+
...finalProps
|
142
|
+
} = props;
|
143
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", {
|
184
144
|
className: "Menu-search",
|
185
|
-
children: /* @__PURE__ */
|
145
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(form.TextField, {
|
186
146
|
...finalProps,
|
187
147
|
ref,
|
188
148
|
className: "Menu-search-input",
|
@@ -195,17 +155,10 @@ var MenuSearch = (0, import_react3.forwardRef)((props, ref) => {
|
|
195
155
|
});
|
196
156
|
});
|
197
157
|
MenuSearch.displayName = "MenuSearch";
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
var
|
202
|
-
var import_react4 = require("react");
|
203
|
-
var import_react_virtual = require("react-virtual");
|
204
|
-
|
205
|
-
// src/utils.ts
|
206
|
-
var createItemId = (index, id) => `${id}-item-${index}`;
|
207
|
-
var getNodeForIndex = (index, menuId) => index === null ? index : document.getElementById(createItemId(index, menuId));
|
208
|
-
var handleKeyboardInteractions = (event, keyHandlers) => {
|
158
|
+
const createItemId = (index, id) => `${id}-item-${index}`;
|
159
|
+
const getNodeForIndex = (index, menuId) => index === null ? index : document.getElementById(createItemId(index, menuId));
|
160
|
+
const handleKeyboardInteractions = (event, keyHandlers) => {
|
161
|
+
var _a;
|
209
162
|
const ops = {
|
210
163
|
ArrowUp: keyHandlers.handleUp,
|
211
164
|
ArrowDown: keyHandlers.handleDown,
|
@@ -213,16 +166,13 @@ var handleKeyboardInteractions = (event, keyHandlers) => {
|
|
213
166
|
};
|
214
167
|
if (ops[event.key]) {
|
215
168
|
event.preventDefault();
|
216
|
-
ops[event.key]
|
169
|
+
(_a = ops[event.key]) == null ? void 0 : _a.call(globalThis, event);
|
217
170
|
}
|
218
171
|
};
|
219
|
-
|
172
|
+
const chainEventHandlers = (...handlers) => (event) => {
|
220
173
|
handlers.forEach((h) => typeof h === "function" && h(event));
|
221
174
|
};
|
222
|
-
|
223
|
-
// src/Menu.tsx
|
224
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
225
|
-
var Menu = (props) => {
|
175
|
+
const Menu = (props) => {
|
226
176
|
const {
|
227
177
|
children,
|
228
178
|
menuItemClassName,
|
@@ -232,15 +182,19 @@ var Menu = (props) => {
|
|
232
182
|
size,
|
233
183
|
overscan = 1
|
234
184
|
} = props;
|
235
|
-
const focusManager =
|
236
|
-
const handleArrowDown =
|
237
|
-
focusManager.focusNext({
|
185
|
+
const focusManager = focus.useFocusManager();
|
186
|
+
const handleArrowDown = react.useCallback(() => {
|
187
|
+
focusManager.focusNext({
|
188
|
+
wrap: true
|
189
|
+
});
|
238
190
|
}, [focusManager]);
|
239
|
-
const handleArrowUp =
|
240
|
-
focusManager.focusPrevious({
|
191
|
+
const handleArrowUp = react.useCallback(() => {
|
192
|
+
focusManager.focusPrevious({
|
193
|
+
wrap: true
|
194
|
+
});
|
241
195
|
}, [focusManager]);
|
242
|
-
const reduceItems =
|
243
|
-
const childrenProps =
|
196
|
+
const reduceItems = react.useMemo(() => {
|
197
|
+
const childrenProps = react.Children.toArray(children);
|
244
198
|
if (enableVirtualization) {
|
245
199
|
let searchElem = null;
|
246
200
|
let elements = [];
|
@@ -254,63 +208,73 @@ var Menu = (props) => {
|
|
254
208
|
case MenuDivider:
|
255
209
|
elements = elements.concat(child);
|
256
210
|
break;
|
257
|
-
default:
|
258
|
-
break;
|
259
211
|
}
|
260
212
|
});
|
261
|
-
return {
|
213
|
+
return {
|
214
|
+
items: elements,
|
215
|
+
searchElement: searchElem
|
216
|
+
};
|
262
217
|
}
|
263
|
-
return childrenProps.reduce(
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
218
|
+
return childrenProps.reduce(({
|
219
|
+
items,
|
220
|
+
searchElement
|
221
|
+
}, child) => {
|
222
|
+
var _a;
|
223
|
+
switch (child.type) {
|
224
|
+
case MenuSearch:
|
225
|
+
return {
|
226
|
+
items,
|
227
|
+
searchElement: react.cloneElement(child, {
|
228
|
+
onKeyDown: (e) => handleKeyboardInteractions(e, {
|
229
|
+
handleDown: handleArrowDown,
|
230
|
+
handleUp: handleArrowUp
|
274
231
|
})
|
275
|
-
}
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
232
|
+
})
|
233
|
+
};
|
234
|
+
case MenuItem:
|
235
|
+
case MenuItemLink:
|
236
|
+
return {
|
237
|
+
items: items.concat(child.props.disabled ? react.cloneElement(child, {
|
238
|
+
onClick: () => void 0,
|
239
|
+
onKeyDown: () => void 0,
|
240
|
+
tabIndex: -1,
|
241
|
+
disabled: true
|
242
|
+
}) : react.cloneElement(child, {
|
243
|
+
className: classix.cx(child.props.className, menuItemClassName),
|
244
|
+
item: (_a = child.props.item) != null ? _a : items.length,
|
245
|
+
onClick: chainEventHandlers(child.props.onClick, () => {
|
246
|
+
var _a2;
|
247
|
+
onSelect == null ? void 0 : onSelect((_a2 = child.props.item) != null ? _a2 : items.length);
|
248
|
+
}),
|
249
|
+
onKeyDown: (e) => handleKeyboardInteractions(e, {
|
250
|
+
handleDown: handleArrowDown,
|
251
|
+
handleUp: handleArrowUp
|
252
|
+
})
|
253
|
+
})),
|
254
|
+
searchElement
|
255
|
+
};
|
256
|
+
case MenuDivider:
|
257
|
+
return {
|
258
|
+
items: items.concat(child),
|
259
|
+
searchElement
|
260
|
+
};
|
261
|
+
default:
|
262
|
+
return {
|
263
|
+
items,
|
264
|
+
searchElement
|
265
|
+
};
|
266
|
+
}
|
267
|
+
}, {
|
268
|
+
items: [],
|
269
|
+
searchElement: null
|
270
|
+
});
|
307
271
|
}, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);
|
308
272
|
if (enableVirtualization) {
|
309
|
-
return /* @__PURE__ */
|
273
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MenuBase, {
|
310
274
|
isVirtual: true,
|
311
275
|
size,
|
312
|
-
children: /* @__PURE__ */
|
313
|
-
items:
|
276
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ItemVirtualizer, {
|
277
|
+
items: react.Children.toArray(reduceItems.items),
|
314
278
|
searchElement: reduceItems.searchElement,
|
315
279
|
overscan,
|
316
280
|
menuItemClassName,
|
@@ -320,18 +284,15 @@ var Menu = (props) => {
|
|
320
284
|
})
|
321
285
|
});
|
322
286
|
}
|
323
|
-
return /* @__PURE__ */
|
287
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(MenuBase, {
|
324
288
|
size,
|
325
|
-
children: [
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
children: reduceItems.items
|
330
|
-
})
|
331
|
-
]
|
289
|
+
children: [reduceItems.searchElement, /* @__PURE__ */ jsxRuntime.jsx(MenuItemList, {
|
290
|
+
role: "presentation",
|
291
|
+
children: reduceItems.items
|
292
|
+
})]
|
332
293
|
});
|
333
294
|
};
|
334
|
-
|
295
|
+
const ItemVirtualizer = (props) => {
|
335
296
|
const {
|
336
297
|
overscan,
|
337
298
|
searchElement,
|
@@ -341,158 +302,138 @@ var ItemVirtualizer = (props) => {
|
|
341
302
|
focusManager,
|
342
303
|
onSelect
|
343
304
|
} = props;
|
344
|
-
const menuId =
|
345
|
-
const focusedItemIndex =
|
346
|
-
const parentRef =
|
347
|
-
const searchRef =
|
348
|
-
const [nextFocusValue, setNextFocusValue] =
|
305
|
+
const menuId = react.useRef(`menu-ctrl-${react.useId()}`);
|
306
|
+
const focusedItemIndex = react.useRef(null);
|
307
|
+
const parentRef = react.useRef(null);
|
308
|
+
const searchRef = react.useRef();
|
309
|
+
const [nextFocusValue, setNextFocusValue] = react.useState(null);
|
349
310
|
const hasSearch = !!searchElement;
|
350
311
|
const lastVirtualItemIndex = items ? items.length - 1 : 0;
|
351
|
-
const rowVirtualizer =
|
312
|
+
const rowVirtualizer = reactVirtual.useVirtual({
|
352
313
|
size: items !== null ? items.length : 0,
|
353
314
|
parentRef,
|
354
|
-
estimateSize:
|
315
|
+
estimateSize: react.useCallback(() => itemHeight, [itemHeight]),
|
355
316
|
overscan
|
356
317
|
});
|
357
|
-
const focusSearchBar =
|
318
|
+
const focusSearchBar = react.useCallback(() => {
|
319
|
+
var _a, _b;
|
358
320
|
rowVirtualizer.scrollToIndex(0);
|
359
|
-
searchRef.current
|
321
|
+
(_b = (_a = searchRef.current) == null ? void 0 : _a.focus) == null ? void 0 : _b.call(_a);
|
360
322
|
}, [rowVirtualizer]);
|
361
|
-
const focusMenuItem =
|
362
|
-
(index)
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
if (hasSearch) {
|
377
|
-
focusSearchBar();
|
378
|
-
} else {
|
379
|
-
focusMenuItem(direction === "next" ? 0 : lastVirtualItemIndex);
|
380
|
-
}
|
381
|
-
return;
|
382
|
-
}
|
383
|
-
switch (direction) {
|
384
|
-
case "next":
|
385
|
-
rowVirtualizer.scrollToIndex(nextIndex);
|
386
|
-
focusManager.focusNext();
|
387
|
-
break;
|
388
|
-
case "previous":
|
389
|
-
rowVirtualizer.scrollToIndex(nextIndex);
|
390
|
-
focusManager.focusPrevious();
|
391
|
-
break;
|
392
|
-
default:
|
393
|
-
break;
|
394
|
-
}
|
395
|
-
},
|
396
|
-
[focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]
|
397
|
-
);
|
398
|
-
const getItemProps = (0, import_react4.useCallback)(
|
399
|
-
(itemElem, index) => {
|
400
|
-
const childProps = itemElem.props;
|
401
|
-
switch (itemElem.type) {
|
402
|
-
case MenuItem:
|
403
|
-
case MenuItemLink:
|
404
|
-
return {
|
405
|
-
className: (0, import_classix3.cx)(childProps.className, menuItemClassName),
|
406
|
-
onKeyDown: childProps.disabled ? () => void 0 : (e) => handleKeyboardFocusKeydown(e, {
|
407
|
-
handleFocusBackward: handleKeyboardFocusInteraction,
|
408
|
-
handleFocusForward: handleKeyboardFocusInteraction
|
409
|
-
}),
|
410
|
-
onFocus: chainEventHandlers(childProps.onFocus, () => {
|
411
|
-
focusedItemIndex.current = index;
|
412
|
-
}),
|
413
|
-
id: createItemId(index, menuId.current),
|
414
|
-
onBlur: chainEventHandlers(childProps.onBlur, () => {
|
415
|
-
focusedItemIndex.current = null;
|
416
|
-
}),
|
417
|
-
onClick: childProps.disabled ? () => void 0 : chainEventHandlers(childProps.onClick, () => {
|
418
|
-
onSelect?.(childProps.item);
|
419
|
-
})
|
420
|
-
};
|
421
|
-
default:
|
422
|
-
return {};
|
323
|
+
const focusMenuItem = react.useCallback((index) => {
|
324
|
+
rowVirtualizer.scrollToIndex(index);
|
325
|
+
setNextFocusValue(index);
|
326
|
+
}, [rowVirtualizer]);
|
327
|
+
const handleKeyboardFocusInteraction = react.useCallback((direction) => {
|
328
|
+
if (focusedItemIndex.current === null || focusedItemIndex.current === void 0) {
|
329
|
+
return;
|
330
|
+
}
|
331
|
+
const nextIndex = direction === "next" ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;
|
332
|
+
const shouldWrap = direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0;
|
333
|
+
if (shouldWrap) {
|
334
|
+
if (hasSearch) {
|
335
|
+
focusSearchBar();
|
336
|
+
} else {
|
337
|
+
focusMenuItem(direction === "next" ? 0 : lastVirtualItemIndex);
|
423
338
|
}
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
339
|
+
return;
|
340
|
+
}
|
341
|
+
switch (direction) {
|
342
|
+
case "next":
|
343
|
+
rowVirtualizer.scrollToIndex(nextIndex);
|
344
|
+
focusManager.focusNext();
|
345
|
+
break;
|
346
|
+
case "previous":
|
347
|
+
rowVirtualizer.scrollToIndex(nextIndex);
|
348
|
+
focusManager.focusPrevious();
|
349
|
+
break;
|
350
|
+
}
|
351
|
+
}, [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]);
|
352
|
+
const getItemProps = react.useCallback((itemElem, index) => {
|
353
|
+
const childProps = itemElem.props;
|
354
|
+
switch (itemElem.type) {
|
355
|
+
case MenuItem:
|
356
|
+
case MenuItemLink:
|
357
|
+
return {
|
358
|
+
className: classix.cx(childProps.className, menuItemClassName),
|
359
|
+
onKeyDown: childProps.disabled ? () => void 0 : (e) => handleKeyboardFocusKeydown(e, {
|
360
|
+
handleFocusBackward: handleKeyboardFocusInteraction,
|
361
|
+
handleFocusForward: handleKeyboardFocusInteraction
|
362
|
+
}),
|
363
|
+
onFocus: chainEventHandlers(childProps.onFocus, () => {
|
364
|
+
focusedItemIndex.current = index;
|
365
|
+
}),
|
366
|
+
id: createItemId(index, menuId.current),
|
367
|
+
onBlur: chainEventHandlers(childProps.onBlur, () => {
|
368
|
+
focusedItemIndex.current = null;
|
369
|
+
}),
|
370
|
+
onClick: childProps.disabled ? () => void 0 : chainEventHandlers(childProps.onClick, () => {
|
371
|
+
onSelect == null ? void 0 : onSelect(childProps.item);
|
372
|
+
})
|
373
|
+
};
|
374
|
+
default:
|
375
|
+
return {};
|
376
|
+
}
|
377
|
+
}, [handleKeyboardFocusInteraction, menuItemClassName, onSelect]);
|
378
|
+
react.useEffect(() => {
|
428
379
|
if (nextFocusValue !== null) {
|
429
380
|
requestAnimationFrame(() => {
|
430
381
|
const element = getNodeForIndex(nextFocusValue, menuId.current);
|
431
|
-
element
|
382
|
+
element == null ? void 0 : element.focus();
|
432
383
|
});
|
433
384
|
setNextFocusValue(null);
|
434
385
|
}
|
435
386
|
}, [nextFocusValue]);
|
436
387
|
const handleKeyboardFocusKeydown = (e, callbacks) => {
|
388
|
+
var _a, _b;
|
437
389
|
const keyOps = ["Tab", "ArrowUp", "ArrowDown"];
|
438
390
|
if (keyOps.includes(e.key)) {
|
439
391
|
e.preventDefault();
|
440
392
|
e.stopPropagation();
|
441
393
|
if (e.key === "Tab" && e.shiftKey || e.key === "ArrowUp") {
|
442
|
-
callbacks.handleFocusBackward
|
394
|
+
(_a = callbacks.handleFocusBackward) == null ? void 0 : _a.call(callbacks, "previous");
|
443
395
|
} else if (e.key === "ArrowDown" || e.key === "Tab") {
|
444
|
-
callbacks.handleFocusForward
|
396
|
+
(_b = callbacks.handleFocusForward) == null ? void 0 : _b.call(callbacks, "next");
|
445
397
|
}
|
446
398
|
}
|
447
399
|
};
|
448
|
-
const renderSearch = (
|
449
|
-
() =>
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
400
|
+
const renderSearch = react.useMemo(() => searchElement ? react.cloneElement(searchElement, {
|
401
|
+
onKeyDown: (e) => handleKeyboardFocusKeydown(e, {
|
402
|
+
handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),
|
403
|
+
handleFocusForward: () => focusMenuItem(0)
|
404
|
+
}),
|
405
|
+
ref: searchRef
|
406
|
+
}) : null, [searchElement, lastVirtualItemIndex, focusMenuItem]);
|
407
|
+
const renderItems = react.useMemo(() => rowVirtualizer.virtualItems.map((virtualRow) => {
|
408
|
+
if (!items) {
|
409
|
+
return null;
|
410
|
+
}
|
411
|
+
const elem = items[virtualRow.index];
|
412
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", {
|
413
|
+
ref: elem.type !== MenuItem || elem.type !== MenuItemLink ? virtualRow.measureRef : void 0,
|
414
|
+
role: "presentation",
|
415
|
+
className: classix.cx("VirtualMenu-item"),
|
416
|
+
style: {
|
417
|
+
transform: `translateY(${virtualRow.start}px)`
|
418
|
+
},
|
419
|
+
children: react.cloneElement(elem, getItemProps(elem, virtualRow.index))
|
420
|
+
}, virtualRow.index);
|
421
|
+
}), [rowVirtualizer.virtualItems, items, getItemProps]);
|
422
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
423
|
+
children: [renderSearch, /* @__PURE__ */ jsxRuntime.jsx(MenuItemList, {
|
424
|
+
ref: parentRef,
|
425
|
+
role: "presentation",
|
426
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", {
|
466
427
|
role: "presentation",
|
467
|
-
className:
|
428
|
+
className: "VirtualMenu-item-list",
|
468
429
|
style: {
|
469
|
-
|
430
|
+
height: `${rowVirtualizer.totalSize}px`
|
470
431
|
},
|
471
|
-
children:
|
472
|
-
}, virtualRow.index);
|
473
|
-
}),
|
474
|
-
[rowVirtualizer.virtualItems, items, getItemProps]
|
475
|
-
);
|
476
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
|
477
|
-
children: [
|
478
|
-
renderSearch,
|
479
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuItemList, {
|
480
|
-
ref: parentRef,
|
481
|
-
role: "presentation",
|
482
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
483
|
-
role: "presentation",
|
484
|
-
className: "VirtualMenu-item-list",
|
485
|
-
style: {
|
486
|
-
height: `${rowVirtualizer.totalSize}px`
|
487
|
-
},
|
488
|
-
children: renderItems
|
489
|
-
})
|
432
|
+
children: renderItems
|
490
433
|
})
|
491
|
-
]
|
434
|
+
})]
|
492
435
|
});
|
493
436
|
};
|
494
|
-
|
495
|
-
// src/types.ts
|
496
437
|
var MenuSize = /* @__PURE__ */ ((MenuSize2) => {
|
497
438
|
MenuSize2["SMALL"] = "sm";
|
498
439
|
MenuSize2["MEDIUM"] = "md";
|
@@ -500,15 +441,12 @@ var MenuSize = /* @__PURE__ */ ((MenuSize2) => {
|
|
500
441
|
MenuSize2["EXTRA_LARGE"] = "xl";
|
501
442
|
return MenuSize2;
|
502
443
|
})(MenuSize || {});
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
MenuSearch,
|
512
|
-
MenuSize
|
513
|
-
});
|
444
|
+
exports.Menu = Menu;
|
445
|
+
exports.MenuBase = MenuBase;
|
446
|
+
exports.MenuDivider = MenuDivider;
|
447
|
+
exports.MenuItem = MenuItem;
|
448
|
+
exports.MenuItemLink = MenuItemLink;
|
449
|
+
exports.MenuItemList = MenuItemList;
|
450
|
+
exports.MenuSearch = MenuSearch;
|
451
|
+
exports.MenuSize = MenuSize;
|
514
452
|
//# sourceMappingURL=index.js.map
|