@launchpad-ui/menu 0.12.9 → 0.12.11

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