@launchpad-ui/menu 0.4.7 → 0.5.1

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/index.js CHANGED
@@ -1,82 +1,53 @@
1
+ require('./style.css');
1
2
  "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- Menu: () => Menu,
24
- MenuBase: () => MenuBase,
25
- MenuDivider: () => MenuDivider,
26
- MenuItem: () => MenuItem,
27
- MenuItemLink: () => MenuItemLink,
28
- MenuItemList: () => MenuItemList,
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
- // src/MenuDivider.tsx
54
- var import_separator = require("@react-aria/separator");
55
- var import_Menu2 = require("./styles/Menu.css");
56
- var import_jsx_runtime = require("react/jsx-runtime");
57
- var MenuDivider = ({ elementType = "div", orientation, innerRef }) => {
58
- const { separatorProps } = (0, import_separator.useSeparator)({
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__ */ (0, import_jsx_runtime.jsx)("div", {
43
+ return /* @__PURE__ */ jsxRuntime.jsx("div", {
63
44
  ...separatorProps,
64
45
  ref: innerRef,
65
46
  className: "Menu-divider"
66
47
  });
67
48
  };
68
-
69
- // src/MenuItem.tsx
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 ? import_react_slot.Slot : defaultElement);
101
- const renderedItem = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_focus.FocusRing, {
71
+ const Component = component || (asChild ? reactSlot.Slot : defaultElement);
72
+ const renderedItem = /* @__PURE__ */ jsxRuntime.jsx(focus.FocusRing, {
102
73
  focusRingClass: "has-focus",
103
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, {
74
+ children: /* @__PURE__ */ jsxRuntime.jsx(Component, {
104
75
  ...rest,
105
76
  disabled,
106
77
  "aria-disabled": disabled ? disabled : void 0,
107
- className: (0, import_classix2.cx)(
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__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
117
- children: [
118
- Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
119
- className: "Menu-item-icon",
120
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, {
121
- size: import_icons.IconSize.SMALL
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__ */ (0, import_jsx_runtime.jsx)(import_tooltip.Tooltip, {
131
- content: tooltip,
132
- rootElementStyle: { display: "block" },
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
- var MenuItemLink = ({
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 ? import_react_router_dom.Link : "a",
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__ */ (0, import_jsx_runtime.jsx)(MenuItem, {
121
+ return /* @__PURE__ */ jsxRuntime.jsx(MenuItem, {
158
122
  ...finalProps,
159
123
  children
160
124
  });
161
125
  };
162
-
163
- // src/MenuItemList.tsx
164
- var import_react2 = require("react");
165
- var import_Menu4 = require("./styles/Menu.css");
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
- // src/MenuSearch.tsx
177
- var import_form = require("@launchpad-ui/form");
178
- var import_react3 = require("react");
179
- var import_Menu5 = require("./styles/Menu.css");
180
- var import_jsx_runtime = require("react/jsx-runtime");
181
- var MenuSearch = (0, import_react3.forwardRef)((props, ref) => {
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__ */ (0, import_jsx_runtime.jsx)(import_form.TextField, {
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
- // src/Menu.tsx
200
- var import_focus2 = require("@react-aria/focus");
201
- var import_classix3 = require("classix");
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]?.call(globalThis, event);
169
+ (_a = ops[event.key]) == null ? void 0 : _a.call(globalThis, event);
217
170
  }
218
171
  };
219
- var chainEventHandlers = (...handlers) => (event) => {
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 = (0, import_focus2.useFocusManager)();
236
- const handleArrowDown = (0, import_react4.useCallback)(() => {
237
- focusManager.focusNext({ wrap: true });
185
+ const focusManager = focus.useFocusManager();
186
+ const handleArrowDown = react.useCallback(() => {
187
+ focusManager.focusNext({
188
+ wrap: true
189
+ });
238
190
  }, [focusManager]);
239
- const handleArrowUp = (0, import_react4.useCallback)(() => {
240
- focusManager.focusPrevious({ wrap: true });
191
+ const handleArrowUp = react.useCallback(() => {
192
+ focusManager.focusPrevious({
193
+ wrap: true
194
+ });
241
195
  }, [focusManager]);
242
- const reduceItems = (0, import_react4.useMemo)(() => {
243
- const childrenProps = import_react4.Children.toArray(children);
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 { items: elements, searchElement: searchElem };
213
+ return {
214
+ items: elements,
215
+ searchElement: searchElem
216
+ };
262
217
  }
263
- return childrenProps.reduce(
264
- ({ items, searchElement }, child) => {
265
- switch (child.type) {
266
- case MenuSearch:
267
- return {
268
- items,
269
- searchElement: (0, import_react4.cloneElement)(child, {
270
- onKeyDown: (e) => handleKeyboardInteractions(e, {
271
- handleDown: handleArrowDown,
272
- handleUp: handleArrowUp
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
- case MenuItem:
277
- case MenuItemLink:
278
- return {
279
- items: items.concat(
280
- child.props.disabled ? (0, import_react4.cloneElement)(child, {
281
- onClick: () => void 0,
282
- onKeyDown: () => void 0,
283
- tabIndex: -1,
284
- disabled: true
285
- }) : (0, import_react4.cloneElement)(child, {
286
- className: (0, import_classix3.cx)(child.props.className, menuItemClassName),
287
- item: child.props.item ?? items.length,
288
- onClick: chainEventHandlers(child.props.onClick, () => {
289
- onSelect?.(child.props.item ?? items.length);
290
- }),
291
- onKeyDown: (e) => handleKeyboardInteractions(e, {
292
- handleDown: handleArrowDown,
293
- handleUp: handleArrowUp
294
- })
295
- })
296
- ),
297
- searchElement
298
- };
299
- case MenuDivider:
300
- return { items: items.concat(child), searchElement };
301
- default:
302
- return { items, searchElement };
303
- }
304
- },
305
- { items: [], searchElement: null }
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__ */ (0, import_jsx_runtime.jsx)(MenuBase, {
273
+ return /* @__PURE__ */ jsxRuntime.jsx(MenuBase, {
310
274
  isVirtual: true,
311
275
  size,
312
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ItemVirtualizer, {
313
- items: import_react4.Children.toArray(reduceItems.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__ */ (0, import_jsx_runtime.jsxs)(MenuBase, {
287
+ return /* @__PURE__ */ jsxRuntime.jsxs(MenuBase, {
324
288
  size,
325
- children: [
326
- reduceItems.searchElement,
327
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuItemList, {
328
- role: "presentation",
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
- var ItemVirtualizer = (props) => {
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 = (0, import_react4.useRef)(`menu-ctrl-${(0, import_react4.useId)()}`);
345
- const focusedItemIndex = (0, import_react4.useRef)(null);
346
- const parentRef = (0, import_react4.useRef)(null);
347
- const searchRef = (0, import_react4.useRef)();
348
- const [nextFocusValue, setNextFocusValue] = (0, import_react4.useState)(null);
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 = (0, import_react_virtual.useVirtual)({
312
+ const rowVirtualizer = reactVirtual.useVirtual({
352
313
  size: items !== null ? items.length : 0,
353
314
  parentRef,
354
- estimateSize: (0, import_react4.useCallback)(() => itemHeight, [itemHeight]),
315
+ estimateSize: react.useCallback(() => itemHeight, [itemHeight]),
355
316
  overscan
356
317
  });
357
- const focusSearchBar = (0, import_react4.useCallback)(() => {
318
+ const focusSearchBar = react.useCallback(() => {
319
+ var _a, _b;
358
320
  rowVirtualizer.scrollToIndex(0);
359
- searchRef.current?.focus?.();
321
+ (_b = (_a = searchRef.current) == null ? void 0 : _a.focus) == null ? void 0 : _b.call(_a);
360
322
  }, [rowVirtualizer]);
361
- const focusMenuItem = (0, import_react4.useCallback)(
362
- (index) => {
363
- rowVirtualizer.scrollToIndex(index);
364
- setNextFocusValue(index);
365
- },
366
- [rowVirtualizer]
367
- );
368
- const handleKeyboardFocusInteraction = (0, import_react4.useCallback)(
369
- (direction) => {
370
- if (focusedItemIndex.current === null || focusedItemIndex.current === void 0) {
371
- return;
372
- }
373
- const nextIndex = direction === "next" ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;
374
- const shouldWrap = direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0;
375
- if (shouldWrap) {
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
- [handleKeyboardFocusInteraction, menuItemClassName, onSelect]
426
- );
427
- (0, import_react4.useEffect)(() => {
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?.focus();
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?.("previous");
394
+ (_a = callbacks.handleFocusBackward) == null ? void 0 : _a.call(callbacks, "previous");
443
395
  } else if (e.key === "ArrowDown" || e.key === "Tab") {
444
- callbacks.handleFocusForward?.("next");
396
+ (_b = callbacks.handleFocusForward) == null ? void 0 : _b.call(callbacks, "next");
445
397
  }
446
398
  }
447
399
  };
448
- const renderSearch = (0, import_react4.useMemo)(
449
- () => searchElement ? (0, import_react4.cloneElement)(searchElement, {
450
- onKeyDown: (e) => handleKeyboardFocusKeydown(e, {
451
- handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),
452
- handleFocusForward: () => focusMenuItem(0)
453
- }),
454
- ref: searchRef
455
- }) : null,
456
- [searchElement, lastVirtualItemIndex, focusMenuItem]
457
- );
458
- const renderItems = (0, import_react4.useMemo)(
459
- () => rowVirtualizer.virtualItems.map((virtualRow) => {
460
- if (!items) {
461
- return null;
462
- }
463
- const elem = items[virtualRow.index];
464
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
465
- ref: elem.type !== MenuItem || elem.type !== MenuItemLink ? virtualRow.measureRef : void 0,
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: (0, import_classix3.cx)("VirtualMenu-item"),
428
+ className: "VirtualMenu-item-list",
468
429
  style: {
469
- transform: `translateY(${virtualRow.start}px)`
430
+ height: `${rowVirtualizer.totalSize}px`
470
431
  },
471
- children: (0, import_react4.cloneElement)(elem, getItemProps(elem, virtualRow.index))
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
- // Annotate the CommonJS export names for ESM import in node:
504
- 0 && (module.exports = {
505
- Menu,
506
- MenuBase,
507
- MenuDivider,
508
- MenuItem,
509
- MenuItemLink,
510
- MenuItemList,
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