@launchpad-ui/menu 0.6.40 → 0.6.41

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.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const jsxRuntime = require("react/jsx-runtime");
3
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
5
4
  const classix = require("classix");
6
5
  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,12 +12,21 @@ 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, 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
- );
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
+ });
21
30
  MenuBase.displayName = "MenuBase";
22
31
  const MenuDivider = ({
23
32
  elementType = "div",
@@ -25,11 +34,18 @@ const MenuDivider = ({
25
34
  innerRef,
26
35
  "data-test-id": testId = "menu-divider"
27
36
  }) => {
28
- const { separatorProps } = separator.useSeparator({
37
+ const {
38
+ separatorProps
39
+ } = separator.useSeparator({
29
40
  orientation,
30
41
  elementType
31
42
  });
32
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ...separatorProps, "data-test-id": testId, ref: innerRef, className: "Menu-divider" });
43
+ return /* @__PURE__ */ jsxRuntime.jsx("div", {
44
+ ...separatorProps,
45
+ "data-test-id": testId,
46
+ ref: innerRef,
47
+ className: "Menu-divider"
48
+ });
33
49
  };
34
50
  const defaultElement = "button";
35
51
  const MenuItem = ({
@@ -55,40 +71,37 @@ const MenuItem = ({
55
71
  ...rest
56
72
  } = props;
57
73
  const Component = component || (asChild ? reactSlot.Slot : defaultElement);
58
- const renderedItem = /* @__PURE__ */ jsxRuntime.jsx(focus.FocusRing, { focusRingClass: "has-focus", children: /* @__PURE__ */ jsxRuntime.jsx(
59
- Component,
60
- {
74
+ const renderedItem = /* @__PURE__ */ jsxRuntime.jsx(focus.FocusRing, {
75
+ focusRingClass: "has-focus",
76
+ children: /* @__PURE__ */ jsxRuntime.jsx(Component, {
61
77
  ...rest,
62
78
  disabled,
63
79
  "aria-disabled": disabled ? disabled : void 0,
64
- className: classix.cx(
65
- "Menu-item",
66
- className,
67
- isHighlighted && "is-highlighted",
68
- nested && "Menu-item--nested",
69
- groupHeader && "Menu-item--header"
70
- ),
80
+ className: classix.cx("Menu-item", className, isHighlighted && "is-highlighted", nested && "Menu-item--nested", groupHeader && "Menu-item--header"),
71
81
  "data-test-id": testId,
72
82
  role,
73
83
  onKeyDown,
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
- ) });
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
+ });
80
94
  if (tooltip$1) {
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
- );
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
+ });
92
105
  }
93
106
  return renderedItem;
94
107
  };
@@ -108,15 +121,32 @@ const MenuItemLink = ({
108
121
  rel: newTab ? "noopener noreferrer" : void 0,
109
122
  target: newTab ? "_blank" : void 0
110
123
  };
111
- return /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { ...finalProps, children });
124
+ return /* @__PURE__ */ jsxRuntime.jsx(MenuItem, {
125
+ ...finalProps,
126
+ children
127
+ });
112
128
  };
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 }));
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
+ }));
114
139
  MenuItemList.displayName = "MenuItemList";
115
140
  const MenuSearch = react.forwardRef((props, ref) => {
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
- {
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, {
120
150
  ...finalProps,
121
151
  ref,
122
152
  className: "Menu-search-input",
@@ -126,8 +156,8 @@ const MenuSearch = react.forwardRef((props, ref) => {
126
156
  autoComplete: "off",
127
157
  placeholder,
128
158
  "aria-label": ariaLabel || "Search"
129
- }
130
- ) });
159
+ })
160
+ });
131
161
  });
132
162
  MenuSearch.displayName = "MenuSearch";
133
163
  const createItemId = (index, id) => `${id}-item-${index}`;
@@ -160,10 +190,14 @@ const Menu = (props) => {
160
190
  } = props;
161
191
  const focusManager = focus.useFocusManager();
162
192
  const handleArrowDown = react.useCallback(() => {
163
- focusManager.focusNext({ wrap: true });
193
+ focusManager.focusNext({
194
+ wrap: true
195
+ });
164
196
  }, [focusManager]);
165
197
  const handleArrowUp = react.useCallback(() => {
166
- focusManager.focusPrevious({ wrap: true });
198
+ focusManager.focusPrevious({
199
+ wrap: true
200
+ });
167
201
  }, [focusManager]);
168
202
  const reduceItems = react.useMemo(() => {
169
203
  const childrenProps = react.Children.toArray(children);
@@ -182,57 +216,71 @@ const Menu = (props) => {
182
216
  break;
183
217
  }
184
218
  });
185
- return { items: elements, searchElement: searchElem };
219
+ return {
220
+ items: elements,
221
+ searchElement: searchElem
222
+ };
186
223
  }
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
- })
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
198
237
  })
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
- );
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
258
+ })
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
+ });
231
277
  }, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);
232
278
  if (enableVirtualization) {
233
- return /* @__PURE__ */ jsxRuntime.jsx(MenuBase, { "data-test-id": testId, isVirtual: true, size, children: /* @__PURE__ */ jsxRuntime.jsx(
234
- ItemVirtualizer,
235
- {
279
+ return /* @__PURE__ */ jsxRuntime.jsx(MenuBase, {
280
+ "data-test-id": testId,
281
+ isVirtual: true,
282
+ size,
283
+ children: /* @__PURE__ */ jsxRuntime.jsx(ItemVirtualizer, {
236
284
  items: react.Children.toArray(reduceItems.items),
237
285
  searchElement: reduceItems.searchElement,
238
286
  overscan,
@@ -240,13 +288,17 @@ const Menu = (props) => {
240
288
  onSelect,
241
289
  itemHeight,
242
290
  focusManager
243
- }
244
- ) });
291
+ })
292
+ });
245
293
  }
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
- ] });
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
+ });
250
302
  };
251
303
  const ItemVirtualizer = (props) => {
252
304
  const {
@@ -276,70 +328,61 @@ const ItemVirtualizer = (props) => {
276
328
  rowVirtualizer.scrollToIndex(0);
277
329
  (_b = (_a = searchRef.current) == null ? void 0 : _a.focus) == null ? void 0 : _b.call(_a);
278
330
  }, [rowVirtualizer]);
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;
290
- }
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 {};
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);
339
346
  }
340
- },
341
- [handleKeyboardFocusInteraction, menuItemClassName, onSelect]
342
- );
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]);
343
386
  react.useEffect(() => {
344
387
  if (nextFocusValue !== null) {
345
388
  requestAnimationFrame(() => {
@@ -362,52 +405,42 @@ const ItemVirtualizer = (props) => {
362
405
  }
363
406
  }
364
407
  };
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
- );
408
+ const renderSearch = react.useMemo(() => searchElement ? react.cloneElement(searchElement, {
409
+ onKeyDown: (e) => handleKeyboardFocusKeydown(e, {
410
+ handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),
411
+ handleFocusForward: () => focusMenuItem(0)
394
412
  }),
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
- {
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", {
402
435
  role: "presentation",
403
436
  className: "VirtualMenu-item-list",
404
437
  style: {
405
438
  height: `${rowVirtualizer.totalSize}px`
406
439
  },
407
440
  children: renderItems
408
- }
409
- ) })
410
- ] });
441
+ })
442
+ })]
443
+ });
411
444
  };
412
445
  exports.Menu = Menu;
413
446
  exports.MenuBase = MenuBase;