@launchpad-ui/menu 0.6.39 → 0.6.40

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,9 +1,9 @@
1
1
  require('./style.css');
2
2
  "use strict";
3
- Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
4
5
  const classix = require("classix");
5
6
  const react = require("react");
6
- const jsxRuntime = require("react/jsx-runtime");
7
7
  const separator = require("@react-aria/separator");
8
8
  const tooltip = require("@launchpad-ui/tooltip");
9
9
  const reactSlot = require("@radix-ui/react-slot");
@@ -12,21 +12,12 @@ const reactRouterDom = require("react-router-dom");
12
12
  const form = require("@launchpad-ui/form");
13
13
  const reactVirtual = require("react-virtual");
14
14
  const Menu$1 = "";
15
- const MenuBase = react.forwardRef(({
16
- children,
17
- size,
18
- isVirtual,
19
- ...props
20
- }, ref) => {
21
- const classes = classix.cx("Menu", isVirtual && "Menu--isVirtual", size && `MenuSize--${size}`);
22
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
23
- ...props,
24
- role: "menu",
25
- className: classes,
26
- ref,
27
- children
28
- });
29
- });
15
+ const MenuBase = react.forwardRef(
16
+ ({ children, size, isVirtual, ...props }, ref) => {
17
+ const classes = classix.cx("Menu", isVirtual && "Menu--isVirtual", size && `MenuSize--${size}`);
18
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, role: "menu", className: classes, ref, children });
19
+ }
20
+ );
30
21
  MenuBase.displayName = "MenuBase";
31
22
  const MenuDivider = ({
32
23
  elementType = "div",
@@ -34,18 +25,11 @@ const MenuDivider = ({
34
25
  innerRef,
35
26
  "data-test-id": testId = "menu-divider"
36
27
  }) => {
37
- const {
38
- separatorProps
39
- } = separator.useSeparator({
28
+ const { separatorProps } = separator.useSeparator({
40
29
  orientation,
41
30
  elementType
42
31
  });
43
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
44
- ...separatorProps,
45
- "data-test-id": testId,
46
- ref: innerRef,
47
- className: "Menu-divider"
48
- });
32
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ...separatorProps, "data-test-id": testId, ref: innerRef, className: "Menu-divider" });
49
33
  };
50
34
  const defaultElement = "button";
51
35
  const MenuItem = ({
@@ -71,37 +55,40 @@ const MenuItem = ({
71
55
  ...rest
72
56
  } = props;
73
57
  const Component = component || (asChild ? reactSlot.Slot : defaultElement);
74
- const renderedItem = /* @__PURE__ */ jsxRuntime.jsx(focus.FocusRing, {
75
- focusRingClass: "has-focus",
76
- children: /* @__PURE__ */ jsxRuntime.jsx(Component, {
58
+ const renderedItem = /* @__PURE__ */ jsxRuntime.jsx(focus.FocusRing, { focusRingClass: "has-focus", children: /* @__PURE__ */ jsxRuntime.jsx(
59
+ Component,
60
+ {
77
61
  ...rest,
78
62
  disabled,
79
63
  "aria-disabled": disabled ? disabled : void 0,
80
- className: classix.cx("Menu-item", className, isHighlighted && "is-highlighted", nested && "Menu-item--nested", groupHeader && "Menu-item--header"),
64
+ className: classix.cx(
65
+ "Menu-item",
66
+ className,
67
+ isHighlighted && "is-highlighted",
68
+ nested && "Menu-item--nested",
69
+ groupHeader && "Menu-item--header"
70
+ ),
81
71
  "data-test-id": testId,
82
72
  role,
83
73
  onKeyDown,
84
- children: asChild ? children : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
85
- children: [Icon && /* @__PURE__ */ jsxRuntime.jsx("span", {
86
- className: "Menu-item-icon",
87
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {
88
- size: "small"
89
- })
90
- }), children]
91
- })
92
- })
93
- });
74
+ children: asChild ? children : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
75
+ Icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "Menu-item-icon", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: "small" }) }),
76
+ children
77
+ ] })
78
+ }
79
+ ) });
94
80
  if (tooltip$1) {
95
- return /* @__PURE__ */ jsxRuntime.jsx(tooltip.Tooltip, {
96
- content: tooltip$1,
97
- rootElementStyle: {
98
- display: "block"
99
- },
100
- allowBoundaryElementOverflow: true,
101
- placement: tooltipPlacement ? tooltipPlacement : "bottom",
102
- ...tooltipOptions || {},
103
- children: renderedItem
104
- });
81
+ return /* @__PURE__ */ jsxRuntime.jsx(
82
+ tooltip.Tooltip,
83
+ {
84
+ content: tooltip$1,
85
+ rootElementStyle: { display: "block" },
86
+ allowBoundaryElementOverflow: true,
87
+ placement: tooltipPlacement ? tooltipPlacement : "bottom",
88
+ ...tooltipOptions || {},
89
+ children: renderedItem
90
+ }
91
+ );
105
92
  }
106
93
  return renderedItem;
107
94
  };
@@ -121,32 +108,15 @@ const MenuItemLink = ({
121
108
  rel: newTab ? "noopener noreferrer" : void 0,
122
109
  target: newTab ? "_blank" : void 0
123
110
  };
124
- return /* @__PURE__ */ jsxRuntime.jsx(MenuItem, {
125
- ...finalProps,
126
- children
127
- });
111
+ return /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { ...finalProps, children });
128
112
  };
129
- const MenuItemList = react.forwardRef(({
130
- children,
131
- ...rest
132
- }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", {
133
- ...rest,
134
- ref,
135
- "data-test-id": "menu-item-list",
136
- className: "Menu-item-list",
137
- children
138
- }));
113
+ const MenuItemList = react.forwardRef(({ children, ...rest }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ...rest, ref, "data-test-id": "menu-item-list", className: "Menu-item-list", children }));
139
114
  MenuItemList.displayName = "MenuItemList";
140
115
  const MenuSearch = react.forwardRef((props, ref) => {
141
- const {
142
- ariaLabel,
143
- placeholder,
144
- "data-test-id": testId = "menu-search",
145
- ...finalProps
146
- } = props;
147
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
148
- className: "Menu-search",
149
- children: /* @__PURE__ */ jsxRuntime.jsx(form.TextField, {
116
+ const { ariaLabel, placeholder, "data-test-id": testId = "menu-search", ...finalProps } = props;
117
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "Menu-search", children: /* @__PURE__ */ jsxRuntime.jsx(
118
+ form.TextField,
119
+ {
150
120
  ...finalProps,
151
121
  ref,
152
122
  className: "Menu-search-input",
@@ -156,8 +126,8 @@ const MenuSearch = react.forwardRef((props, ref) => {
156
126
  autoComplete: "off",
157
127
  placeholder,
158
128
  "aria-label": ariaLabel || "Search"
159
- })
160
- });
129
+ }
130
+ ) });
161
131
  });
162
132
  MenuSearch.displayName = "MenuSearch";
163
133
  const createItemId = (index, id) => `${id}-item-${index}`;
@@ -190,14 +160,10 @@ const Menu = (props) => {
190
160
  } = props;
191
161
  const focusManager = focus.useFocusManager();
192
162
  const handleArrowDown = react.useCallback(() => {
193
- focusManager.focusNext({
194
- wrap: true
195
- });
163
+ focusManager.focusNext({ wrap: true });
196
164
  }, [focusManager]);
197
165
  const handleArrowUp = react.useCallback(() => {
198
- focusManager.focusPrevious({
199
- wrap: true
200
- });
166
+ focusManager.focusPrevious({ wrap: true });
201
167
  }, [focusManager]);
202
168
  const reduceItems = react.useMemo(() => {
203
169
  const childrenProps = react.Children.toArray(children);
@@ -216,71 +182,57 @@ const Menu = (props) => {
216
182
  break;
217
183
  }
218
184
  });
219
- return {
220
- items: elements,
221
- searchElement: searchElem
222
- };
185
+ return { items: elements, searchElement: searchElem };
223
186
  }
224
- return childrenProps.reduce(({
225
- items,
226
- searchElement
227
- }, child) => {
228
- var _a;
229
- switch (child.type) {
230
- case MenuSearch:
231
- return {
232
- items,
233
- searchElement: react.cloneElement(child, {
234
- onKeyDown: (e) => handleKeyboardInteractions(e, {
235
- handleDown: handleArrowDown,
236
- handleUp: handleArrowUp
237
- })
238
- })
239
- };
240
- case MenuItem:
241
- case MenuItemLink:
242
- return {
243
- items: items.concat(child.props.disabled ? react.cloneElement(child, {
244
- onClick: () => void 0,
245
- onKeyDown: () => void 0,
246
- tabIndex: -1,
247
- disabled: true
248
- }) : react.cloneElement(child, {
249
- className: classix.cx(child.props.className, menuItemClassName),
250
- item: (_a = child.props.item) != null ? _a : items.length,
251
- onClick: chainEventHandlers(child.props.onClick, () => {
252
- var _a2;
253
- onSelect == null ? void 0 : onSelect((_a2 = child.props.item) != null ? _a2 : items.length);
254
- }),
255
- onKeyDown: (e) => handleKeyboardInteractions(e, {
256
- handleDown: handleArrowDown,
257
- handleUp: handleArrowUp
187
+ return childrenProps.reduce(
188
+ ({ items, searchElement }, child) => {
189
+ switch (child.type) {
190
+ case MenuSearch:
191
+ return {
192
+ items,
193
+ searchElement: react.cloneElement(child, {
194
+ onKeyDown: (e) => handleKeyboardInteractions(e, {
195
+ handleDown: handleArrowDown,
196
+ handleUp: handleArrowUp
197
+ })
258
198
  })
259
- })),
260
- searchElement
261
- };
262
- case MenuDivider:
263
- return {
264
- items: items.concat(child),
265
- searchElement
266
- };
267
- default:
268
- return {
269
- items,
270
- searchElement
271
- };
272
- }
273
- }, {
274
- items: [],
275
- searchElement: null
276
- });
199
+ };
200
+ case MenuItem:
201
+ case MenuItemLink:
202
+ return {
203
+ items: items.concat(
204
+ child.props.disabled ? react.cloneElement(child, {
205
+ onClick: () => void 0,
206
+ onKeyDown: () => void 0,
207
+ tabIndex: -1,
208
+ disabled: true
209
+ }) : react.cloneElement(child, {
210
+ className: classix.cx(child.props.className, menuItemClassName),
211
+ item: child.props.item ?? items.length,
212
+ onClick: chainEventHandlers(child.props.onClick, () => {
213
+ onSelect == null ? void 0 : onSelect(child.props.item ?? items.length);
214
+ }),
215
+ onKeyDown: (e) => handleKeyboardInteractions(e, {
216
+ handleDown: handleArrowDown,
217
+ handleUp: handleArrowUp
218
+ })
219
+ })
220
+ ),
221
+ searchElement
222
+ };
223
+ case MenuDivider:
224
+ return { items: items.concat(child), searchElement };
225
+ default:
226
+ return { items, searchElement };
227
+ }
228
+ },
229
+ { items: [], searchElement: null }
230
+ );
277
231
  }, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);
278
232
  if (enableVirtualization) {
279
- return /* @__PURE__ */ jsxRuntime.jsx(MenuBase, {
280
- "data-test-id": testId,
281
- isVirtual: true,
282
- size,
283
- children: /* @__PURE__ */ jsxRuntime.jsx(ItemVirtualizer, {
233
+ return /* @__PURE__ */ jsxRuntime.jsx(MenuBase, { "data-test-id": testId, isVirtual: true, size, children: /* @__PURE__ */ jsxRuntime.jsx(
234
+ ItemVirtualizer,
235
+ {
284
236
  items: react.Children.toArray(reduceItems.items),
285
237
  searchElement: reduceItems.searchElement,
286
238
  overscan,
@@ -288,17 +240,13 @@ const Menu = (props) => {
288
240
  onSelect,
289
241
  itemHeight,
290
242
  focusManager
291
- })
292
- });
243
+ }
244
+ ) });
293
245
  }
294
- return /* @__PURE__ */ jsxRuntime.jsxs(MenuBase, {
295
- "data-test-id": testId,
296
- size,
297
- children: [reduceItems.searchElement, /* @__PURE__ */ jsxRuntime.jsx(MenuItemList, {
298
- role: "presentation",
299
- children: reduceItems.items
300
- })]
301
- });
246
+ return /* @__PURE__ */ jsxRuntime.jsxs(MenuBase, { "data-test-id": testId, size, children: [
247
+ reduceItems.searchElement,
248
+ /* @__PURE__ */ jsxRuntime.jsx(MenuItemList, { role: "presentation", children: reduceItems.items })
249
+ ] });
302
250
  };
303
251
  const ItemVirtualizer = (props) => {
304
252
  const {
@@ -328,61 +276,70 @@ const ItemVirtualizer = (props) => {
328
276
  rowVirtualizer.scrollToIndex(0);
329
277
  (_b = (_a = searchRef.current) == null ? void 0 : _a.focus) == null ? void 0 : _b.call(_a);
330
278
  }, [rowVirtualizer]);
331
- const focusMenuItem = react.useCallback((index) => {
332
- rowVirtualizer.scrollToIndex(index);
333
- setNextFocusValue(index);
334
- }, [rowVirtualizer]);
335
- const handleKeyboardFocusInteraction = react.useCallback((direction) => {
336
- if (focusedItemIndex.current === null || focusedItemIndex.current === void 0) {
337
- return;
338
- }
339
- const nextIndex = direction === "next" ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;
340
- const shouldWrap = direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0;
341
- if (shouldWrap) {
342
- if (hasSearch) {
343
- focusSearchBar();
344
- } else {
345
- focusMenuItem(direction === "next" ? 0 : lastVirtualItemIndex);
279
+ const focusMenuItem = react.useCallback(
280
+ (index) => {
281
+ rowVirtualizer.scrollToIndex(index);
282
+ setNextFocusValue(index);
283
+ },
284
+ [rowVirtualizer]
285
+ );
286
+ const handleKeyboardFocusInteraction = react.useCallback(
287
+ (direction) => {
288
+ if (focusedItemIndex.current === null || focusedItemIndex.current === void 0) {
289
+ return;
346
290
  }
347
- return;
348
- }
349
- switch (direction) {
350
- case "next":
351
- rowVirtualizer.scrollToIndex(nextIndex);
352
- focusManager.focusNext();
353
- break;
354
- case "previous":
355
- rowVirtualizer.scrollToIndex(nextIndex);
356
- focusManager.focusPrevious();
357
- break;
358
- }
359
- }, [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]);
360
- const getItemProps = react.useCallback((itemElem, index) => {
361
- const childProps = itemElem.props;
362
- switch (itemElem.type) {
363
- case MenuItem:
364
- case MenuItemLink:
365
- return {
366
- className: classix.cx(childProps.className, menuItemClassName),
367
- onKeyDown: childProps.disabled ? () => void 0 : (e) => handleKeyboardFocusKeydown(e, {
368
- handleFocusBackward: handleKeyboardFocusInteraction,
369
- handleFocusForward: handleKeyboardFocusInteraction
370
- }),
371
- onFocus: chainEventHandlers(childProps.onFocus, () => {
372
- focusedItemIndex.current = index;
373
- }),
374
- id: createItemId(index, menuId.current),
375
- onBlur: chainEventHandlers(childProps.onBlur, () => {
376
- focusedItemIndex.current = null;
377
- }),
378
- onClick: childProps.disabled ? () => void 0 : chainEventHandlers(childProps.onClick, () => {
379
- onSelect == null ? void 0 : onSelect(childProps.item);
380
- })
381
- };
382
- default:
383
- return {};
384
- }
385
- }, [handleKeyboardFocusInteraction, menuItemClassName, onSelect]);
291
+ const nextIndex = direction === "next" ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;
292
+ const shouldWrap = direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0;
293
+ if (shouldWrap) {
294
+ if (hasSearch) {
295
+ focusSearchBar();
296
+ } else {
297
+ focusMenuItem(direction === "next" ? 0 : lastVirtualItemIndex);
298
+ }
299
+ return;
300
+ }
301
+ switch (direction) {
302
+ case "next":
303
+ rowVirtualizer.scrollToIndex(nextIndex);
304
+ focusManager.focusNext();
305
+ break;
306
+ case "previous":
307
+ rowVirtualizer.scrollToIndex(nextIndex);
308
+ focusManager.focusPrevious();
309
+ break;
310
+ }
311
+ },
312
+ [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]
313
+ );
314
+ const getItemProps = react.useCallback(
315
+ (itemElem, index) => {
316
+ const childProps = itemElem.props;
317
+ switch (itemElem.type) {
318
+ case MenuItem:
319
+ case MenuItemLink:
320
+ return {
321
+ className: classix.cx(childProps.className, menuItemClassName),
322
+ onKeyDown: childProps.disabled ? () => void 0 : (e) => handleKeyboardFocusKeydown(e, {
323
+ handleFocusBackward: handleKeyboardFocusInteraction,
324
+ handleFocusForward: handleKeyboardFocusInteraction
325
+ }),
326
+ onFocus: chainEventHandlers(childProps.onFocus, () => {
327
+ focusedItemIndex.current = index;
328
+ }),
329
+ id: createItemId(index, menuId.current),
330
+ onBlur: chainEventHandlers(childProps.onBlur, () => {
331
+ focusedItemIndex.current = null;
332
+ }),
333
+ onClick: childProps.disabled ? () => void 0 : chainEventHandlers(childProps.onClick, () => {
334
+ onSelect == null ? void 0 : onSelect(childProps.item);
335
+ })
336
+ };
337
+ default:
338
+ return {};
339
+ }
340
+ },
341
+ [handleKeyboardFocusInteraction, menuItemClassName, onSelect]
342
+ );
386
343
  react.useEffect(() => {
387
344
  if (nextFocusValue !== null) {
388
345
  requestAnimationFrame(() => {
@@ -405,42 +362,52 @@ const ItemVirtualizer = (props) => {
405
362
  }
406
363
  }
407
364
  };
408
- const renderSearch = react.useMemo(() => searchElement ? react.cloneElement(searchElement, {
409
- onKeyDown: (e) => handleKeyboardFocusKeydown(e, {
410
- handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),
411
- handleFocusForward: () => focusMenuItem(0)
365
+ const renderSearch = react.useMemo(
366
+ () => searchElement ? react.cloneElement(searchElement, {
367
+ onKeyDown: (e) => handleKeyboardFocusKeydown(e, {
368
+ handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),
369
+ handleFocusForward: () => focusMenuItem(0)
370
+ }),
371
+ ref: searchRef
372
+ }) : null,
373
+ [searchElement, lastVirtualItemIndex, focusMenuItem]
374
+ );
375
+ const renderItems = react.useMemo(
376
+ () => rowVirtualizer.virtualItems.map((virtualRow) => {
377
+ if (!items) {
378
+ return null;
379
+ }
380
+ const elem = items[virtualRow.index];
381
+ return /* @__PURE__ */ jsxRuntime.jsx(
382
+ "div",
383
+ {
384
+ ref: elem.type !== MenuItem || elem.type !== MenuItemLink ? virtualRow.measureRef : void 0,
385
+ role: "presentation",
386
+ className: classix.cx("VirtualMenu-item"),
387
+ style: {
388
+ transform: `translateY(${virtualRow.start}px)`
389
+ },
390
+ children: react.cloneElement(elem, getItemProps(elem, virtualRow.index))
391
+ },
392
+ virtualRow.index
393
+ );
412
394
  }),
413
- ref: searchRef
414
- }) : null, [searchElement, lastVirtualItemIndex, focusMenuItem]);
415
- const renderItems = react.useMemo(() => rowVirtualizer.virtualItems.map((virtualRow) => {
416
- if (!items) {
417
- return null;
418
- }
419
- const elem = items[virtualRow.index];
420
- return /* @__PURE__ */ jsxRuntime.jsx("div", {
421
- ref: elem.type !== MenuItem || elem.type !== MenuItemLink ? virtualRow.measureRef : void 0,
422
- role: "presentation",
423
- className: classix.cx("VirtualMenu-item"),
424
- style: {
425
- transform: `translateY(${virtualRow.start}px)`
426
- },
427
- children: react.cloneElement(elem, getItemProps(elem, virtualRow.index))
428
- }, virtualRow.index);
429
- }), [rowVirtualizer.virtualItems, items, getItemProps]);
430
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
431
- children: [renderSearch, /* @__PURE__ */ jsxRuntime.jsx(MenuItemList, {
432
- ref: parentRef,
433
- role: "presentation",
434
- children: /* @__PURE__ */ jsxRuntime.jsx("div", {
395
+ [rowVirtualizer.virtualItems, items, getItemProps]
396
+ );
397
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
398
+ renderSearch,
399
+ /* @__PURE__ */ jsxRuntime.jsx(MenuItemList, { ref: parentRef, role: "presentation", children: /* @__PURE__ */ jsxRuntime.jsx(
400
+ "div",
401
+ {
435
402
  role: "presentation",
436
403
  className: "VirtualMenu-item-list",
437
404
  style: {
438
405
  height: `${rowVirtualizer.totalSize}px`
439
406
  },
440
407
  children: renderItems
441
- })
442
- })]
443
- });
408
+ }
409
+ ) })
410
+ ] });
444
411
  };
445
412
  exports.Menu = Menu;
446
413
  exports.MenuBase = MenuBase;