@launchpad-ui/menu 0.16.14 → 0.16.15

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 CHANGED
@@ -1,5 +1,5 @@
1
- import type { FocusManager } from '@react-aria/focus';
2
1
  import type { ReactElement, ReactNode } from 'react';
2
+ import { type FocusManager } from 'react-aria/FocusScope';
3
3
  type ControlledMenuProps<T> = {
4
4
  children: ReactNode;
5
5
  onSelect?: (item: T) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA8BpE,KAAK,mBAAmB,CAAC,CAAC,IAAI;IAC7B,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAEnE;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,CAAC,CAAC,CAAC,4CAyH3D,CAAC;AAEF,KAAK,oBAAoB,CAAC,CAAC,IAAI,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG;IACzE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,oBAAoB,CAAC,CAAC,CAAC,4CAiNjF,CAAC;AAEF,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACjC,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAcpE,OAAO,EAAE,KAAK,YAAY,EAAmB,MAAM,uBAAuB,CAAC;AAgB3E,KAAK,mBAAmB,CAAC,CAAC,IAAI;IAC7B,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAEnE;;;;GAIG;AACH,QAAA,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,SAAS,CAAC,CAAC,CAAC,4CAyH3D,CAAC;AAEF,KAAK,oBAAoB,CAAC,CAAC,IAAI,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG;IACzE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,oBAAoB,CAAC,CAAC,CAAC,4CAiNjF,CAAC;AAEF,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACjC,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC"}
@@ -1,5 +1,5 @@
1
- import type { SeparatorProps } from '@react-aria/separator';
2
1
  import type { RefObject } from 'react';
2
+ import { type SeparatorProps } from 'react-aria/useSeparator';
3
3
  type MenuDividerProps = SeparatorProps & {
4
4
  innerRef?: RefObject<HTMLDivElement>;
5
5
  'data-test-id'?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"MenuDivider.d.ts","sourceRoot":"","sources":["../src/MenuDivider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,KAAK,gBAAgB,GAAG,cAAc,GAAG;IACxC,QAAQ,CAAC,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,WAAW,GAAI,iEAKlB,gBAAgB,4CAclB,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"MenuDivider.d.ts","sourceRoot":"","sources":["../src/MenuDivider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,yBAAyB,CAAC;AAI5E,KAAK,gBAAgB,GAAG,cAAc,GAAG;IACxC,QAAQ,CAAC,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,WAAW,GAAI,iEAKlB,gBAAgB,4CAclB,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
package/dist/index.es.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import './style.css';
2
- import { FocusRing, useFocusManager } from "@react-aria/focus";
3
2
  import { cx } from "classix";
4
3
  import { Children, cloneElement, forwardRef, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
4
+ import { useFocusManager } from "react-aria/FocusScope";
5
5
  import { useVirtual } from "react-virtual";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
- import { useSeparator } from "@react-aria/separator";
7
+ import { useSeparator } from "react-aria/useSeparator";
8
8
  import { Tooltip } from "@launchpad-ui/tooltip";
9
9
  import { Slot } from "@radix-ui/react-slot";
10
+ import { FocusRing } from "react-aria/FocusRing";
10
11
  import { TextField } from "@launchpad-ui/form";
11
12
  const Menu$1 = "C73R2W_Menu";
12
13
  var Menu_module_default = {
@@ -29,7 +30,7 @@ var Menu_module_default = {
29
30
  "VirtualMenu-item": "C73R2W_VirtualMenu-item",
30
31
  "VirtualMenu-item-list": "C73R2W_VirtualMenu-item-list"
31
32
  };
32
- const MenuBase = /* @__PURE__ */ forwardRef(({ children, size, isVirtual,...props }, ref) => {
33
+ var MenuBase = /* @__PURE__ */ forwardRef(({ children, size, isVirtual, ...props }, ref) => {
33
34
  const classes = cx(Menu_module_default.Menu, isVirtual && Menu_module_default["Menu--isVirtual"], size && Menu_module_default[`MenuSize--${size}`]);
34
35
  return /* @__PURE__ */ jsx("div", {
35
36
  ...props,
@@ -40,7 +41,7 @@ const MenuBase = /* @__PURE__ */ forwardRef(({ children, size, isVirtual,...prop
40
41
  });
41
42
  });
42
43
  MenuBase.displayName = "MenuBase";
43
- const MenuDivider = ({ elementType = "div", orientation, innerRef, "data-test-id": testId = "menu-divider" }) => {
44
+ var MenuDivider = ({ elementType = "div", orientation, innerRef, "data-test-id": testId = "menu-divider" }) => {
44
45
  const { separatorProps } = useSeparator({
45
46
  orientation,
46
47
  elementType
@@ -52,9 +53,9 @@ const MenuDivider = ({ elementType = "div", orientation, innerRef, "data-test-id
52
53
  className: Menu_module_default["Menu-divider"]
53
54
  });
54
55
  };
55
- const defaultElement = "button";
56
- const MenuItem = ({ ...props }) => {
57
- const { component, children, isHighlighted, icon, nested, groupHeader, item, disabled, className, tooltip, role = "menuitem", tooltipPlacement, onKeyDown, tooltipOptions, asChild, "data-test-id": testId = "menu-item",...rest } = props;
56
+ var defaultElement = "button";
57
+ var MenuItem = ({ ...props }) => {
58
+ const { component, children, isHighlighted, icon, nested, groupHeader, item, disabled, className, tooltip, role = "menuitem", tooltipPlacement, onKeyDown, tooltipOptions, asChild, "data-test-id": testId = "menu-item", ...rest } = props;
58
59
  const Component = component || (asChild ? Slot : defaultElement);
59
60
  const renderIcon = icon && /* @__PURE__ */ cloneElement(icon, { size: "small" });
60
61
  const renderedItem = /* @__PURE__ */ jsx(FocusRing, {
@@ -83,7 +84,7 @@ const MenuItem = ({ ...props }) => {
83
84
  });
84
85
  return renderedItem;
85
86
  };
86
- const MenuItemList = /* @__PURE__ */ forwardRef(({ children,...rest }, ref) => /* @__PURE__ */ jsx("div", {
87
+ var MenuItemList = /* @__PURE__ */ forwardRef(({ children, ...rest }, ref) => /* @__PURE__ */ jsx("div", {
87
88
  ...rest,
88
89
  ref,
89
90
  "data-test-id": "menu-item-list",
@@ -91,8 +92,8 @@ const MenuItemList = /* @__PURE__ */ forwardRef(({ children,...rest }, ref) => /
91
92
  children
92
93
  }));
93
94
  MenuItemList.displayName = "MenuItemList";
94
- const MenuSearch = /* @__PURE__ */ forwardRef((props, ref) => {
95
- const { ariaLabel, placeholder, id, "data-test-id": testId = "menu-search",...finalProps } = props;
95
+ var MenuSearch = /* @__PURE__ */ forwardRef((props, ref) => {
96
+ const { ariaLabel, placeholder, id, "data-test-id": testId = "menu-search", ...finalProps } = props;
96
97
  return /* @__PURE__ */ jsx("div", {
97
98
  className: Menu_module_default["Menu-search"],
98
99
  children: /* @__PURE__ */ jsx(TextField, {
@@ -110,9 +111,9 @@ const MenuSearch = /* @__PURE__ */ forwardRef((props, ref) => {
110
111
  });
111
112
  });
112
113
  MenuSearch.displayName = "MenuSearch";
113
- const createItemId = (index, id) => `${id}-item-${index}`;
114
- const getNodeForIndex = (index, menuId) => index === null ? index : document.getElementById(createItemId(index, menuId));
115
- const handleKeyboardInteractions = (event, keyHandlers) => {
114
+ var createItemId = (index, id) => `${id}-item-${index}`;
115
+ var getNodeForIndex = (index, menuId) => index === null ? index : document.getElementById(createItemId(index, menuId));
116
+ var handleKeyboardInteractions = (event, keyHandlers) => {
116
117
  const ops = {
117
118
  ArrowUp: keyHandlers.handleUp,
118
119
  ArrowDown: keyHandlers.handleDown,
@@ -123,15 +124,10 @@ const handleKeyboardInteractions = (event, keyHandlers) => {
123
124
  ops[event.key]?.call(globalThis, event);
124
125
  }
125
126
  };
126
- const chainEventHandlers = (...handlers) => (event) => {
127
+ var chainEventHandlers = (...handlers) => (event) => {
127
128
  for (const h of handlers) typeof h === "function" && h(event);
128
129
  };
129
- /**
130
- * @deprecated use `Menu` or `ListBox` from `@launchpad-ui/components` instead
131
- *
132
- * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs
133
- */
134
- const Menu = (props) => {
130
+ var Menu = (props) => {
135
131
  const { children, menuItemClassName, onSelect, enableVirtualization, itemHeight, size, overscan = 1, "data-test-id": testId = "menu" } = props;
136
132
  const focusManager = useFocusManager();
137
133
  const handleArrowDown = useCallback(() => {
@@ -233,7 +229,7 @@ const Menu = (props) => {
233
229
  })]
234
230
  });
235
231
  };
236
- const ItemVirtualizer = (props) => {
232
+ var ItemVirtualizer = (props) => {
237
233
  const { overscan, searchElement, itemHeight = 31.5, menuItemClassName, items, focusManager, onSelect } = props;
238
234
  const menuId = useRef(`menu-ctrl-${useId()}`);
239
235
  const focusedItemIndex = useRef(null);
@@ -252,10 +248,6 @@ const ItemVirtualizer = (props) => {
252
248
  rowVirtualizer.scrollToIndex(0);
253
249
  searchRef.current?.focus?.();
254
250
  }, [rowVirtualizer]);
255
- /**
256
- * Scrolls to the menu item with the index provided and
257
- * then manually focuses it using a side effect in useEffect
258
- */
259
251
  const focusMenuItem = useCallback((index) => {
260
252
  rowVirtualizer.scrollToIndex(index);
261
253
  setNextFocusValue(index);
@@ -263,8 +255,7 @@ const ItemVirtualizer = (props) => {
263
255
  const handleKeyboardFocusInteraction = useCallback((direction) => {
264
256
  if (focusedItemIndex.current === null || focusedItemIndex.current === void 0) return;
265
257
  const nextIndex = direction === "next" ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;
266
- const shouldWrap = direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0;
267
- if (shouldWrap) {
258
+ if (direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0) {
268
259
  if (hasSearch) focusSearchBar();
269
260
  else focusMenuItem(direction === "next" ? 0 : lastVirtualItemIndex);
270
261
  return;
@@ -318,23 +309,17 @@ const ItemVirtualizer = (props) => {
318
309
  useEffect(() => {
319
310
  if (nextFocusValue !== null) {
320
311
  requestAnimationFrame(() => {
321
- const element = getNodeForIndex(nextFocusValue, menuId.current);
322
- element?.focus();
312
+ getNodeForIndex(nextFocusValue, menuId.current)?.focus();
323
313
  });
324
314
  setNextFocusValue(null);
325
315
  }
326
316
  }, [nextFocusValue]);
327
- /**
328
- * Calls handleFocusForward when the user is attempting to focus forward using
329
- * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.
330
- */
331
317
  const handleKeyboardFocusKeydown = (e, callbacks) => {
332
- const keyOps = [
318
+ if ([
333
319
  "Tab",
334
320
  "ArrowUp",
335
321
  "ArrowDown"
336
- ];
337
- if (keyOps.includes(e.key)) {
322
+ ].includes(e.key)) {
338
323
  e.preventDefault();
339
324
  e.stopPropagation();
340
325
  if (e.key === "Tab" && e.shiftKey || e.key === "ArrowUp") callbacks.handleFocusBackward?.("previous");
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","names":["Component: ElementType","index: number","id: string","index: number | null","menuId: string","event: KeyboardEvent","keyHandlers: Partial<\n\t\tRecord<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n\t>","event: SyntheticEvent","props: MenuProps<T>","elements: ReactElement[]","child: ReactElement<any>","e: KeyboardEvent","props: ItemVirtualizerProps<T>","index: number","direction: 'next' | 'previous'","itemElem: ReactElement","callbacks: Record<\n\t\t\t'handleFocusForward' | 'handleFocusBackward',\n\t\t\t(direction: 'next' | 'previous') => void\n\t\t>"],"sources":["../src/styles/Menu.module.css","../src/MenuBase.tsx","../src/MenuDivider.tsx","../src/MenuItem.tsx","../src/MenuItemList.tsx","../src/MenuSearch.tsx","../src/utils.ts","../src/Menu.tsx"],"sourcesContent":[".Menu-item {\n\tbackground-color: transparent;\n\tborder-radius: var(--lp-border-radius-regular);\n\tborder-width: var(--lp-border-width-100);\n\tcolor: var(--lp-color-text-ui-primary-base);\n\tcursor: pointer;\n\tdisplay: block;\n\tfont: var(--lp-text-label-1-medium);\n\toutline: none;\n\toverflow: hidden;\n\tpadding-inline: var(--lp-spacing-300);\n\tpadding-block: var(--lp-spacing-200);\n\tposition: relative;\n\ttext-align: left;\n\ttext-decoration: none;\n\ttext-overflow: ellipsis;\n\tuser-select: none;\n\twhite-space: nowrap;\n\twidth: 100%;\n}\n\n.Menu-item-list {\n\tmax-height: 55vh;\n\tmin-width: 7.5rem;\n\toverflow: auto;\n\tpadding: var(--lp-spacing-200);\n}\n\n.Menu .Menu-item:not([disabled]):not([aria-disabled]):not(.Menu-item--header) {\n\t&:active {\n\t\ttext-decoration: none;\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-active);\n\t}\n\n\t&:hover:not(:active):not(.has-focus) {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t}\n\n\t&.has-focus {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t\tbox-shadow: inset 0 0 0 2px var(--lp-color-shadow-interactive-focus);\n\t}\n}\n\n.Menu {\n\tbackground: var(--lp-color-bg-overlay-secondary);\n\tborder-radius: var(--lp-border-radius-medium);\n\tfont-family: var(--lp-font-family-base);\n\n\t&:focus {\n\t\toutline: none;\n\t}\n\n\t/* Override our link styles for link component */\n\t& a.Menu-item {\n\t\t&:focus:not(:hover):not(.has-focus) {\n\t\t\ttext-decoration: none;\n\t\t\tbox-shadow: none;\n\t\t}\n\n\t\t/* Ensures that links that are disabled don't show active styles */\n\t\t&:active[disabled],\n\t\t&:active[aria-disabled] {\n\t\t\ttext-decoration: none;\n\t\t\tcolor: var(--lp-color-text-interactive-disabled);\n\t\t}\n\t}\n}\n\n.Menu-item--nested {\n\tpadding-left: 2.5rem;\n}\n\n.Menu-item--header {\n\tfont: var(--lp-text-small-1-regular);\n\tcolor: var(--lp-color-text-ui-tertiary);\n}\n\n.Menu-item-icon {\n\tmargin-right: var(--lp-spacing-300);\n}\n\n.Menu-item :global(.Gravatar) {\n\tmargin-right: 0.3125rem;\n}\n\n.Menu-item.is-highlighted {\n\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n}\n\n.Menu-item[aria-disabled],\n.Menu-item[disabled] {\n\tcolor: var(--lp-color-text-interactive-disabled);\n\tcursor: not-allowed;\n}\n\n.Menu-divider {\n\tborder-top: 1px solid var(--lp-color-border-ui-secondary);\n\tmargin: var(--lp-spacing-200) 0;\n}\n\n.Menu-search {\n\tborder-bottom: 1px solid var(--lp-color-border-ui-secondary);\n\tpadding: var(--lp-spacing-300);\n}\n\n[class*='_Popover-content'] .Menu-search {\n\twidth: 100%;\n\n\t/* Removing anything that could give it some height */\n\t& .Menu-search-hidden-placeholder {\n\t\tpadding-top: 0;\n\t\tpadding-bottom: 0;\n\t\theight: 0;\n\t\tborder: none;\n\t\tvisibility: hidden;\n\t}\n}\n\n.Menu--isVirtual {\n\tdisplay: flex;\n\talign-items: stretch;\n\tflex-direction: column;\n}\n\n.MenuSize--xl {\n\twidth: 20rem;\n}\n\n.MenuSize--lg {\n\twidth: 15rem;\n}\n\n.MenuSize--md {\n\twidth: 10rem;\n}\n\n.MenuSize--sm {\n\twidth: 7.5rem;\n}\n\n.VirtualMenu-item-list {\n\twidth: 100%;\n\tposition: relative;\n}\n\n.VirtualMenu-item {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n}\n","import type { ComponentPropsWithRef } from 'react';\nimport type { MenuProps } from './Menu';\n\nimport { cx } from 'classix';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuBaseProps = ComponentPropsWithRef<'div'> & {\n\tisVirtual?: boolean;\n\tsize?: MenuProps<string>['size'];\n};\n\nconst MenuBase = forwardRef<HTMLDivElement, MenuBaseProps>(\n\t({ children, size, isVirtual, ...props }, ref) => {\n\t\tconst classes = cx(\n\t\t\tstyles.Menu,\n\t\t\tisVirtual && styles['Menu--isVirtual'],\n\t\t\tsize && styles[`MenuSize--${size}`],\n\t\t);\n\n\t\treturn (\n\t\t\t<div {...props} role=\"menu\" className={classes} ref={ref}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t},\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n","import type { SeparatorProps } from '@react-aria/separator';\nimport type { RefObject } from 'react';\n\nimport { useSeparator } from '@react-aria/separator';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuDividerProps = SeparatorProps & {\n\tinnerRef?: RefObject<HTMLDivElement>;\n\t'data-test-id'?: string;\n};\n\nconst MenuDivider = ({\n\telementType = 'div',\n\torientation,\n\tinnerRef,\n\t'data-test-id': testId = 'menu-divider',\n}: MenuDividerProps) => {\n\tconst { separatorProps } = useSeparator({\n\t\torientation,\n\t\telementType,\n\t});\n\n\treturn (\n\t\t<div\n\t\t\t{...separatorProps}\n\t\t\tdata-test-id={testId}\n\t\t\tref={innerRef}\n\t\t\tclassName={styles['Menu-divider']}\n\t\t/>\n\t);\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n","import type { IconProps } from '@launchpad-ui/icons';\nimport type { PopoverPlacement } from '@launchpad-ui/popover';\nimport type { ComponentPropsWithRef, ElementType, JSX, PropsWithRef, ReactElement } from 'react';\n\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { Slot } from '@radix-ui/react-slot';\nimport { FocusRing } from '@react-aria/focus';\nimport { cx } from 'classix';\nimport { cloneElement } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\n// Merge two types and get rid of overlapping definitions\ntype Merge<T, U> = Omit<T, keyof U> & U;\n\ntype PropsWithComponent<P, T extends ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends ElementType> = Merge<\n\tT extends keyof JSX.IntrinsicElements\n\t\t? PropsWithRef<JSX.IntrinsicElements[T]>\n\t\t: ComponentPropsWithRef<T>,\n\tPropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n\tisHighlighted?: boolean;\n\ticon?: ReactElement<IconProps>;\n\tdisabled?: boolean;\n\tnested?: boolean;\n\tgroupHeader?: boolean;\n\ttooltip?: string | ReactElement;\n\ttooltipOptions?: ComponentPropsWithRef<typeof Tooltip>;\n\ttooltipPlacement?: PopoverPlacement;\n\tasChild?: boolean;\n\t'data-test-id'?: string;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<P, T extends ElementType = typeof defaultElement> = PolymorphicPropsWithRef<\n\t| (MenuItemOwnProps & {\n\t\t\titem: P; // Infer the type if it is included\n\t })\n\t| (MenuItemOwnProps & {\n\t\t\titem?: undefined;\n\t }),\n\tT\n>;\n\nconst MenuItem = <P, T extends ElementType = typeof defaultElement>({\n\t...props\n}: MenuItemProps<P, T>) => {\n\tconst {\n\t\t// TODO: remove component prop once we migrate over to asChild format\n\t\tcomponent,\n\t\tchildren,\n\t\tisHighlighted,\n\t\ticon,\n\t\tnested,\n\t\tgroupHeader,\n\t\t// biome-ignore lint/correctness/noUnusedVariables: ignore\n\t\titem,\n\t\tdisabled,\n\t\tclassName,\n\t\ttooltip,\n\t\trole = 'menuitem',\n\t\ttooltipPlacement,\n\t\tonKeyDown,\n\t\ttooltipOptions,\n\t\tasChild,\n\t\t'data-test-id': testId = 'menu-item',\n\t\t...rest\n\t} = props;\n\n\tconst Component: ElementType = component || (asChild ? Slot : defaultElement);\n\n\tconst renderIcon = icon && cloneElement(icon, { size: 'small' });\n\n\tconst renderedItem = (\n\t\t<FocusRing focusRingClass={styles['has-focus']}>\n\t\t\t<Component\n\t\t\t\t{...rest}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-disabled={disabled ? disabled : undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\tstyles['Menu-item'],\n\t\t\t\t\tclassName,\n\t\t\t\t\tisHighlighted && styles['is-highlighted'],\n\t\t\t\t\tnested && styles['Menu-item--nested'],\n\t\t\t\t\tgroupHeader && styles['Menu-item--header'],\n\t\t\t\t)}\n\t\t\t\tdata-test-id={testId}\n\t\t\t\trole={role}\n\t\t\t\tonKeyDown={onKeyDown}\n\t\t\t>\n\t\t\t\t{asChild ? (\n\t\t\t\t\tchildren\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{icon && <span className={styles['Menu-item-icon']}>{renderIcon}</span>}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Component>\n\t\t</FocusRing>\n\t);\n\n\tif (tooltip) {\n\t\treturn (\n\t\t\t<Tooltip\n\t\t\t\tcontent={tooltip}\n\t\t\t\trootElementStyle={{ display: 'block' }}\n\t\t\t\tallowBoundaryElementOverflow\n\t\t\t\tplacement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n\t\t\t\t{...(tooltipOptions || {})}\n\t\t\t>\n\t\t\t\t{renderedItem}\n\t\t\t</Tooltip>\n\t\t);\n\t}\n\n\treturn renderedItem;\n};\n\nexport { MenuItem };\nexport type { MenuItemProps };\n","import type { ComponentPropsWithRef } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuItemListProps = Omit<ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n\t<div {...rest} ref={ref} data-test-id=\"menu-item-list\" className={styles['Menu-item-list']}>\n\t\t{children}\n\t</div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n","import type { ChangeEvent } from 'react';\n\nimport { TextField } from '@launchpad-ui/form';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuSearchProps = {\n\tariaLabel?: string;\n\tvalue?: string;\n\tid?: string;\n\tplaceholder?: string;\n\tonChange?(event: ChangeEvent<HTMLInputElement>): void;\n\t'data-test-id'?: string;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n\tconst {\n\t\tariaLabel,\n\t\tplaceholder,\n\t\tid,\n\t\t'data-test-id': testId = 'menu-search',\n\t\t...finalProps\n\t} = props;\n\n\treturn (\n\t\t<div className={styles['Menu-search']}>\n\t\t\t<TextField\n\t\t\t\t{...finalProps}\n\t\t\t\tref={ref}\n\t\t\t\tclassName={styles['Menu-search-input']}\n\t\t\t\ttiny\n\t\t\t\tid={id}\n\t\t\t\ttype=\"search\"\n\t\t\t\tdata-test-id={testId}\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\taria-label={ariaLabel || 'Search'}\n\t\t\t/>\n\t\t</div>\n\t);\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n","import type { EventHandler, KeyboardEvent, SyntheticEvent } from 'react';\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n\tindex === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst handleKeyboardInteractions = (\n\tevent: KeyboardEvent,\n\tkeyHandlers: Partial<\n\t\tRecord<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n\t>,\n) => {\n\tconst ops = {\n\t\tArrowUp: keyHandlers.handleUp,\n\t\tArrowDown: keyHandlers.handleDown,\n\t\tEnter: keyHandlers.handleEnter,\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: ignore\n\t} as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n\tif (ops[event.key]) {\n\t\tevent.preventDefault();\n\t\tops[event.key]?.call(globalThis, event);\n\t}\n};\n\nconst chainEventHandlers =\n\t(...handlers: (EventHandler<SyntheticEvent> | undefined)[]) =>\n\t(event: SyntheticEvent) => {\n\t\tfor (const h of handlers) {\n\t\t\ttypeof h === 'function' && h(event);\n\t\t}\n\t};\n\nexport { createItemId, getNodeForIndex, handleKeyboardInteractions, chainEventHandlers };\n","import type { FocusManager } from '@react-aria/focus';\nimport type { KeyboardEvent, ReactElement, ReactNode } from 'react';\nimport type { MenuItemProps } from './MenuItem';\n\nimport { useFocusManager } from '@react-aria/focus';\nimport { cx } from 'classix';\nimport {\n\tChildren,\n\tcloneElement,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { useVirtual } from 'react-virtual';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport styles from './styles/Menu.module.css';\nimport {\n\tchainEventHandlers,\n\tcreateItemId,\n\tgetNodeForIndex,\n\thandleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n\tchildren: ReactNode;\n\tonSelect?: (item: T) => void;\n\t/**\n\t * Menus items are rendered using react-virtual for\n\t * additional rendering performance.\n\t */\n\tenableVirtualization?: boolean;\n\t/**\n\t * Class name to be applied to all MenuItem components\n\t * in the menu.\n\t */\n\tmenuItemClassName?: string;\n\t/**\n\t * Sets the width of the menu. This is especially useful when using virtual items\n\t * since the width cannot be automatically set by the widest element.\n\t */\n\tsize?: 'sm' | 'md' | 'lg' | 'xl';\n\t/**\n\t * Sets the number out of elements rendered outside of the view window\n\t * when using virtualization\n\t */\n\toverscan?: number;\n\t/**\n\t * Sets the height for each menu item when using virtualization.\n\t *\n\t */\n\titemHeight?: number;\n\t'data-test-id'?: string;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\n/**\n * @deprecated use `Menu` or `ListBox` from `@launchpad-ui/components` instead\n *\n * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs\n */\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n\tconst {\n\t\tchildren,\n\t\tmenuItemClassName,\n\t\tonSelect,\n\t\tenableVirtualization,\n\t\titemHeight,\n\t\tsize,\n\t\toverscan = 1,\n\t\t'data-test-id': testId = 'menu',\n\t} = props;\n\n\tconst focusManager = useFocusManager();\n\n\tconst handleArrowDown = useCallback(() => {\n\t\tfocusManager?.focusNext({ wrap: true });\n\t}, [focusManager]);\n\n\tconst handleArrowUp = useCallback(() => {\n\t\tfocusManager?.focusPrevious({ wrap: true });\n\t}, [focusManager]);\n\n\tconst reduceItems = useMemo(() => {\n\t\tconst childrenProps = Children.toArray(children);\n\t\tif (enableVirtualization) {\n\t\t\t// the virtualized menu has its own handlers and props\n\t\t\tlet searchElem = null;\n\t\t\tlet elements: ReactElement[] = [];\n\t\t\tfor (const child of childrenProps as ReactElement[]) {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\tsearchElem = child;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\telements = elements.concat(child);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { items: elements, searchElement: searchElem };\n\t\t}\n\n\t\treturn (childrenProps as ReactElement[]).reduce(\n\t\t\t(\n\t\t\t\t{ items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\tchild: ReactElement<any>,\n\t\t\t) => {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems,\n\t\t\t\t\t\t\tsearchElement: cloneElement(child, {\n\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems: items.concat(\n\t\t\t\t\t\t\t\tchild.props.disabled\n\t\t\t\t\t\t\t\t\t? cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\tonClick: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\t\t\t\t\t\t\tdisabled: true,\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t: cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\titem: child.props.item ?? items.length,\n\t\t\t\t\t\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\t\t\t\t\t\tonClick: chainEventHandlers(child.props.onClick, () => {\n\t\t\t\t\t\t\t\t\t\t\t\tonSelect?.(child.props.item ?? items.length);\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tsearchElement,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\treturn { items: items.concat(child), searchElement };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn { items, searchElement };\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ items: [], searchElement: null },\n\t\t);\n\t}, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n\tif (enableVirtualization) {\n\t\treturn (\n\t\t\t<MenuBase data-test-id={testId} isVirtual size={size}>\n\t\t\t\t<ItemVirtualizer<T>\n\t\t\t\t\titems={Children.toArray(reduceItems.items) as ReactElement[]}\n\t\t\t\t\tsearchElement={reduceItems.searchElement}\n\t\t\t\t\toverscan={overscan}\n\t\t\t\t\tmenuItemClassName={menuItemClassName}\n\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\titemHeight={itemHeight}\n\t\t\t\t\tfocusManager={focusManager}\n\t\t\t\t/>\n\t\t\t</MenuBase>\n\t\t);\n\t}\n\n\treturn (\n\t\t<MenuBase data-test-id={testId} size={size}>\n\t\t\t{reduceItems.searchElement}\n\t\t\t<MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n\t\t</MenuBase>\n\t);\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n\titems: ReactElement[] | null;\n\tsearchElement?: ReactElement | null;\n\tfocusManager?: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n\tconst {\n\t\toverscan,\n\t\tsearchElement,\n\t\titemHeight = 31.5,\n\t\tmenuItemClassName,\n\t\titems,\n\t\tfocusManager,\n\t\tonSelect,\n\t} = props;\n\n\tconst menuId = useRef(`menu-ctrl-${useId()}`);\n\n\tconst focusedItemIndex = useRef<number | null>(null);\n\tconst parentRef = useRef<HTMLDivElement | null>(null);\n\tconst searchRef = useRef<HTMLInputElement | null>(null);\n\n\tconst [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n\tconst hasSearch = !!searchElement;\n\n\tconst lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n\tconst rowVirtualizer = useVirtual({\n\t\tsize: items !== null ? items.length : 0,\n\t\tparentRef,\n\t\testimateSize: useCallback(() => itemHeight, [itemHeight]),\n\t\toverscan,\n\t});\n\n\tconst focusSearchBar = useCallback(() => {\n\t\trowVirtualizer.scrollToIndex(0);\n\t\tsearchRef.current?.focus?.();\n\t}, [rowVirtualizer]);\n\n\t/**\n\t * Scrolls to the menu item with the index provided and\n\t * then manually focuses it using a side effect in useEffect\n\t */\n\tconst focusMenuItem = useCallback(\n\t\t(index: number) => {\n\t\t\trowVirtualizer.scrollToIndex(index);\n\t\t\tsetNextFocusValue(index);\n\t\t},\n\t\t[rowVirtualizer],\n\t);\n\n\tconst handleKeyboardFocusInteraction = useCallback(\n\t\t(direction: 'next' | 'previous') => {\n\t\t\tif (focusedItemIndex.current === null || focusedItemIndex.current === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextIndex =\n\t\t\t\tdirection === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n\t\t\tconst shouldWrap =\n\t\t\t\t(direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n\t\t\t\t(direction === 'previous' && focusedItemIndex.current === 0);\n\t\t\tif (shouldWrap) {\n\t\t\t\t// we are at the end of the list so we will\n\t\t\t\t// scroll back to the beginning of the list\n\t\t\t\tif (hasSearch) {\n\t\t\t\t\tfocusSearchBar();\n\t\t\t\t} else {\n\t\t\t\t\t// if at end, wrap to beginning, else focus last item\n\t\t\t\t\tfocusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tswitch (direction) {\n\t\t\t\tcase 'next':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusNext();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'previous':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusPrevious();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t[focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer],\n\t);\n\n\tconst getItemProps = useCallback(\n\t\t(itemElem: ReactElement, index: number) => {\n\t\t\tconst childProps = itemElem.props as MenuItemProps<T>;\n\t\t\tswitch (itemElem.type) {\n\t\t\t\tcase MenuItem:\n\t\t\t\t\treturn {\n\t\t\t\t\t\tclassName: cx(childProps.className, menuItemClassName),\n\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\tonKeyDown: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\t\t\thandleFocusBackward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t\thandleFocusForward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tonFocus: chainEventHandlers(childProps.onFocus, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = index;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tid: createItemId(index, menuId.current),\n\t\t\t\t\t\tonBlur: chainEventHandlers(childProps.onBlur, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = null;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tonClick: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: chainEventHandlers(childProps.onClick, () => {\n\t\t\t\t\t\t\t\t\tonSelect?.(childProps.item as T);\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t} as MenuItemProps<T>;\n\t\t\t\tdefault:\n\t\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\t[handleKeyboardFocusInteraction, menuItemClassName, onSelect],\n\t);\n\n\tuseEffect(() => {\n\t\tif (nextFocusValue !== null) {\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tconst element = getNodeForIndex(nextFocusValue, menuId.current);\n\t\t\t\telement?.focus();\n\t\t\t});\n\t\t\tsetNextFocusValue(null);\n\t\t}\n\t}, [nextFocusValue]);\n\n\t/**\n\t * Calls handleFocusForward when the user is attempting to focus forward using\n\t * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n\t */\n\tconst handleKeyboardFocusKeydown = (\n\t\te: KeyboardEvent,\n\t\tcallbacks: Record<\n\t\t\t'handleFocusForward' | 'handleFocusBackward',\n\t\t\t(direction: 'next' | 'previous') => void\n\t\t>,\n\t) => {\n\t\tconst keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n\t\tif (keyOps.includes(e.key)) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n\t\t\t\tcallbacks.handleFocusBackward?.('previous');\n\t\t\t} else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n\t\t\t\tcallbacks.handleFocusForward?.('next');\n\t\t\t}\n\t\t}\n\t};\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: ignore\n\tconst renderSearch = useMemo(\n\t\t() =>\n\t\t\tsearchElement\n\t\t\t\t? // biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\t\tcloneElement(searchElement as ReactElement<any>, {\n\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\thandleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n\t\t\t\t\t\t\t\thandleFocusForward: () => focusMenuItem(0),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tref: searchRef,\n\t\t\t\t\t})\n\t\t\t\t: null,\n\t\t[searchElement, lastVirtualItemIndex, focusMenuItem],\n\t);\n\n\tconst renderItems = useMemo(\n\t\t() =>\n\t\t\trowVirtualizer.virtualItems.map((virtualRow) => {\n\t\t\t\tif (!items) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst elem = items[virtualRow.index];\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={virtualRow.index}\n\t\t\t\t\t\tref={virtualRow.measureRef}\n\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\tclassName={styles['VirtualMenu-item']}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\ttransform: `translateY(${virtualRow.start}px)`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{cloneElement(elem, getItemProps(elem, virtualRow.index))}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}),\n\t\t[rowVirtualizer.virtualItems, items, getItemProps],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{renderSearch}\n\t\t\t<MenuItemList ref={parentRef} role=\"presentation\">\n\t\t\t\t<div\n\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\tclassName={styles['VirtualMenu-item-list']}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\theight: `${rowVirtualizer.totalSize}px`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{renderItems}\n\t\t\t\t</div>\n\t\t\t</MenuItemList>\n\t\t</>\n\t);\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACaA,MAAM,2BAAW,WAChB,CAAC,EAAE,UAAU,MAAM,UAAW,GAAG,OAAO,EAAE,QAAQ;CACjD,MAAM,UAAU,GACf,oBAAO,MACP,aAAa,oBAAO,oBACpB,QAAQ,qBAAQ,YAAY,KAAK,GACjC;AAED,wBACC,IAAC,OAAA;EAAI,GAAI;EAAO,MAAK;EAAO,WAAW;EAAc;EACnD;GACI;AAEP,EACD;AAED,SAAS,cAAc;ACjBvB,MAAM,cAAc,CAAC,EACpB,cAAc,OACd,aACA,UACA,gBAAgB,SAAS,gBACP,KAAK;CACvB,MAAM,EAAE,gBAAgB,GAAG,aAAa;EACvC;EACA;CACA,EAAC;AAEF,wBACC,IAAC,OAAA;EACA,GAAI;EACJ,gBAAc;EACd,KAAK;EACL,WAAW,oBAAO;GACjB;AAEH;ACMD,MAAM,iBAAiB;AAYvB,MAAM,WAAW,CAAmD,EACnE,GAAG,OACkB,KAAK;CAC1B,MAAM,EAEL,WACA,UACA,eACA,MACA,QACA,aAEA,MACA,UACA,WACA,SACA,OAAO,YACP,kBACA,WACA,gBACA,SACA,gBAAgB,SAAS,YACzB,GAAG,MACH,GAAG;CAEJ,MAAMA,YAAyB,cAAc,UAAU,OAAO;CAE9D,MAAM,aAAa,wBAAQ,aAAa,MAAM,EAAE,MAAM,QAAS,EAAC;CAEhE,MAAM,+BACL,IAAC,WAAA;EAAU,gBAAgB,oBAAO;4BACjC,IAAC,WAAA;GACA,GAAI;GACM;GACV,iBAAe,WAAW,gBAAA;GAC1B,WAAW,GACV,oBAAO,cACP,WACA,iBAAiB,oBAAO,mBACxB,UAAU,oBAAO,sBACjB,eAAe,oBAAO,qBACtB;GACD,gBAAc;GACR;GACK;aAEV,UACA,2BAEA,KAAA,UAAA,EAAA,UAAA,CACE,wBAAQ,IAAC,QAAA;IAAK,WAAW,oBAAO;cAAoB;KAAkB,EACtE,QAAA,EAAA,EAAA;;GAIO;AAGb,KAAI,QACH,wBACC,IAAC,SAAA;EACA,SAAS;EACT,kBAAkB,EAAE,SAAS,QAAS;EACtC,8BAAA;EACA,WAAW,mBAAmB,mBAAmB;EACjD,GAAK,kBAAkB,CAAE;YAExB;GACQ;AAIZ,QAAO;AACP;AClHD,MAAM,+BAAe,WAA8C,CAAC,EAAE,SAAU,GAAG,MAAM,EAAE,wBAC1F,IAAC,OAAA;CAAI,GAAI;CAAW;CAAK,gBAAa;CAAiB,WAAW,oBAAO;CACvE;EACI,CACL;AAEF,aAAa,cAAc;ACE3B,MAAM,6BAAa,WAA8C,CAAC,OAAO,QAAQ;CAChF,MAAM,EACL,WACA,aACA,IACA,gBAAgB,SAAS,cACzB,GAAG,YACH,GAAG;AAEJ,wBACC,IAAC,OAAA;EAAI,WAAW,oBAAO;4BACtB,IAAC,WAAA;GACA,GAAI;GACC;GACL,WAAW,oBAAO;GAClB,MAAA;GACI;GACJ,MAAK;GACL,gBAAc;GACd,cAAa;GACA;GACb,cAAY,aAAa;;GAErB;AAEP,EAAC;AAEF,WAAW,cAAc;ACzCzB,MAAM,eAAe,CAACa,OAAeX,QAAgB,EAAE,GAAG,QAAQ,MAAM;AAExE,MAAM,kBAAkB,CAACC,OAAsBC,WAC9C,UAAU,OAAO,QAAQ,SAAS,eAAe,aAAa,OAAO,OAAO,CAAC;AAE9E,MAAM,6BAA6B,CAClCC,OACAC,gBAGI;CACJ,MAAM,MAAM;EACX,SAAS,YAAY;EACrB,WAAW,YAAY;EACvB,OAAO,YAAY;CAEnB;AAED,KAAI,IAAI,MAAM,MAAM;AACnB,QAAM,gBAAgB;AACtB,MAAI,MAAM,MAAM,KAAK,YAAY,MAAM;CACvC;AACD;AAED,MAAM,qBACL,CAAC,GAAG,aACJ,CAACC,UAA0B;AAC1B,MAAK,MAAM,KAAK,SACf,QAAO,MAAM,cAAc,EAAE,MAAM;AAEpC;;;;;;ACqCF,MAAM,OAAO,CAA4BC,UAAwB;CAChE,MAAM,EACL,UACA,mBACA,UACA,sBACA,YACA,MACA,WAAW,GACX,gBAAgB,SAAS,QACzB,GAAG;CAEJ,MAAM,eAAe,iBAAiB;CAEtC,MAAM,kBAAkB,YAAY,MAAM;AACzC,gBAAc,UAAU,EAAE,MAAM,KAAM,EAAC;CACvC,GAAE,CAAC,YAAa,EAAC;CAElB,MAAM,gBAAgB,YAAY,MAAM;AACvC,gBAAc,cAAc,EAAE,MAAM,KAAM,EAAC;CAC3C,GAAE,CAAC,YAAa,EAAC;CAElB,MAAM,cAAc,QAAQ,MAAM;EACjC,MAAM,gBAAgB,SAAS,QAAQ,SAAS;AAChD,MAAI,sBAAsB;GAEzB,IAAI,aAAa;GACjB,IAAIC,WAA2B,CAAE;AACjC,QAAK,MAAM,SAAS,cACnB,SAAQ,MAAM,MAAd;IACC,KAAK;AACJ,kBAAa;AACb;IACD,KAAK;IACL,KAAK;AACJ,gBAAW,SAAS,OAAO,MAAM;AACjC;IACD,QACC;GACD;AAEF,UAAO;IAAE,OAAO;IAAU,eAAe;GAAY;EACrD;AAED,SAAO,cAAkC,OACxC,CACC,EAAE,OAAO,eAA8E,EAEvFC,UACI;AACJ,WAAQ,MAAM,MAAd;IACC,KAAK,WACJ,QAAO;KACN;KACA,+BAAe,aAAa,OAAO,EAClC,WAAW,CAACC,MACX,2BAA2B,GAAG;MAC7B,YAAY;MACZ,UAAU;KACV,EAAC,CACH,EAAA;IACD;IACF,KAAK,SACJ,QAAO;KACN,OAAO,MAAM,OACZ,MAAM,MAAM,2BACT,aAAa,OAAO;MACpB,WAAW,GAAG,MAAM,MAAM,WAAW,kBAAkB;MACvD,SAAS,WAAA;MACT,WAAW,WAAA;MACX,UAAA;MACA,UAAU;KACV,EAAC,mBACD,aAAa,OAAO;MACpB,WAAW,GAAG,MAAM,MAAM,WAAW,kBAAkB;MACvD,MAAM,MAAM,MAAM,QAAQ,MAAM;MAEhC,SAAS,mBAAmB,MAAM,MAAM,SAAS,MAAM;AACtD,kBAAW,MAAM,MAAM,QAAQ,MAAM,OAAO;MAC5C,EAAC;MACF,WAAW,CAACA,MACX,2BAA2B,GAAG;OAC7B,YAAY;OACZ,UAAU;MACV,EAAA;KACF,EAAC,CACJ;KACD;IACA;IACF,KAAK,YACJ,QAAO;KAAE,OAAO,MAAM,OAAO,MAAM;KAAE;IAAe;IACrD,QACC,QAAO;KAAE;KAAO;IAAe;GAChC;EACD,GACD;GAAE,OAAO,CAAE;GAAE,eAAe;EAAM,EAClC;CACD,GAAE;EAAC;EAAU;EAAsB;EAAmB;EAAiB;EAAe;CAAS,EAAC;AAEjG,KAAI,qBACH,wBACC,IAAC,UAAA;EAAS,gBAAc;EAAQ,WAAA;EAAgB;4BAC/C,IAAC,iBAAA;GACA,OAAO,SAAS,QAAQ,YAAY,MAAM;GAC1C,eAAe,YAAY;GACjB;GACS;GACT;GACE;GACE;;GAEL;AAIb,wBACC,KAAC,UAAA;EAAS,gBAAc;EAAc;aACpC,YAAY,+BACb,IAAC,cAAA;GAAa,MAAK;aAAgB,YAAY;IAAqB;GAC1D;AAEZ;AAQD,MAAM,kBAAkB,CAA4BC,UAAmC;CACtF,MAAM,EACL,UACA,eACA,aAAa,MACb,mBACA,OACA,cACA,UACA,GAAG;CAEJ,MAAM,SAAS,QAAQ,YAAY,OAAO,CAAC,EAAE;CAE7C,MAAM,mBAAmB,OAAsB,KAAK;CACpD,MAAM,YAAY,OAA8B,KAAK;CACrD,MAAM,YAAY,OAAgC,KAAK;CAEvD,MAAM,CAAC,gBAAgB,kBAAkB,GAAG,SAAwB,KAAK;CAEzE,MAAM,cAAc;CAEpB,MAAM,uBAAuB,QAAQ,MAAM,SAAS,IAAI;CAExD,MAAM,iBAAiB,WAAW;EACjC,MAAM,UAAU,OAAO,MAAM,SAAS;EACtC;EACA,cAAc,YAAY,MAAM,YAAY,CAAC,UAAW,EAAC;EACzD;CACA,EAAC;CAEF,MAAM,iBAAiB,YAAY,MAAM;AACxC,iBAAe,cAAc,EAAE;AAC/B,YAAU,SAAS,SAAS;CAC5B,GAAE,CAAC,cAAe,EAAC;;;;;CAMpB,MAAM,gBAAgB,YACrB,CAACC,UAAkB;AAClB,iBAAe,cAAc,MAAM;AACnC,oBAAkB,MAAM;CACxB,GACD,CAAC,cAAe,EAChB;CAED,MAAM,iCAAiC,YACtC,CAACC,cAAmC;AACnC,MAAI,iBAAiB,YAAY,QAAQ,iBAAiB,iBAAA,EACzD;EAED,MAAM,YACL,cAAc,SAAS,iBAAiB,UAAU,IAAI,iBAAiB,UAAU;EAClF,MAAM,aACJ,cAAc,UAAU,iBAAiB,YAAY,wBACrD,cAAc,cAAc,iBAAiB,YAAY;AAC3D,MAAI,YAAY;AAGf,OAAI,UACH,iBAAgB;OAGhB,eAAc,cAAc,SAAS,IAAI,qBAAqB;AAE/D;EACA;AACD,UAAQ,WAAR;GACC,KAAK;AACJ,mBAAe,cAAc,UAAU;AACvC,kBAAc,WAAW;AACzB;GACD,KAAK;AACJ,mBAAe,cAAc,UAAU;AACvC,kBAAc,eAAe;AAC7B;GACD,QACC;EACD;CACD,GACD;EAAC;EAAc;EAAe;EAAgB;EAAW;EAAsB;CAAe,EAC9F;CAED,MAAM,eAAe,YACpB,CAACC,UAAwBF,UAAkB;EAC1C,MAAM,aAAa,SAAS;AAC5B,UAAQ,SAAS,MAAjB;GACC,KAAK,SACJ,QAAO;IACN,WAAW,GAAG,WAAW,WAAW,kBAAkB;IAEtD,WAAW,WAAW,WACnB,WAAA,IACA,CAACF,MACD,2BAA2B,GAAG;KAC7B,qBAAqB;KACrB,oBAAoB;IACpB,EAAC;IACL,SAAS,mBAAmB,WAAW,SAAS,MAAM;AACrD,sBAAiB,UAAU;IAC3B,EAAC;IACF,IAAI,aAAa,OAAO,OAAO,QAAQ;IACvC,QAAQ,mBAAmB,WAAW,QAAQ,MAAM;AACnD,sBAAiB,UAAU;IAC3B,EAAC;IACF,SAAS,WAAW,WACjB,WAAA,IACA,mBAAmB,WAAW,SAAS,MAAM;AAC7C,gBAAW,WAAW,KAAU;IAChC,EAAA;GACH;GACF,QACC,QAAO,CAAE;EACV;CACD,GACD;EAAC;EAAgC;EAAmB;CAAS,EAC7D;AAED,WAAU,MAAM;AACf,MAAI,mBAAmB,MAAM;AAC5B,yBAAsB,MAAM;IAC3B,MAAM,UAAU,gBAAgB,gBAAgB,OAAO,QAAQ;AAC/D,aAAS,OAAO;GAChB,EAAC;AACF,qBAAkB,KAAK;EACvB;CACD,GAAE,CAAC,cAAe,EAAC;;;;;CAMpB,MAAM,6BAA6B,CAClCA,GACAK,cAII;EACJ,MAAM,SAAS;GAAC;GAAO;GAAW;EAAY;AAC9C,MAAI,OAAO,SAAS,EAAE,IAAI,EAAE;AAC3B,KAAE,gBAAgB;AAClB,KAAE,iBAAiB;AACnB,OAAK,EAAE,QAAQ,SAAS,EAAE,YAAa,EAAE,QAAQ,UAChD,WAAU,sBAAsB,WAAW;YACjC,EAAE,QAAQ,eAAe,EAAE,QAAQ,MAC7C,WAAU,qBAAqB,OAAO;EAEvC;CACD;CAGD,MAAM,eAAe,QACpB,MACC,gCAEE,aAAa,eAAoC;EAChD,WAAW,CAACL,MACX,2BAA2B,GAAG;GAC7B,qBAAqB,MAAM,cAAc,qBAAqB;GAC9D,oBAAoB,MAAM,cAAc,EAAA;EACxC,EAAC;EACH,KAAK;CACL,EAAC,GACD,MACJ;EAAC;EAAe;EAAsB;CAAc,EACpD;CAED,MAAM,cAAc,QACnB,MACC,eAAe,aAAa,IAAI,CAAC,eAAe;AAC/C,OAAK,MACJ,QAAO;EAER,MAAM,OAAO,MAAM,WAAW;AAC9B,yBACC,IAAC,OAAA;GAEA,KAAK,WAAW;GAChB,MAAK;GACL,WAAW,oBAAO;GAClB,OAAO,EACN,YAAY,aAAa,WAAW,MAAM,KAC1C;6BAEA,aAAa,MAAM,aAAa,MAAM,WAAW,MAAM,CAAA;KARnD,WAAW,MASX;CAEP,EAAC,EACH;EAAC,eAAe;EAAc;EAAO;CAAa,EAClD;AAED,wBACC,KAAA,UAAA,EAAA,UAAA,CACE,8BACD,IAAC,cAAA;EAAa,KAAK;EAAW,MAAK;4BAClC,IAAC,OAAA;GACA,MAAK;GACL,WAAW,oBAAO;GAClB,OAAO,EACN,SAAS,EAAE,eAAe,UAAU,IACpC;aAEA;;GAEY,EAAA,EACb;AAEJ"}
1
+ {"version":3,"file":"index.es.js","names":["Component: ElementType","elements: ReactElement[]"],"sources":["../src/styles/Menu.module.css","../src/MenuBase.tsx","../src/MenuDivider.tsx","../src/MenuItem.tsx","../src/MenuItemList.tsx","../src/MenuSearch.tsx","../src/utils.ts","../src/Menu.tsx"],"sourcesContent":[".Menu-item {\n\tbackground-color: transparent;\n\tborder-radius: var(--lp-border-radius-regular);\n\tborder-width: var(--lp-border-width-100);\n\tcolor: var(--lp-color-text-ui-primary-base);\n\tcursor: pointer;\n\tdisplay: block;\n\tfont: var(--lp-text-label-1-medium);\n\toutline: none;\n\toverflow: hidden;\n\tpadding-inline: var(--lp-spacing-300);\n\tpadding-block: var(--lp-spacing-200);\n\tposition: relative;\n\ttext-align: left;\n\ttext-decoration: none;\n\ttext-overflow: ellipsis;\n\tuser-select: none;\n\twhite-space: nowrap;\n\twidth: 100%;\n}\n\n.Menu-item-list {\n\tmax-height: 55vh;\n\tmin-width: 7.5rem;\n\toverflow: auto;\n\tpadding: var(--lp-spacing-200);\n}\n\n.Menu .Menu-item:not([disabled]):not([aria-disabled]):not(.Menu-item--header) {\n\t&:active {\n\t\ttext-decoration: none;\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-active);\n\t}\n\n\t&:hover:not(:active):not(.has-focus) {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t}\n\n\t&.has-focus {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t\tbox-shadow: inset 0 0 0 2px var(--lp-color-shadow-interactive-focus);\n\t}\n}\n\n.Menu {\n\tbackground: var(--lp-color-bg-overlay-secondary);\n\tborder-radius: var(--lp-border-radius-medium);\n\tfont-family: var(--lp-font-family-base);\n\n\t&:focus {\n\t\toutline: none;\n\t}\n\n\t/* Override our link styles for link component */\n\t& a.Menu-item {\n\t\t&:focus:not(:hover):not(.has-focus) {\n\t\t\ttext-decoration: none;\n\t\t\tbox-shadow: none;\n\t\t}\n\n\t\t/* Ensures that links that are disabled don't show active styles */\n\t\t&:active[disabled],\n\t\t&:active[aria-disabled] {\n\t\t\ttext-decoration: none;\n\t\t\tcolor: var(--lp-color-text-interactive-disabled);\n\t\t}\n\t}\n}\n\n.Menu-item--nested {\n\tpadding-left: 2.5rem;\n}\n\n.Menu-item--header {\n\tfont: var(--lp-text-small-1-regular);\n\tcolor: var(--lp-color-text-ui-tertiary);\n}\n\n.Menu-item-icon {\n\tmargin-right: var(--lp-spacing-300);\n}\n\n.Menu-item :global(.Gravatar) {\n\tmargin-right: 0.3125rem;\n}\n\n.Menu-item.is-highlighted {\n\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n}\n\n.Menu-item[aria-disabled],\n.Menu-item[disabled] {\n\tcolor: var(--lp-color-text-interactive-disabled);\n\tcursor: not-allowed;\n}\n\n.Menu-divider {\n\tborder-top: 1px solid var(--lp-color-border-ui-secondary);\n\tmargin: var(--lp-spacing-200) 0;\n}\n\n.Menu-search {\n\tborder-bottom: 1px solid var(--lp-color-border-ui-secondary);\n\tpadding: var(--lp-spacing-300);\n}\n\n[class*='_Popover-content'] .Menu-search {\n\twidth: 100%;\n\n\t/* Removing anything that could give it some height */\n\t& .Menu-search-hidden-placeholder {\n\t\tpadding-top: 0;\n\t\tpadding-bottom: 0;\n\t\theight: 0;\n\t\tborder: none;\n\t\tvisibility: hidden;\n\t}\n}\n\n.Menu--isVirtual {\n\tdisplay: flex;\n\talign-items: stretch;\n\tflex-direction: column;\n}\n\n.MenuSize--xl {\n\twidth: 20rem;\n}\n\n.MenuSize--lg {\n\twidth: 15rem;\n}\n\n.MenuSize--md {\n\twidth: 10rem;\n}\n\n.MenuSize--sm {\n\twidth: 7.5rem;\n}\n\n.VirtualMenu-item-list {\n\twidth: 100%;\n\tposition: relative;\n}\n\n.VirtualMenu-item {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n}\n","import type { ComponentPropsWithRef } from 'react';\nimport type { MenuProps } from './Menu';\n\nimport { cx } from 'classix';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuBaseProps = ComponentPropsWithRef<'div'> & {\n\tisVirtual?: boolean;\n\tsize?: MenuProps<string>['size'];\n};\n\nconst MenuBase = forwardRef<HTMLDivElement, MenuBaseProps>(\n\t({ children, size, isVirtual, ...props }, ref) => {\n\t\tconst classes = cx(\n\t\t\tstyles.Menu,\n\t\t\tisVirtual && styles['Menu--isVirtual'],\n\t\t\tsize && styles[`MenuSize--${size}`],\n\t\t);\n\n\t\treturn (\n\t\t\t<div {...props} role=\"menu\" className={classes} ref={ref}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t},\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n","import type { RefObject } from 'react';\n\nimport { type SeparatorProps, useSeparator } from 'react-aria/useSeparator';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuDividerProps = SeparatorProps & {\n\tinnerRef?: RefObject<HTMLDivElement>;\n\t'data-test-id'?: string;\n};\n\nconst MenuDivider = ({\n\telementType = 'div',\n\torientation,\n\tinnerRef,\n\t'data-test-id': testId = 'menu-divider',\n}: MenuDividerProps) => {\n\tconst { separatorProps } = useSeparator({\n\t\torientation,\n\t\telementType,\n\t});\n\n\treturn (\n\t\t<div\n\t\t\t{...separatorProps}\n\t\t\tdata-test-id={testId}\n\t\t\tref={innerRef}\n\t\t\tclassName={styles['Menu-divider']}\n\t\t/>\n\t);\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n","import type { IconProps } from '@launchpad-ui/icons';\nimport type { PopoverPlacement } from '@launchpad-ui/popover';\nimport type { ComponentPropsWithRef, ElementType, JSX, PropsWithRef, ReactElement } from 'react';\n\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cx } from 'classix';\nimport { cloneElement } from 'react';\nimport { FocusRing } from 'react-aria/FocusRing';\n\nimport styles from './styles/Menu.module.css';\n\n// Merge two types and get rid of overlapping definitions\ntype Merge<T, U> = Omit<T, keyof U> & U;\n\ntype PropsWithComponent<P, T extends ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends ElementType> = Merge<\n\tT extends keyof JSX.IntrinsicElements\n\t\t? PropsWithRef<JSX.IntrinsicElements[T]>\n\t\t: ComponentPropsWithRef<T>,\n\tPropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n\tisHighlighted?: boolean;\n\ticon?: ReactElement<IconProps>;\n\tdisabled?: boolean;\n\tnested?: boolean;\n\tgroupHeader?: boolean;\n\ttooltip?: string | ReactElement;\n\ttooltipOptions?: ComponentPropsWithRef<typeof Tooltip>;\n\ttooltipPlacement?: PopoverPlacement;\n\tasChild?: boolean;\n\t'data-test-id'?: string;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<P, T extends ElementType = typeof defaultElement> = PolymorphicPropsWithRef<\n\t| (MenuItemOwnProps & {\n\t\t\titem: P; // Infer the type if it is included\n\t })\n\t| (MenuItemOwnProps & {\n\t\t\titem?: undefined;\n\t }),\n\tT\n>;\n\nconst MenuItem = <P, T extends ElementType = typeof defaultElement>({\n\t...props\n}: MenuItemProps<P, T>) => {\n\tconst {\n\t\t// TODO: remove component prop once we migrate over to asChild format\n\t\tcomponent,\n\t\tchildren,\n\t\tisHighlighted,\n\t\ticon,\n\t\tnested,\n\t\tgroupHeader,\n\t\t// biome-ignore lint/correctness/noUnusedVariables: ignore\n\t\titem,\n\t\tdisabled,\n\t\tclassName,\n\t\ttooltip,\n\t\trole = 'menuitem',\n\t\ttooltipPlacement,\n\t\tonKeyDown,\n\t\ttooltipOptions,\n\t\tasChild,\n\t\t'data-test-id': testId = 'menu-item',\n\t\t...rest\n\t} = props;\n\n\tconst Component: ElementType = component || (asChild ? Slot : defaultElement);\n\n\tconst renderIcon = icon && cloneElement(icon, { size: 'small' });\n\n\tconst renderedItem = (\n\t\t<FocusRing focusRingClass={styles['has-focus']}>\n\t\t\t<Component\n\t\t\t\t{...rest}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-disabled={disabled ? disabled : undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\tstyles['Menu-item'],\n\t\t\t\t\tclassName,\n\t\t\t\t\tisHighlighted && styles['is-highlighted'],\n\t\t\t\t\tnested && styles['Menu-item--nested'],\n\t\t\t\t\tgroupHeader && styles['Menu-item--header'],\n\t\t\t\t)}\n\t\t\t\tdata-test-id={testId}\n\t\t\t\trole={role}\n\t\t\t\tonKeyDown={onKeyDown}\n\t\t\t>\n\t\t\t\t{asChild ? (\n\t\t\t\t\tchildren\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{icon && <span className={styles['Menu-item-icon']}>{renderIcon}</span>}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Component>\n\t\t</FocusRing>\n\t);\n\n\tif (tooltip) {\n\t\treturn (\n\t\t\t<Tooltip\n\t\t\t\tcontent={tooltip}\n\t\t\t\trootElementStyle={{ display: 'block' }}\n\t\t\t\tallowBoundaryElementOverflow\n\t\t\t\tplacement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n\t\t\t\t{...(tooltipOptions || {})}\n\t\t\t>\n\t\t\t\t{renderedItem}\n\t\t\t</Tooltip>\n\t\t);\n\t}\n\n\treturn renderedItem;\n};\n\nexport { MenuItem };\nexport type { MenuItemProps };\n","import type { ComponentPropsWithRef } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuItemListProps = Omit<ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n\t<div {...rest} ref={ref} data-test-id=\"menu-item-list\" className={styles['Menu-item-list']}>\n\t\t{children}\n\t</div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n","import type { ChangeEvent } from 'react';\n\nimport { TextField } from '@launchpad-ui/form';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuSearchProps = {\n\tariaLabel?: string;\n\tvalue?: string;\n\tid?: string;\n\tplaceholder?: string;\n\tonChange?(event: ChangeEvent<HTMLInputElement>): void;\n\t'data-test-id'?: string;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n\tconst {\n\t\tariaLabel,\n\t\tplaceholder,\n\t\tid,\n\t\t'data-test-id': testId = 'menu-search',\n\t\t...finalProps\n\t} = props;\n\n\treturn (\n\t\t<div className={styles['Menu-search']}>\n\t\t\t<TextField\n\t\t\t\t{...finalProps}\n\t\t\t\tref={ref}\n\t\t\t\tclassName={styles['Menu-search-input']}\n\t\t\t\ttiny\n\t\t\t\tid={id}\n\t\t\t\ttype=\"search\"\n\t\t\t\tdata-test-id={testId}\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\taria-label={ariaLabel || 'Search'}\n\t\t\t/>\n\t\t</div>\n\t);\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n","import type { EventHandler, KeyboardEvent, SyntheticEvent } from 'react';\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n\tindex === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst handleKeyboardInteractions = (\n\tevent: KeyboardEvent,\n\tkeyHandlers: Partial<\n\t\tRecord<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n\t>,\n) => {\n\tconst ops = {\n\t\tArrowUp: keyHandlers.handleUp,\n\t\tArrowDown: keyHandlers.handleDown,\n\t\tEnter: keyHandlers.handleEnter,\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: ignore\n\t} as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n\tif (ops[event.key]) {\n\t\tevent.preventDefault();\n\t\tops[event.key]?.call(globalThis, event);\n\t}\n};\n\nconst chainEventHandlers =\n\t(...handlers: (EventHandler<SyntheticEvent> | undefined)[]) =>\n\t(event: SyntheticEvent) => {\n\t\tfor (const h of handlers) {\n\t\t\ttypeof h === 'function' && h(event);\n\t\t}\n\t};\n\nexport { createItemId, getNodeForIndex, handleKeyboardInteractions, chainEventHandlers };\n","import type { KeyboardEvent, ReactElement, ReactNode } from 'react';\nimport type { MenuItemProps } from './MenuItem';\n\nimport { cx } from 'classix';\nimport {\n\tChildren,\n\tcloneElement,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { type FocusManager, useFocusManager } from 'react-aria/FocusScope';\nimport { useVirtual } from 'react-virtual';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport styles from './styles/Menu.module.css';\nimport {\n\tchainEventHandlers,\n\tcreateItemId,\n\tgetNodeForIndex,\n\thandleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n\tchildren: ReactNode;\n\tonSelect?: (item: T) => void;\n\t/**\n\t * Menus items are rendered using react-virtual for\n\t * additional rendering performance.\n\t */\n\tenableVirtualization?: boolean;\n\t/**\n\t * Class name to be applied to all MenuItem components\n\t * in the menu.\n\t */\n\tmenuItemClassName?: string;\n\t/**\n\t * Sets the width of the menu. This is especially useful when using virtual items\n\t * since the width cannot be automatically set by the widest element.\n\t */\n\tsize?: 'sm' | 'md' | 'lg' | 'xl';\n\t/**\n\t * Sets the number out of elements rendered outside of the view window\n\t * when using virtualization\n\t */\n\toverscan?: number;\n\t/**\n\t * Sets the height for each menu item when using virtualization.\n\t *\n\t */\n\titemHeight?: number;\n\t'data-test-id'?: string;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\n/**\n * @deprecated use `Menu` or `ListBox` from `@launchpad-ui/components` instead\n *\n * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs\n */\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n\tconst {\n\t\tchildren,\n\t\tmenuItemClassName,\n\t\tonSelect,\n\t\tenableVirtualization,\n\t\titemHeight,\n\t\tsize,\n\t\toverscan = 1,\n\t\t'data-test-id': testId = 'menu',\n\t} = props;\n\n\tconst focusManager = useFocusManager();\n\n\tconst handleArrowDown = useCallback(() => {\n\t\tfocusManager?.focusNext({ wrap: true });\n\t}, [focusManager]);\n\n\tconst handleArrowUp = useCallback(() => {\n\t\tfocusManager?.focusPrevious({ wrap: true });\n\t}, [focusManager]);\n\n\tconst reduceItems = useMemo(() => {\n\t\tconst childrenProps = Children.toArray(children);\n\t\tif (enableVirtualization) {\n\t\t\t// the virtualized menu has its own handlers and props\n\t\t\tlet searchElem = null;\n\t\t\tlet elements: ReactElement[] = [];\n\t\t\tfor (const child of childrenProps as ReactElement[]) {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\tsearchElem = child;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\telements = elements.concat(child);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { items: elements, searchElement: searchElem };\n\t\t}\n\n\t\treturn (childrenProps as ReactElement[]).reduce(\n\t\t\t(\n\t\t\t\t{ items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\tchild: ReactElement<any>,\n\t\t\t) => {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems,\n\t\t\t\t\t\t\tsearchElement: cloneElement(child, {\n\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems: items.concat(\n\t\t\t\t\t\t\t\tchild.props.disabled\n\t\t\t\t\t\t\t\t\t? cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\tonClick: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\t\t\t\t\t\t\tdisabled: true,\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t: cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\titem: child.props.item ?? items.length,\n\t\t\t\t\t\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\t\t\t\t\t\tonClick: chainEventHandlers(child.props.onClick, () => {\n\t\t\t\t\t\t\t\t\t\t\t\tonSelect?.(child.props.item ?? items.length);\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tsearchElement,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\treturn { items: items.concat(child), searchElement };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn { items, searchElement };\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ items: [], searchElement: null },\n\t\t);\n\t}, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n\tif (enableVirtualization) {\n\t\treturn (\n\t\t\t<MenuBase data-test-id={testId} isVirtual size={size}>\n\t\t\t\t<ItemVirtualizer<T>\n\t\t\t\t\titems={Children.toArray(reduceItems.items) as ReactElement[]}\n\t\t\t\t\tsearchElement={reduceItems.searchElement}\n\t\t\t\t\toverscan={overscan}\n\t\t\t\t\tmenuItemClassName={menuItemClassName}\n\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\titemHeight={itemHeight}\n\t\t\t\t\tfocusManager={focusManager}\n\t\t\t\t/>\n\t\t\t</MenuBase>\n\t\t);\n\t}\n\n\treturn (\n\t\t<MenuBase data-test-id={testId} size={size}>\n\t\t\t{reduceItems.searchElement}\n\t\t\t<MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n\t\t</MenuBase>\n\t);\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n\titems: ReactElement[] | null;\n\tsearchElement?: ReactElement | null;\n\tfocusManager?: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n\tconst {\n\t\toverscan,\n\t\tsearchElement,\n\t\titemHeight = 31.5,\n\t\tmenuItemClassName,\n\t\titems,\n\t\tfocusManager,\n\t\tonSelect,\n\t} = props;\n\n\tconst menuId = useRef(`menu-ctrl-${useId()}`);\n\n\tconst focusedItemIndex = useRef<number | null>(null);\n\tconst parentRef = useRef<HTMLDivElement | null>(null);\n\tconst searchRef = useRef<HTMLInputElement | null>(null);\n\n\tconst [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n\tconst hasSearch = !!searchElement;\n\n\tconst lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n\tconst rowVirtualizer = useVirtual({\n\t\tsize: items !== null ? items.length : 0,\n\t\tparentRef,\n\t\testimateSize: useCallback(() => itemHeight, [itemHeight]),\n\t\toverscan,\n\t});\n\n\tconst focusSearchBar = useCallback(() => {\n\t\trowVirtualizer.scrollToIndex(0);\n\t\tsearchRef.current?.focus?.();\n\t}, [rowVirtualizer]);\n\n\t/**\n\t * Scrolls to the menu item with the index provided and\n\t * then manually focuses it using a side effect in useEffect\n\t */\n\tconst focusMenuItem = useCallback(\n\t\t(index: number) => {\n\t\t\trowVirtualizer.scrollToIndex(index);\n\t\t\tsetNextFocusValue(index);\n\t\t},\n\t\t[rowVirtualizer],\n\t);\n\n\tconst handleKeyboardFocusInteraction = useCallback(\n\t\t(direction: 'next' | 'previous') => {\n\t\t\tif (focusedItemIndex.current === null || focusedItemIndex.current === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextIndex =\n\t\t\t\tdirection === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n\t\t\tconst shouldWrap =\n\t\t\t\t(direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n\t\t\t\t(direction === 'previous' && focusedItemIndex.current === 0);\n\t\t\tif (shouldWrap) {\n\t\t\t\t// we are at the end of the list so we will\n\t\t\t\t// scroll back to the beginning of the list\n\t\t\t\tif (hasSearch) {\n\t\t\t\t\tfocusSearchBar();\n\t\t\t\t} else {\n\t\t\t\t\t// if at end, wrap to beginning, else focus last item\n\t\t\t\t\tfocusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tswitch (direction) {\n\t\t\t\tcase 'next':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusNext();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'previous':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusPrevious();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t[focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer],\n\t);\n\n\tconst getItemProps = useCallback(\n\t\t(itemElem: ReactElement, index: number) => {\n\t\t\tconst childProps = itemElem.props as MenuItemProps<T>;\n\t\t\tswitch (itemElem.type) {\n\t\t\t\tcase MenuItem:\n\t\t\t\t\treturn {\n\t\t\t\t\t\tclassName: cx(childProps.className, menuItemClassName),\n\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\tonKeyDown: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\t\t\thandleFocusBackward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t\thandleFocusForward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tonFocus: chainEventHandlers(childProps.onFocus, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = index;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tid: createItemId(index, menuId.current),\n\t\t\t\t\t\tonBlur: chainEventHandlers(childProps.onBlur, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = null;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tonClick: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: chainEventHandlers(childProps.onClick, () => {\n\t\t\t\t\t\t\t\t\tonSelect?.(childProps.item as T);\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t} as MenuItemProps<T>;\n\t\t\t\tdefault:\n\t\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\t[handleKeyboardFocusInteraction, menuItemClassName, onSelect],\n\t);\n\n\tuseEffect(() => {\n\t\tif (nextFocusValue !== null) {\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tconst element = getNodeForIndex(nextFocusValue, menuId.current);\n\t\t\t\telement?.focus();\n\t\t\t});\n\t\t\tsetNextFocusValue(null);\n\t\t}\n\t}, [nextFocusValue]);\n\n\t/**\n\t * Calls handleFocusForward when the user is attempting to focus forward using\n\t * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n\t */\n\tconst handleKeyboardFocusKeydown = (\n\t\te: KeyboardEvent,\n\t\tcallbacks: Record<\n\t\t\t'handleFocusForward' | 'handleFocusBackward',\n\t\t\t(direction: 'next' | 'previous') => void\n\t\t>,\n\t) => {\n\t\tconst keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n\t\tif (keyOps.includes(e.key)) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n\t\t\t\tcallbacks.handleFocusBackward?.('previous');\n\t\t\t} else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n\t\t\t\tcallbacks.handleFocusForward?.('next');\n\t\t\t}\n\t\t}\n\t};\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: ignore\n\tconst renderSearch = useMemo(\n\t\t() =>\n\t\t\tsearchElement\n\t\t\t\t? // biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\t\tcloneElement(searchElement as ReactElement<any>, {\n\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\thandleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n\t\t\t\t\t\t\t\thandleFocusForward: () => focusMenuItem(0),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tref: searchRef,\n\t\t\t\t\t})\n\t\t\t\t: null,\n\t\t[searchElement, lastVirtualItemIndex, focusMenuItem],\n\t);\n\n\tconst renderItems = useMemo(\n\t\t() =>\n\t\t\trowVirtualizer.virtualItems.map((virtualRow) => {\n\t\t\t\tif (!items) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst elem = items[virtualRow.index];\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={virtualRow.index}\n\t\t\t\t\t\tref={virtualRow.measureRef}\n\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\tclassName={styles['VirtualMenu-item']}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\ttransform: `translateY(${virtualRow.start}px)`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{cloneElement(elem, getItemProps(elem, virtualRow.index))}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}),\n\t\t[rowVirtualizer.virtualItems, items, getItemProps],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{renderSearch}\n\t\t\t<MenuItemList ref={parentRef} role=\"presentation\">\n\t\t\t\t<div\n\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\tclassName={styles['VirtualMenu-item-list']}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\theight: `${rowVirtualizer.totalSize}px`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{renderItems}\n\t\t\t\t</div>\n\t\t\t</MenuItemList>\n\t\t</>\n\t);\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,33 +1,15 @@
1
1
  require('./style.css');
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
- value: mod,
20
- enumerable: true
21
- }) : target, mod));
22
- const __react_aria_focus = __toESM(require("@react-aria/focus"));
23
- const classix = __toESM(require("classix"));
24
- const react = __toESM(require("react"));
25
- const react_virtual = __toESM(require("react-virtual"));
26
- const react_jsx_runtime = __toESM(require("react/jsx-runtime"));
27
- const __react_aria_separator = __toESM(require("@react-aria/separator"));
28
- const __launchpad_ui_tooltip = __toESM(require("@launchpad-ui/tooltip"));
29
- const __radix_ui_react_slot = __toESM(require("@radix-ui/react-slot"));
30
- const __launchpad_ui_form = __toESM(require("@launchpad-ui/form"));
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ let classix = require("classix");
4
+ let react = require("react");
5
+ let react_aria_FocusScope = require("react-aria/FocusScope");
6
+ let react_virtual = require("react-virtual");
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ let react_aria_useSeparator = require("react-aria/useSeparator");
9
+ let __launchpad_ui_tooltip = require("@launchpad-ui/tooltip");
10
+ let __radix_ui_react_slot = require("@radix-ui/react-slot");
11
+ let react_aria_FocusRing = require("react-aria/FocusRing");
12
+ let __launchpad_ui_form = require("@launchpad-ui/form");
31
13
  const Menu$1 = "C73R2W_Menu";
32
14
  var Menu_module_default = {
33
15
  "has-focus": "C73R2W_has-focus",
@@ -49,7 +31,7 @@ var Menu_module_default = {
49
31
  "VirtualMenu-item": "C73R2W_VirtualMenu-item",
50
32
  "VirtualMenu-item-list": "C73R2W_VirtualMenu-item-list"
51
33
  };
52
- const MenuBase = /* @__PURE__ */ (0, react.forwardRef)(({ children, size, isVirtual,...props }, ref) => {
34
+ var MenuBase = /* @__PURE__ */ (0, react.forwardRef)(({ children, size, isVirtual, ...props }, ref) => {
53
35
  const classes = (0, classix.cx)(Menu_module_default.Menu, isVirtual && Menu_module_default["Menu--isVirtual"], size && Menu_module_default[`MenuSize--${size}`]);
54
36
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
55
37
  ...props,
@@ -60,8 +42,8 @@ const MenuBase = /* @__PURE__ */ (0, react.forwardRef)(({ children, size, isVirt
60
42
  });
61
43
  });
62
44
  MenuBase.displayName = "MenuBase";
63
- const MenuDivider = ({ elementType = "div", orientation, innerRef, "data-test-id": testId = "menu-divider" }) => {
64
- const { separatorProps } = (0, __react_aria_separator.useSeparator)({
45
+ var MenuDivider = ({ elementType = "div", orientation, innerRef, "data-test-id": testId = "menu-divider" }) => {
46
+ const { separatorProps } = (0, react_aria_useSeparator.useSeparator)({
65
47
  orientation,
66
48
  elementType
67
49
  });
@@ -72,12 +54,12 @@ const MenuDivider = ({ elementType = "div", orientation, innerRef, "data-test-id
72
54
  className: Menu_module_default["Menu-divider"]
73
55
  });
74
56
  };
75
- const defaultElement = "button";
76
- const MenuItem = ({ ...props }) => {
77
- const { component, children, isHighlighted, icon, nested, groupHeader, item, disabled, className, tooltip, role = "menuitem", tooltipPlacement, onKeyDown, tooltipOptions, asChild, "data-test-id": testId = "menu-item",...rest } = props;
57
+ var defaultElement = "button";
58
+ var MenuItem = ({ ...props }) => {
59
+ const { component, children, isHighlighted, icon, nested, groupHeader, item, disabled, className, tooltip, role = "menuitem", tooltipPlacement, onKeyDown, tooltipOptions, asChild, "data-test-id": testId = "menu-item", ...rest } = props;
78
60
  const Component = component || (asChild ? __radix_ui_react_slot.Slot : defaultElement);
79
61
  const renderIcon = icon && /* @__PURE__ */ (0, react.cloneElement)(icon, { size: "small" });
80
- const renderedItem = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__react_aria_focus.FocusRing, {
62
+ const renderedItem = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_aria_FocusRing.FocusRing, {
81
63
  focusRingClass: Menu_module_default["has-focus"],
82
64
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
83
65
  ...rest,
@@ -103,7 +85,7 @@ const MenuItem = ({ ...props }) => {
103
85
  });
104
86
  return renderedItem;
105
87
  };
106
- const MenuItemList = /* @__PURE__ */ (0, react.forwardRef)(({ children,...rest }, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
88
+ var MenuItemList = /* @__PURE__ */ (0, react.forwardRef)(({ children, ...rest }, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
107
89
  ...rest,
108
90
  ref,
109
91
  "data-test-id": "menu-item-list",
@@ -111,8 +93,8 @@ const MenuItemList = /* @__PURE__ */ (0, react.forwardRef)(({ children,...rest }
111
93
  children
112
94
  }));
113
95
  MenuItemList.displayName = "MenuItemList";
114
- const MenuSearch = /* @__PURE__ */ (0, react.forwardRef)((props, ref) => {
115
- const { ariaLabel, placeholder, id, "data-test-id": testId = "menu-search",...finalProps } = props;
96
+ var MenuSearch = /* @__PURE__ */ (0, react.forwardRef)((props, ref) => {
97
+ const { ariaLabel, placeholder, id, "data-test-id": testId = "menu-search", ...finalProps } = props;
116
98
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
117
99
  className: Menu_module_default["Menu-search"],
118
100
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__launchpad_ui_form.TextField, {
@@ -130,9 +112,9 @@ const MenuSearch = /* @__PURE__ */ (0, react.forwardRef)((props, ref) => {
130
112
  });
131
113
  });
132
114
  MenuSearch.displayName = "MenuSearch";
133
- const createItemId = (index, id) => `${id}-item-${index}`;
134
- const getNodeForIndex = (index, menuId) => index === null ? index : document.getElementById(createItemId(index, menuId));
135
- const handleKeyboardInteractions = (event, keyHandlers) => {
115
+ var createItemId = (index, id) => `${id}-item-${index}`;
116
+ var getNodeForIndex = (index, menuId) => index === null ? index : document.getElementById(createItemId(index, menuId));
117
+ var handleKeyboardInteractions = (event, keyHandlers) => {
136
118
  const ops = {
137
119
  ArrowUp: keyHandlers.handleUp,
138
120
  ArrowDown: keyHandlers.handleDown,
@@ -143,17 +125,12 @@ const handleKeyboardInteractions = (event, keyHandlers) => {
143
125
  ops[event.key]?.call(globalThis, event);
144
126
  }
145
127
  };
146
- const chainEventHandlers = (...handlers) => (event) => {
128
+ var chainEventHandlers = (...handlers) => (event) => {
147
129
  for (const h of handlers) typeof h === "function" && h(event);
148
130
  };
149
- /**
150
- * @deprecated use `Menu` or `ListBox` from `@launchpad-ui/components` instead
151
- *
152
- * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs
153
- */
154
- const Menu = (props) => {
131
+ var Menu = (props) => {
155
132
  const { children, menuItemClassName, onSelect, enableVirtualization, itemHeight, size, overscan = 1, "data-test-id": testId = "menu" } = props;
156
- const focusManager = (0, __react_aria_focus.useFocusManager)();
133
+ const focusManager = (0, react_aria_FocusScope.useFocusManager)();
157
134
  const handleArrowDown = (0, react.useCallback)(() => {
158
135
  focusManager?.focusNext({ wrap: true });
159
136
  }, [focusManager]);
@@ -253,7 +230,7 @@ const Menu = (props) => {
253
230
  })]
254
231
  });
255
232
  };
256
- const ItemVirtualizer = (props) => {
233
+ var ItemVirtualizer = (props) => {
257
234
  const { overscan, searchElement, itemHeight = 31.5, menuItemClassName, items, focusManager, onSelect } = props;
258
235
  const menuId = (0, react.useRef)(`menu-ctrl-${(0, react.useId)()}`);
259
236
  const focusedItemIndex = (0, react.useRef)(null);
@@ -272,10 +249,6 @@ const ItemVirtualizer = (props) => {
272
249
  rowVirtualizer.scrollToIndex(0);
273
250
  searchRef.current?.focus?.();
274
251
  }, [rowVirtualizer]);
275
- /**
276
- * Scrolls to the menu item with the index provided and
277
- * then manually focuses it using a side effect in useEffect
278
- */
279
252
  const focusMenuItem = (0, react.useCallback)((index) => {
280
253
  rowVirtualizer.scrollToIndex(index);
281
254
  setNextFocusValue(index);
@@ -283,8 +256,7 @@ const ItemVirtualizer = (props) => {
283
256
  const handleKeyboardFocusInteraction = (0, react.useCallback)((direction) => {
284
257
  if (focusedItemIndex.current === null || focusedItemIndex.current === void 0) return;
285
258
  const nextIndex = direction === "next" ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;
286
- const shouldWrap = direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0;
287
- if (shouldWrap) {
259
+ if (direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0) {
288
260
  if (hasSearch) focusSearchBar();
289
261
  else focusMenuItem(direction === "next" ? 0 : lastVirtualItemIndex);
290
262
  return;
@@ -338,23 +310,17 @@ const ItemVirtualizer = (props) => {
338
310
  (0, react.useEffect)(() => {
339
311
  if (nextFocusValue !== null) {
340
312
  requestAnimationFrame(() => {
341
- const element = getNodeForIndex(nextFocusValue, menuId.current);
342
- element?.focus();
313
+ getNodeForIndex(nextFocusValue, menuId.current)?.focus();
343
314
  });
344
315
  setNextFocusValue(null);
345
316
  }
346
317
  }, [nextFocusValue]);
347
- /**
348
- * Calls handleFocusForward when the user is attempting to focus forward using
349
- * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.
350
- */
351
318
  const handleKeyboardFocusKeydown = (e, callbacks) => {
352
- const keyOps = [
319
+ if ([
353
320
  "Tab",
354
321
  "ArrowUp",
355
322
  "ArrowDown"
356
- ];
357
- if (keyOps.includes(e.key)) {
323
+ ].includes(e.key)) {
358
324
  e.preventDefault();
359
325
  e.stopPropagation();
360
326
  if (e.key === "Tab" && e.shiftKey || e.key === "ArrowUp") callbacks.handleFocusBackward?.("previous");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Component: ElementType","index: number","id: string","index: number | null","menuId: string","event: KeyboardEvent","keyHandlers: Partial<\n\t\tRecord<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n\t>","event: SyntheticEvent","props: MenuProps<T>","elements: ReactElement[]","child: ReactElement<any>","e: KeyboardEvent","props: ItemVirtualizerProps<T>","index: number","direction: 'next' | 'previous'","itemElem: ReactElement","callbacks: Record<\n\t\t\t'handleFocusForward' | 'handleFocusBackward',\n\t\t\t(direction: 'next' | 'previous') => void\n\t\t>"],"sources":["../src/styles/Menu.module.css","../src/MenuBase.tsx","../src/MenuDivider.tsx","../src/MenuItem.tsx","../src/MenuItemList.tsx","../src/MenuSearch.tsx","../src/utils.ts","../src/Menu.tsx"],"sourcesContent":[".Menu-item {\n\tbackground-color: transparent;\n\tborder-radius: var(--lp-border-radius-regular);\n\tborder-width: var(--lp-border-width-100);\n\tcolor: var(--lp-color-text-ui-primary-base);\n\tcursor: pointer;\n\tdisplay: block;\n\tfont: var(--lp-text-label-1-medium);\n\toutline: none;\n\toverflow: hidden;\n\tpadding-inline: var(--lp-spacing-300);\n\tpadding-block: var(--lp-spacing-200);\n\tposition: relative;\n\ttext-align: left;\n\ttext-decoration: none;\n\ttext-overflow: ellipsis;\n\tuser-select: none;\n\twhite-space: nowrap;\n\twidth: 100%;\n}\n\n.Menu-item-list {\n\tmax-height: 55vh;\n\tmin-width: 7.5rem;\n\toverflow: auto;\n\tpadding: var(--lp-spacing-200);\n}\n\n.Menu .Menu-item:not([disabled]):not([aria-disabled]):not(.Menu-item--header) {\n\t&:active {\n\t\ttext-decoration: none;\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-active);\n\t}\n\n\t&:hover:not(:active):not(.has-focus) {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t}\n\n\t&.has-focus {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t\tbox-shadow: inset 0 0 0 2px var(--lp-color-shadow-interactive-focus);\n\t}\n}\n\n.Menu {\n\tbackground: var(--lp-color-bg-overlay-secondary);\n\tborder-radius: var(--lp-border-radius-medium);\n\tfont-family: var(--lp-font-family-base);\n\n\t&:focus {\n\t\toutline: none;\n\t}\n\n\t/* Override our link styles for link component */\n\t& a.Menu-item {\n\t\t&:focus:not(:hover):not(.has-focus) {\n\t\t\ttext-decoration: none;\n\t\t\tbox-shadow: none;\n\t\t}\n\n\t\t/* Ensures that links that are disabled don't show active styles */\n\t\t&:active[disabled],\n\t\t&:active[aria-disabled] {\n\t\t\ttext-decoration: none;\n\t\t\tcolor: var(--lp-color-text-interactive-disabled);\n\t\t}\n\t}\n}\n\n.Menu-item--nested {\n\tpadding-left: 2.5rem;\n}\n\n.Menu-item--header {\n\tfont: var(--lp-text-small-1-regular);\n\tcolor: var(--lp-color-text-ui-tertiary);\n}\n\n.Menu-item-icon {\n\tmargin-right: var(--lp-spacing-300);\n}\n\n.Menu-item :global(.Gravatar) {\n\tmargin-right: 0.3125rem;\n}\n\n.Menu-item.is-highlighted {\n\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n}\n\n.Menu-item[aria-disabled],\n.Menu-item[disabled] {\n\tcolor: var(--lp-color-text-interactive-disabled);\n\tcursor: not-allowed;\n}\n\n.Menu-divider {\n\tborder-top: 1px solid var(--lp-color-border-ui-secondary);\n\tmargin: var(--lp-spacing-200) 0;\n}\n\n.Menu-search {\n\tborder-bottom: 1px solid var(--lp-color-border-ui-secondary);\n\tpadding: var(--lp-spacing-300);\n}\n\n[class*='_Popover-content'] .Menu-search {\n\twidth: 100%;\n\n\t/* Removing anything that could give it some height */\n\t& .Menu-search-hidden-placeholder {\n\t\tpadding-top: 0;\n\t\tpadding-bottom: 0;\n\t\theight: 0;\n\t\tborder: none;\n\t\tvisibility: hidden;\n\t}\n}\n\n.Menu--isVirtual {\n\tdisplay: flex;\n\talign-items: stretch;\n\tflex-direction: column;\n}\n\n.MenuSize--xl {\n\twidth: 20rem;\n}\n\n.MenuSize--lg {\n\twidth: 15rem;\n}\n\n.MenuSize--md {\n\twidth: 10rem;\n}\n\n.MenuSize--sm {\n\twidth: 7.5rem;\n}\n\n.VirtualMenu-item-list {\n\twidth: 100%;\n\tposition: relative;\n}\n\n.VirtualMenu-item {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n}\n","import type { ComponentPropsWithRef } from 'react';\nimport type { MenuProps } from './Menu';\n\nimport { cx } from 'classix';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuBaseProps = ComponentPropsWithRef<'div'> & {\n\tisVirtual?: boolean;\n\tsize?: MenuProps<string>['size'];\n};\n\nconst MenuBase = forwardRef<HTMLDivElement, MenuBaseProps>(\n\t({ children, size, isVirtual, ...props }, ref) => {\n\t\tconst classes = cx(\n\t\t\tstyles.Menu,\n\t\t\tisVirtual && styles['Menu--isVirtual'],\n\t\t\tsize && styles[`MenuSize--${size}`],\n\t\t);\n\n\t\treturn (\n\t\t\t<div {...props} role=\"menu\" className={classes} ref={ref}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t},\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n","import type { SeparatorProps } from '@react-aria/separator';\nimport type { RefObject } from 'react';\n\nimport { useSeparator } from '@react-aria/separator';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuDividerProps = SeparatorProps & {\n\tinnerRef?: RefObject<HTMLDivElement>;\n\t'data-test-id'?: string;\n};\n\nconst MenuDivider = ({\n\telementType = 'div',\n\torientation,\n\tinnerRef,\n\t'data-test-id': testId = 'menu-divider',\n}: MenuDividerProps) => {\n\tconst { separatorProps } = useSeparator({\n\t\torientation,\n\t\telementType,\n\t});\n\n\treturn (\n\t\t<div\n\t\t\t{...separatorProps}\n\t\t\tdata-test-id={testId}\n\t\t\tref={innerRef}\n\t\t\tclassName={styles['Menu-divider']}\n\t\t/>\n\t);\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n","import type { IconProps } from '@launchpad-ui/icons';\nimport type { PopoverPlacement } from '@launchpad-ui/popover';\nimport type { ComponentPropsWithRef, ElementType, JSX, PropsWithRef, ReactElement } from 'react';\n\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { Slot } from '@radix-ui/react-slot';\nimport { FocusRing } from '@react-aria/focus';\nimport { cx } from 'classix';\nimport { cloneElement } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\n// Merge two types and get rid of overlapping definitions\ntype Merge<T, U> = Omit<T, keyof U> & U;\n\ntype PropsWithComponent<P, T extends ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends ElementType> = Merge<\n\tT extends keyof JSX.IntrinsicElements\n\t\t? PropsWithRef<JSX.IntrinsicElements[T]>\n\t\t: ComponentPropsWithRef<T>,\n\tPropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n\tisHighlighted?: boolean;\n\ticon?: ReactElement<IconProps>;\n\tdisabled?: boolean;\n\tnested?: boolean;\n\tgroupHeader?: boolean;\n\ttooltip?: string | ReactElement;\n\ttooltipOptions?: ComponentPropsWithRef<typeof Tooltip>;\n\ttooltipPlacement?: PopoverPlacement;\n\tasChild?: boolean;\n\t'data-test-id'?: string;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<P, T extends ElementType = typeof defaultElement> = PolymorphicPropsWithRef<\n\t| (MenuItemOwnProps & {\n\t\t\titem: P; // Infer the type if it is included\n\t })\n\t| (MenuItemOwnProps & {\n\t\t\titem?: undefined;\n\t }),\n\tT\n>;\n\nconst MenuItem = <P, T extends ElementType = typeof defaultElement>({\n\t...props\n}: MenuItemProps<P, T>) => {\n\tconst {\n\t\t// TODO: remove component prop once we migrate over to asChild format\n\t\tcomponent,\n\t\tchildren,\n\t\tisHighlighted,\n\t\ticon,\n\t\tnested,\n\t\tgroupHeader,\n\t\t// biome-ignore lint/correctness/noUnusedVariables: ignore\n\t\titem,\n\t\tdisabled,\n\t\tclassName,\n\t\ttooltip,\n\t\trole = 'menuitem',\n\t\ttooltipPlacement,\n\t\tonKeyDown,\n\t\ttooltipOptions,\n\t\tasChild,\n\t\t'data-test-id': testId = 'menu-item',\n\t\t...rest\n\t} = props;\n\n\tconst Component: ElementType = component || (asChild ? Slot : defaultElement);\n\n\tconst renderIcon = icon && cloneElement(icon, { size: 'small' });\n\n\tconst renderedItem = (\n\t\t<FocusRing focusRingClass={styles['has-focus']}>\n\t\t\t<Component\n\t\t\t\t{...rest}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-disabled={disabled ? disabled : undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\tstyles['Menu-item'],\n\t\t\t\t\tclassName,\n\t\t\t\t\tisHighlighted && styles['is-highlighted'],\n\t\t\t\t\tnested && styles['Menu-item--nested'],\n\t\t\t\t\tgroupHeader && styles['Menu-item--header'],\n\t\t\t\t)}\n\t\t\t\tdata-test-id={testId}\n\t\t\t\trole={role}\n\t\t\t\tonKeyDown={onKeyDown}\n\t\t\t>\n\t\t\t\t{asChild ? (\n\t\t\t\t\tchildren\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{icon && <span className={styles['Menu-item-icon']}>{renderIcon}</span>}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Component>\n\t\t</FocusRing>\n\t);\n\n\tif (tooltip) {\n\t\treturn (\n\t\t\t<Tooltip\n\t\t\t\tcontent={tooltip}\n\t\t\t\trootElementStyle={{ display: 'block' }}\n\t\t\t\tallowBoundaryElementOverflow\n\t\t\t\tplacement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n\t\t\t\t{...(tooltipOptions || {})}\n\t\t\t>\n\t\t\t\t{renderedItem}\n\t\t\t</Tooltip>\n\t\t);\n\t}\n\n\treturn renderedItem;\n};\n\nexport { MenuItem };\nexport type { MenuItemProps };\n","import type { ComponentPropsWithRef } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuItemListProps = Omit<ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n\t<div {...rest} ref={ref} data-test-id=\"menu-item-list\" className={styles['Menu-item-list']}>\n\t\t{children}\n\t</div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n","import type { ChangeEvent } from 'react';\n\nimport { TextField } from '@launchpad-ui/form';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuSearchProps = {\n\tariaLabel?: string;\n\tvalue?: string;\n\tid?: string;\n\tplaceholder?: string;\n\tonChange?(event: ChangeEvent<HTMLInputElement>): void;\n\t'data-test-id'?: string;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n\tconst {\n\t\tariaLabel,\n\t\tplaceholder,\n\t\tid,\n\t\t'data-test-id': testId = 'menu-search',\n\t\t...finalProps\n\t} = props;\n\n\treturn (\n\t\t<div className={styles['Menu-search']}>\n\t\t\t<TextField\n\t\t\t\t{...finalProps}\n\t\t\t\tref={ref}\n\t\t\t\tclassName={styles['Menu-search-input']}\n\t\t\t\ttiny\n\t\t\t\tid={id}\n\t\t\t\ttype=\"search\"\n\t\t\t\tdata-test-id={testId}\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\taria-label={ariaLabel || 'Search'}\n\t\t\t/>\n\t\t</div>\n\t);\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n","import type { EventHandler, KeyboardEvent, SyntheticEvent } from 'react';\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n\tindex === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst handleKeyboardInteractions = (\n\tevent: KeyboardEvent,\n\tkeyHandlers: Partial<\n\t\tRecord<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n\t>,\n) => {\n\tconst ops = {\n\t\tArrowUp: keyHandlers.handleUp,\n\t\tArrowDown: keyHandlers.handleDown,\n\t\tEnter: keyHandlers.handleEnter,\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: ignore\n\t} as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n\tif (ops[event.key]) {\n\t\tevent.preventDefault();\n\t\tops[event.key]?.call(globalThis, event);\n\t}\n};\n\nconst chainEventHandlers =\n\t(...handlers: (EventHandler<SyntheticEvent> | undefined)[]) =>\n\t(event: SyntheticEvent) => {\n\t\tfor (const h of handlers) {\n\t\t\ttypeof h === 'function' && h(event);\n\t\t}\n\t};\n\nexport { createItemId, getNodeForIndex, handleKeyboardInteractions, chainEventHandlers };\n","import type { FocusManager } from '@react-aria/focus';\nimport type { KeyboardEvent, ReactElement, ReactNode } from 'react';\nimport type { MenuItemProps } from './MenuItem';\n\nimport { useFocusManager } from '@react-aria/focus';\nimport { cx } from 'classix';\nimport {\n\tChildren,\n\tcloneElement,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { useVirtual } from 'react-virtual';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport styles from './styles/Menu.module.css';\nimport {\n\tchainEventHandlers,\n\tcreateItemId,\n\tgetNodeForIndex,\n\thandleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n\tchildren: ReactNode;\n\tonSelect?: (item: T) => void;\n\t/**\n\t * Menus items are rendered using react-virtual for\n\t * additional rendering performance.\n\t */\n\tenableVirtualization?: boolean;\n\t/**\n\t * Class name to be applied to all MenuItem components\n\t * in the menu.\n\t */\n\tmenuItemClassName?: string;\n\t/**\n\t * Sets the width of the menu. This is especially useful when using virtual items\n\t * since the width cannot be automatically set by the widest element.\n\t */\n\tsize?: 'sm' | 'md' | 'lg' | 'xl';\n\t/**\n\t * Sets the number out of elements rendered outside of the view window\n\t * when using virtualization\n\t */\n\toverscan?: number;\n\t/**\n\t * Sets the height for each menu item when using virtualization.\n\t *\n\t */\n\titemHeight?: number;\n\t'data-test-id'?: string;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\n/**\n * @deprecated use `Menu` or `ListBox` from `@launchpad-ui/components` instead\n *\n * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs\n */\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n\tconst {\n\t\tchildren,\n\t\tmenuItemClassName,\n\t\tonSelect,\n\t\tenableVirtualization,\n\t\titemHeight,\n\t\tsize,\n\t\toverscan = 1,\n\t\t'data-test-id': testId = 'menu',\n\t} = props;\n\n\tconst focusManager = useFocusManager();\n\n\tconst handleArrowDown = useCallback(() => {\n\t\tfocusManager?.focusNext({ wrap: true });\n\t}, [focusManager]);\n\n\tconst handleArrowUp = useCallback(() => {\n\t\tfocusManager?.focusPrevious({ wrap: true });\n\t}, [focusManager]);\n\n\tconst reduceItems = useMemo(() => {\n\t\tconst childrenProps = Children.toArray(children);\n\t\tif (enableVirtualization) {\n\t\t\t// the virtualized menu has its own handlers and props\n\t\t\tlet searchElem = null;\n\t\t\tlet elements: ReactElement[] = [];\n\t\t\tfor (const child of childrenProps as ReactElement[]) {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\tsearchElem = child;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\telements = elements.concat(child);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { items: elements, searchElement: searchElem };\n\t\t}\n\n\t\treturn (childrenProps as ReactElement[]).reduce(\n\t\t\t(\n\t\t\t\t{ items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\tchild: ReactElement<any>,\n\t\t\t) => {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems,\n\t\t\t\t\t\t\tsearchElement: cloneElement(child, {\n\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems: items.concat(\n\t\t\t\t\t\t\t\tchild.props.disabled\n\t\t\t\t\t\t\t\t\t? cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\tonClick: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\t\t\t\t\t\t\tdisabled: true,\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t: cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\titem: child.props.item ?? items.length,\n\t\t\t\t\t\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\t\t\t\t\t\tonClick: chainEventHandlers(child.props.onClick, () => {\n\t\t\t\t\t\t\t\t\t\t\t\tonSelect?.(child.props.item ?? items.length);\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tsearchElement,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\treturn { items: items.concat(child), searchElement };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn { items, searchElement };\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ items: [], searchElement: null },\n\t\t);\n\t}, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n\tif (enableVirtualization) {\n\t\treturn (\n\t\t\t<MenuBase data-test-id={testId} isVirtual size={size}>\n\t\t\t\t<ItemVirtualizer<T>\n\t\t\t\t\titems={Children.toArray(reduceItems.items) as ReactElement[]}\n\t\t\t\t\tsearchElement={reduceItems.searchElement}\n\t\t\t\t\toverscan={overscan}\n\t\t\t\t\tmenuItemClassName={menuItemClassName}\n\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\titemHeight={itemHeight}\n\t\t\t\t\tfocusManager={focusManager}\n\t\t\t\t/>\n\t\t\t</MenuBase>\n\t\t);\n\t}\n\n\treturn (\n\t\t<MenuBase data-test-id={testId} size={size}>\n\t\t\t{reduceItems.searchElement}\n\t\t\t<MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n\t\t</MenuBase>\n\t);\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n\titems: ReactElement[] | null;\n\tsearchElement?: ReactElement | null;\n\tfocusManager?: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n\tconst {\n\t\toverscan,\n\t\tsearchElement,\n\t\titemHeight = 31.5,\n\t\tmenuItemClassName,\n\t\titems,\n\t\tfocusManager,\n\t\tonSelect,\n\t} = props;\n\n\tconst menuId = useRef(`menu-ctrl-${useId()}`);\n\n\tconst focusedItemIndex = useRef<number | null>(null);\n\tconst parentRef = useRef<HTMLDivElement | null>(null);\n\tconst searchRef = useRef<HTMLInputElement | null>(null);\n\n\tconst [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n\tconst hasSearch = !!searchElement;\n\n\tconst lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n\tconst rowVirtualizer = useVirtual({\n\t\tsize: items !== null ? items.length : 0,\n\t\tparentRef,\n\t\testimateSize: useCallback(() => itemHeight, [itemHeight]),\n\t\toverscan,\n\t});\n\n\tconst focusSearchBar = useCallback(() => {\n\t\trowVirtualizer.scrollToIndex(0);\n\t\tsearchRef.current?.focus?.();\n\t}, [rowVirtualizer]);\n\n\t/**\n\t * Scrolls to the menu item with the index provided and\n\t * then manually focuses it using a side effect in useEffect\n\t */\n\tconst focusMenuItem = useCallback(\n\t\t(index: number) => {\n\t\t\trowVirtualizer.scrollToIndex(index);\n\t\t\tsetNextFocusValue(index);\n\t\t},\n\t\t[rowVirtualizer],\n\t);\n\n\tconst handleKeyboardFocusInteraction = useCallback(\n\t\t(direction: 'next' | 'previous') => {\n\t\t\tif (focusedItemIndex.current === null || focusedItemIndex.current === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextIndex =\n\t\t\t\tdirection === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n\t\t\tconst shouldWrap =\n\t\t\t\t(direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n\t\t\t\t(direction === 'previous' && focusedItemIndex.current === 0);\n\t\t\tif (shouldWrap) {\n\t\t\t\t// we are at the end of the list so we will\n\t\t\t\t// scroll back to the beginning of the list\n\t\t\t\tif (hasSearch) {\n\t\t\t\t\tfocusSearchBar();\n\t\t\t\t} else {\n\t\t\t\t\t// if at end, wrap to beginning, else focus last item\n\t\t\t\t\tfocusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tswitch (direction) {\n\t\t\t\tcase 'next':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusNext();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'previous':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusPrevious();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t[focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer],\n\t);\n\n\tconst getItemProps = useCallback(\n\t\t(itemElem: ReactElement, index: number) => {\n\t\t\tconst childProps = itemElem.props as MenuItemProps<T>;\n\t\t\tswitch (itemElem.type) {\n\t\t\t\tcase MenuItem:\n\t\t\t\t\treturn {\n\t\t\t\t\t\tclassName: cx(childProps.className, menuItemClassName),\n\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\tonKeyDown: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\t\t\thandleFocusBackward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t\thandleFocusForward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tonFocus: chainEventHandlers(childProps.onFocus, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = index;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tid: createItemId(index, menuId.current),\n\t\t\t\t\t\tonBlur: chainEventHandlers(childProps.onBlur, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = null;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tonClick: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: chainEventHandlers(childProps.onClick, () => {\n\t\t\t\t\t\t\t\t\tonSelect?.(childProps.item as T);\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t} as MenuItemProps<T>;\n\t\t\t\tdefault:\n\t\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\t[handleKeyboardFocusInteraction, menuItemClassName, onSelect],\n\t);\n\n\tuseEffect(() => {\n\t\tif (nextFocusValue !== null) {\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tconst element = getNodeForIndex(nextFocusValue, menuId.current);\n\t\t\t\telement?.focus();\n\t\t\t});\n\t\t\tsetNextFocusValue(null);\n\t\t}\n\t}, [nextFocusValue]);\n\n\t/**\n\t * Calls handleFocusForward when the user is attempting to focus forward using\n\t * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n\t */\n\tconst handleKeyboardFocusKeydown = (\n\t\te: KeyboardEvent,\n\t\tcallbacks: Record<\n\t\t\t'handleFocusForward' | 'handleFocusBackward',\n\t\t\t(direction: 'next' | 'previous') => void\n\t\t>,\n\t) => {\n\t\tconst keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n\t\tif (keyOps.includes(e.key)) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n\t\t\t\tcallbacks.handleFocusBackward?.('previous');\n\t\t\t} else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n\t\t\t\tcallbacks.handleFocusForward?.('next');\n\t\t\t}\n\t\t}\n\t};\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: ignore\n\tconst renderSearch = useMemo(\n\t\t() =>\n\t\t\tsearchElement\n\t\t\t\t? // biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\t\tcloneElement(searchElement as ReactElement<any>, {\n\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\thandleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n\t\t\t\t\t\t\t\thandleFocusForward: () => focusMenuItem(0),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tref: searchRef,\n\t\t\t\t\t})\n\t\t\t\t: null,\n\t\t[searchElement, lastVirtualItemIndex, focusMenuItem],\n\t);\n\n\tconst renderItems = useMemo(\n\t\t() =>\n\t\t\trowVirtualizer.virtualItems.map((virtualRow) => {\n\t\t\t\tif (!items) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst elem = items[virtualRow.index];\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={virtualRow.index}\n\t\t\t\t\t\tref={virtualRow.measureRef}\n\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\tclassName={styles['VirtualMenu-item']}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\ttransform: `translateY(${virtualRow.start}px)`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{cloneElement(elem, getItemProps(elem, virtualRow.index))}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}),\n\t\t[rowVirtualizer.virtualItems, items, getItemProps],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{renderSearch}\n\t\t\t<MenuItemList ref={parentRef} role=\"presentation\">\n\t\t\t\t<div\n\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\tclassName={styles['VirtualMenu-item-list']}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\theight: `${rowVirtualizer.totalSize}px`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{renderItems}\n\t\t\t\t</div>\n\t\t\t</MenuItemList>\n\t\t</>\n\t);\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Component: ElementType","elements: ReactElement[]"],"sources":["../src/styles/Menu.module.css","../src/MenuBase.tsx","../src/MenuDivider.tsx","../src/MenuItem.tsx","../src/MenuItemList.tsx","../src/MenuSearch.tsx","../src/utils.ts","../src/Menu.tsx"],"sourcesContent":[".Menu-item {\n\tbackground-color: transparent;\n\tborder-radius: var(--lp-border-radius-regular);\n\tborder-width: var(--lp-border-width-100);\n\tcolor: var(--lp-color-text-ui-primary-base);\n\tcursor: pointer;\n\tdisplay: block;\n\tfont: var(--lp-text-label-1-medium);\n\toutline: none;\n\toverflow: hidden;\n\tpadding-inline: var(--lp-spacing-300);\n\tpadding-block: var(--lp-spacing-200);\n\tposition: relative;\n\ttext-align: left;\n\ttext-decoration: none;\n\ttext-overflow: ellipsis;\n\tuser-select: none;\n\twhite-space: nowrap;\n\twidth: 100%;\n}\n\n.Menu-item-list {\n\tmax-height: 55vh;\n\tmin-width: 7.5rem;\n\toverflow: auto;\n\tpadding: var(--lp-spacing-200);\n}\n\n.Menu .Menu-item:not([disabled]):not([aria-disabled]):not(.Menu-item--header) {\n\t&:active {\n\t\ttext-decoration: none;\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-active);\n\t}\n\n\t&:hover:not(:active):not(.has-focus) {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t}\n\n\t&.has-focus {\n\t\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n\t\tbox-shadow: inset 0 0 0 2px var(--lp-color-shadow-interactive-focus);\n\t}\n}\n\n.Menu {\n\tbackground: var(--lp-color-bg-overlay-secondary);\n\tborder-radius: var(--lp-border-radius-medium);\n\tfont-family: var(--lp-font-family-base);\n\n\t&:focus {\n\t\toutline: none;\n\t}\n\n\t/* Override our link styles for link component */\n\t& a.Menu-item {\n\t\t&:focus:not(:hover):not(.has-focus) {\n\t\t\ttext-decoration: none;\n\t\t\tbox-shadow: none;\n\t\t}\n\n\t\t/* Ensures that links that are disabled don't show active styles */\n\t\t&:active[disabled],\n\t\t&:active[aria-disabled] {\n\t\t\ttext-decoration: none;\n\t\t\tcolor: var(--lp-color-text-interactive-disabled);\n\t\t}\n\t}\n}\n\n.Menu-item--nested {\n\tpadding-left: 2.5rem;\n}\n\n.Menu-item--header {\n\tfont: var(--lp-text-small-1-regular);\n\tcolor: var(--lp-color-text-ui-tertiary);\n}\n\n.Menu-item-icon {\n\tmargin-right: var(--lp-spacing-300);\n}\n\n.Menu-item :global(.Gravatar) {\n\tmargin-right: 0.3125rem;\n}\n\n.Menu-item.is-highlighted {\n\tbackground-color: var(--lp-color-bg-interactive-secondary-hover);\n}\n\n.Menu-item[aria-disabled],\n.Menu-item[disabled] {\n\tcolor: var(--lp-color-text-interactive-disabled);\n\tcursor: not-allowed;\n}\n\n.Menu-divider {\n\tborder-top: 1px solid var(--lp-color-border-ui-secondary);\n\tmargin: var(--lp-spacing-200) 0;\n}\n\n.Menu-search {\n\tborder-bottom: 1px solid var(--lp-color-border-ui-secondary);\n\tpadding: var(--lp-spacing-300);\n}\n\n[class*='_Popover-content'] .Menu-search {\n\twidth: 100%;\n\n\t/* Removing anything that could give it some height */\n\t& .Menu-search-hidden-placeholder {\n\t\tpadding-top: 0;\n\t\tpadding-bottom: 0;\n\t\theight: 0;\n\t\tborder: none;\n\t\tvisibility: hidden;\n\t}\n}\n\n.Menu--isVirtual {\n\tdisplay: flex;\n\talign-items: stretch;\n\tflex-direction: column;\n}\n\n.MenuSize--xl {\n\twidth: 20rem;\n}\n\n.MenuSize--lg {\n\twidth: 15rem;\n}\n\n.MenuSize--md {\n\twidth: 10rem;\n}\n\n.MenuSize--sm {\n\twidth: 7.5rem;\n}\n\n.VirtualMenu-item-list {\n\twidth: 100%;\n\tposition: relative;\n}\n\n.VirtualMenu-item {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n}\n","import type { ComponentPropsWithRef } from 'react';\nimport type { MenuProps } from './Menu';\n\nimport { cx } from 'classix';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuBaseProps = ComponentPropsWithRef<'div'> & {\n\tisVirtual?: boolean;\n\tsize?: MenuProps<string>['size'];\n};\n\nconst MenuBase = forwardRef<HTMLDivElement, MenuBaseProps>(\n\t({ children, size, isVirtual, ...props }, ref) => {\n\t\tconst classes = cx(\n\t\t\tstyles.Menu,\n\t\t\tisVirtual && styles['Menu--isVirtual'],\n\t\t\tsize && styles[`MenuSize--${size}`],\n\t\t);\n\n\t\treturn (\n\t\t\t<div {...props} role=\"menu\" className={classes} ref={ref}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t},\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n","import type { RefObject } from 'react';\n\nimport { type SeparatorProps, useSeparator } from 'react-aria/useSeparator';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuDividerProps = SeparatorProps & {\n\tinnerRef?: RefObject<HTMLDivElement>;\n\t'data-test-id'?: string;\n};\n\nconst MenuDivider = ({\n\telementType = 'div',\n\torientation,\n\tinnerRef,\n\t'data-test-id': testId = 'menu-divider',\n}: MenuDividerProps) => {\n\tconst { separatorProps } = useSeparator({\n\t\torientation,\n\t\telementType,\n\t});\n\n\treturn (\n\t\t<div\n\t\t\t{...separatorProps}\n\t\t\tdata-test-id={testId}\n\t\t\tref={innerRef}\n\t\t\tclassName={styles['Menu-divider']}\n\t\t/>\n\t);\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n","import type { IconProps } from '@launchpad-ui/icons';\nimport type { PopoverPlacement } from '@launchpad-ui/popover';\nimport type { ComponentPropsWithRef, ElementType, JSX, PropsWithRef, ReactElement } from 'react';\n\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cx } from 'classix';\nimport { cloneElement } from 'react';\nimport { FocusRing } from 'react-aria/FocusRing';\n\nimport styles from './styles/Menu.module.css';\n\n// Merge two types and get rid of overlapping definitions\ntype Merge<T, U> = Omit<T, keyof U> & U;\n\ntype PropsWithComponent<P, T extends ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends ElementType> = Merge<\n\tT extends keyof JSX.IntrinsicElements\n\t\t? PropsWithRef<JSX.IntrinsicElements[T]>\n\t\t: ComponentPropsWithRef<T>,\n\tPropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n\tisHighlighted?: boolean;\n\ticon?: ReactElement<IconProps>;\n\tdisabled?: boolean;\n\tnested?: boolean;\n\tgroupHeader?: boolean;\n\ttooltip?: string | ReactElement;\n\ttooltipOptions?: ComponentPropsWithRef<typeof Tooltip>;\n\ttooltipPlacement?: PopoverPlacement;\n\tasChild?: boolean;\n\t'data-test-id'?: string;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<P, T extends ElementType = typeof defaultElement> = PolymorphicPropsWithRef<\n\t| (MenuItemOwnProps & {\n\t\t\titem: P; // Infer the type if it is included\n\t })\n\t| (MenuItemOwnProps & {\n\t\t\titem?: undefined;\n\t }),\n\tT\n>;\n\nconst MenuItem = <P, T extends ElementType = typeof defaultElement>({\n\t...props\n}: MenuItemProps<P, T>) => {\n\tconst {\n\t\t// TODO: remove component prop once we migrate over to asChild format\n\t\tcomponent,\n\t\tchildren,\n\t\tisHighlighted,\n\t\ticon,\n\t\tnested,\n\t\tgroupHeader,\n\t\t// biome-ignore lint/correctness/noUnusedVariables: ignore\n\t\titem,\n\t\tdisabled,\n\t\tclassName,\n\t\ttooltip,\n\t\trole = 'menuitem',\n\t\ttooltipPlacement,\n\t\tonKeyDown,\n\t\ttooltipOptions,\n\t\tasChild,\n\t\t'data-test-id': testId = 'menu-item',\n\t\t...rest\n\t} = props;\n\n\tconst Component: ElementType = component || (asChild ? Slot : defaultElement);\n\n\tconst renderIcon = icon && cloneElement(icon, { size: 'small' });\n\n\tconst renderedItem = (\n\t\t<FocusRing focusRingClass={styles['has-focus']}>\n\t\t\t<Component\n\t\t\t\t{...rest}\n\t\t\t\tdisabled={disabled}\n\t\t\t\taria-disabled={disabled ? disabled : undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\tstyles['Menu-item'],\n\t\t\t\t\tclassName,\n\t\t\t\t\tisHighlighted && styles['is-highlighted'],\n\t\t\t\t\tnested && styles['Menu-item--nested'],\n\t\t\t\t\tgroupHeader && styles['Menu-item--header'],\n\t\t\t\t)}\n\t\t\t\tdata-test-id={testId}\n\t\t\t\trole={role}\n\t\t\t\tonKeyDown={onKeyDown}\n\t\t\t>\n\t\t\t\t{asChild ? (\n\t\t\t\t\tchildren\n\t\t\t\t) : (\n\t\t\t\t\t<>\n\t\t\t\t\t\t{icon && <span className={styles['Menu-item-icon']}>{renderIcon}</span>}\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Component>\n\t\t</FocusRing>\n\t);\n\n\tif (tooltip) {\n\t\treturn (\n\t\t\t<Tooltip\n\t\t\t\tcontent={tooltip}\n\t\t\t\trootElementStyle={{ display: 'block' }}\n\t\t\t\tallowBoundaryElementOverflow\n\t\t\t\tplacement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n\t\t\t\t{...(tooltipOptions || {})}\n\t\t\t>\n\t\t\t\t{renderedItem}\n\t\t\t</Tooltip>\n\t\t);\n\t}\n\n\treturn renderedItem;\n};\n\nexport { MenuItem };\nexport type { MenuItemProps };\n","import type { ComponentPropsWithRef } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuItemListProps = Omit<ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n\t<div {...rest} ref={ref} data-test-id=\"menu-item-list\" className={styles['Menu-item-list']}>\n\t\t{children}\n\t</div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n","import type { ChangeEvent } from 'react';\n\nimport { TextField } from '@launchpad-ui/form';\nimport { forwardRef } from 'react';\n\nimport styles from './styles/Menu.module.css';\n\ntype MenuSearchProps = {\n\tariaLabel?: string;\n\tvalue?: string;\n\tid?: string;\n\tplaceholder?: string;\n\tonChange?(event: ChangeEvent<HTMLInputElement>): void;\n\t'data-test-id'?: string;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n\tconst {\n\t\tariaLabel,\n\t\tplaceholder,\n\t\tid,\n\t\t'data-test-id': testId = 'menu-search',\n\t\t...finalProps\n\t} = props;\n\n\treturn (\n\t\t<div className={styles['Menu-search']}>\n\t\t\t<TextField\n\t\t\t\t{...finalProps}\n\t\t\t\tref={ref}\n\t\t\t\tclassName={styles['Menu-search-input']}\n\t\t\t\ttiny\n\t\t\t\tid={id}\n\t\t\t\ttype=\"search\"\n\t\t\t\tdata-test-id={testId}\n\t\t\t\tautoComplete=\"off\"\n\t\t\t\tplaceholder={placeholder}\n\t\t\t\taria-label={ariaLabel || 'Search'}\n\t\t\t/>\n\t\t</div>\n\t);\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n","import type { EventHandler, KeyboardEvent, SyntheticEvent } from 'react';\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n\tindex === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst handleKeyboardInteractions = (\n\tevent: KeyboardEvent,\n\tkeyHandlers: Partial<\n\t\tRecord<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n\t>,\n) => {\n\tconst ops = {\n\t\tArrowUp: keyHandlers.handleUp,\n\t\tArrowDown: keyHandlers.handleDown,\n\t\tEnter: keyHandlers.handleEnter,\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: ignore\n\t} as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n\tif (ops[event.key]) {\n\t\tevent.preventDefault();\n\t\tops[event.key]?.call(globalThis, event);\n\t}\n};\n\nconst chainEventHandlers =\n\t(...handlers: (EventHandler<SyntheticEvent> | undefined)[]) =>\n\t(event: SyntheticEvent) => {\n\t\tfor (const h of handlers) {\n\t\t\ttypeof h === 'function' && h(event);\n\t\t}\n\t};\n\nexport { createItemId, getNodeForIndex, handleKeyboardInteractions, chainEventHandlers };\n","import type { KeyboardEvent, ReactElement, ReactNode } from 'react';\nimport type { MenuItemProps } from './MenuItem';\n\nimport { cx } from 'classix';\nimport {\n\tChildren,\n\tcloneElement,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { type FocusManager, useFocusManager } from 'react-aria/FocusScope';\nimport { useVirtual } from 'react-virtual';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport styles from './styles/Menu.module.css';\nimport {\n\tchainEventHandlers,\n\tcreateItemId,\n\tgetNodeForIndex,\n\thandleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n\tchildren: ReactNode;\n\tonSelect?: (item: T) => void;\n\t/**\n\t * Menus items are rendered using react-virtual for\n\t * additional rendering performance.\n\t */\n\tenableVirtualization?: boolean;\n\t/**\n\t * Class name to be applied to all MenuItem components\n\t * in the menu.\n\t */\n\tmenuItemClassName?: string;\n\t/**\n\t * Sets the width of the menu. This is especially useful when using virtual items\n\t * since the width cannot be automatically set by the widest element.\n\t */\n\tsize?: 'sm' | 'md' | 'lg' | 'xl';\n\t/**\n\t * Sets the number out of elements rendered outside of the view window\n\t * when using virtualization\n\t */\n\toverscan?: number;\n\t/**\n\t * Sets the height for each menu item when using virtualization.\n\t *\n\t */\n\titemHeight?: number;\n\t'data-test-id'?: string;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\n/**\n * @deprecated use `Menu` or `ListBox` from `@launchpad-ui/components` instead\n *\n * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs\n */\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n\tconst {\n\t\tchildren,\n\t\tmenuItemClassName,\n\t\tonSelect,\n\t\tenableVirtualization,\n\t\titemHeight,\n\t\tsize,\n\t\toverscan = 1,\n\t\t'data-test-id': testId = 'menu',\n\t} = props;\n\n\tconst focusManager = useFocusManager();\n\n\tconst handleArrowDown = useCallback(() => {\n\t\tfocusManager?.focusNext({ wrap: true });\n\t}, [focusManager]);\n\n\tconst handleArrowUp = useCallback(() => {\n\t\tfocusManager?.focusPrevious({ wrap: true });\n\t}, [focusManager]);\n\n\tconst reduceItems = useMemo(() => {\n\t\tconst childrenProps = Children.toArray(children);\n\t\tif (enableVirtualization) {\n\t\t\t// the virtualized menu has its own handlers and props\n\t\t\tlet searchElem = null;\n\t\t\tlet elements: ReactElement[] = [];\n\t\t\tfor (const child of childrenProps as ReactElement[]) {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\tsearchElem = child;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\telements = elements.concat(child);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { items: elements, searchElement: searchElem };\n\t\t}\n\n\t\treturn (childrenProps as ReactElement[]).reduce(\n\t\t\t(\n\t\t\t\t{ items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\tchild: ReactElement<any>,\n\t\t\t) => {\n\t\t\t\tswitch (child.type) {\n\t\t\t\t\tcase MenuSearch:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems,\n\t\t\t\t\t\t\tsearchElement: cloneElement(child, {\n\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuItem:\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\titems: items.concat(\n\t\t\t\t\t\t\t\tchild.props.disabled\n\t\t\t\t\t\t\t\t\t? cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\tonClick: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: () => undefined,\n\t\t\t\t\t\t\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\t\t\t\t\t\t\tdisabled: true,\n\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t: cloneElement(child, {\n\t\t\t\t\t\t\t\t\t\t\tclassName: cx(child.props.className, menuItemClassName),\n\t\t\t\t\t\t\t\t\t\t\titem: child.props.item ?? items.length,\n\t\t\t\t\t\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\t\t\t\t\t\tonClick: chainEventHandlers(child.props.onClick, () => {\n\t\t\t\t\t\t\t\t\t\t\t\tonSelect?.(child.props.item ?? items.length);\n\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\t\t\t\thandleKeyboardInteractions(e, {\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleDown: handleArrowDown,\n\t\t\t\t\t\t\t\t\t\t\t\t\thandleUp: handleArrowUp,\n\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tsearchElement,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase MenuDivider:\n\t\t\t\t\t\treturn { items: items.concat(child), searchElement };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn { items, searchElement };\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ items: [], searchElement: null },\n\t\t);\n\t}, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n\tif (enableVirtualization) {\n\t\treturn (\n\t\t\t<MenuBase data-test-id={testId} isVirtual size={size}>\n\t\t\t\t<ItemVirtualizer<T>\n\t\t\t\t\titems={Children.toArray(reduceItems.items) as ReactElement[]}\n\t\t\t\t\tsearchElement={reduceItems.searchElement}\n\t\t\t\t\toverscan={overscan}\n\t\t\t\t\tmenuItemClassName={menuItemClassName}\n\t\t\t\t\tonSelect={onSelect}\n\t\t\t\t\titemHeight={itemHeight}\n\t\t\t\t\tfocusManager={focusManager}\n\t\t\t\t/>\n\t\t\t</MenuBase>\n\t\t);\n\t}\n\n\treturn (\n\t\t<MenuBase data-test-id={testId} size={size}>\n\t\t\t{reduceItems.searchElement}\n\t\t\t<MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n\t\t</MenuBase>\n\t);\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n\titems: ReactElement[] | null;\n\tsearchElement?: ReactElement | null;\n\tfocusManager?: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n\tconst {\n\t\toverscan,\n\t\tsearchElement,\n\t\titemHeight = 31.5,\n\t\tmenuItemClassName,\n\t\titems,\n\t\tfocusManager,\n\t\tonSelect,\n\t} = props;\n\n\tconst menuId = useRef(`menu-ctrl-${useId()}`);\n\n\tconst focusedItemIndex = useRef<number | null>(null);\n\tconst parentRef = useRef<HTMLDivElement | null>(null);\n\tconst searchRef = useRef<HTMLInputElement | null>(null);\n\n\tconst [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n\tconst hasSearch = !!searchElement;\n\n\tconst lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n\tconst rowVirtualizer = useVirtual({\n\t\tsize: items !== null ? items.length : 0,\n\t\tparentRef,\n\t\testimateSize: useCallback(() => itemHeight, [itemHeight]),\n\t\toverscan,\n\t});\n\n\tconst focusSearchBar = useCallback(() => {\n\t\trowVirtualizer.scrollToIndex(0);\n\t\tsearchRef.current?.focus?.();\n\t}, [rowVirtualizer]);\n\n\t/**\n\t * Scrolls to the menu item with the index provided and\n\t * then manually focuses it using a side effect in useEffect\n\t */\n\tconst focusMenuItem = useCallback(\n\t\t(index: number) => {\n\t\t\trowVirtualizer.scrollToIndex(index);\n\t\t\tsetNextFocusValue(index);\n\t\t},\n\t\t[rowVirtualizer],\n\t);\n\n\tconst handleKeyboardFocusInteraction = useCallback(\n\t\t(direction: 'next' | 'previous') => {\n\t\t\tif (focusedItemIndex.current === null || focusedItemIndex.current === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nextIndex =\n\t\t\t\tdirection === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n\t\t\tconst shouldWrap =\n\t\t\t\t(direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n\t\t\t\t(direction === 'previous' && focusedItemIndex.current === 0);\n\t\t\tif (shouldWrap) {\n\t\t\t\t// we are at the end of the list so we will\n\t\t\t\t// scroll back to the beginning of the list\n\t\t\t\tif (hasSearch) {\n\t\t\t\t\tfocusSearchBar();\n\t\t\t\t} else {\n\t\t\t\t\t// if at end, wrap to beginning, else focus last item\n\t\t\t\t\tfocusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tswitch (direction) {\n\t\t\t\tcase 'next':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusNext();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'previous':\n\t\t\t\t\trowVirtualizer.scrollToIndex(nextIndex);\n\t\t\t\t\tfocusManager?.focusPrevious();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\t[focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer],\n\t);\n\n\tconst getItemProps = useCallback(\n\t\t(itemElem: ReactElement, index: number) => {\n\t\t\tconst childProps = itemElem.props as MenuItemProps<T>;\n\t\t\tswitch (itemElem.type) {\n\t\t\t\tcase MenuItem:\n\t\t\t\t\treturn {\n\t\t\t\t\t\tclassName: cx(childProps.className, menuItemClassName),\n\t\t\t\t\t\t// set focus on the first menu item if there is no search input, and set in the tab order\n\t\t\t\t\t\tonKeyDown: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\t\t\thandleFocusBackward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t\thandleFocusForward: handleKeyboardFocusInteraction,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tonFocus: chainEventHandlers(childProps.onFocus, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = index;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tid: createItemId(index, menuId.current),\n\t\t\t\t\t\tonBlur: chainEventHandlers(childProps.onBlur, () => {\n\t\t\t\t\t\t\tfocusedItemIndex.current = null;\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tonClick: childProps.disabled\n\t\t\t\t\t\t\t? () => undefined\n\t\t\t\t\t\t\t: chainEventHandlers(childProps.onClick, () => {\n\t\t\t\t\t\t\t\t\tonSelect?.(childProps.item as T);\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t} as MenuItemProps<T>;\n\t\t\t\tdefault:\n\t\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\t\t[handleKeyboardFocusInteraction, menuItemClassName, onSelect],\n\t);\n\n\tuseEffect(() => {\n\t\tif (nextFocusValue !== null) {\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tconst element = getNodeForIndex(nextFocusValue, menuId.current);\n\t\t\t\telement?.focus();\n\t\t\t});\n\t\t\tsetNextFocusValue(null);\n\t\t}\n\t}, [nextFocusValue]);\n\n\t/**\n\t * Calls handleFocusForward when the user is attempting to focus forward using\n\t * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n\t */\n\tconst handleKeyboardFocusKeydown = (\n\t\te: KeyboardEvent,\n\t\tcallbacks: Record<\n\t\t\t'handleFocusForward' | 'handleFocusBackward',\n\t\t\t(direction: 'next' | 'previous') => void\n\t\t>,\n\t) => {\n\t\tconst keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n\t\tif (keyOps.includes(e.key)) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n\t\t\t\tcallbacks.handleFocusBackward?.('previous');\n\t\t\t} else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n\t\t\t\tcallbacks.handleFocusForward?.('next');\n\t\t\t}\n\t\t}\n\t};\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: ignore\n\tconst renderSearch = useMemo(\n\t\t() =>\n\t\t\tsearchElement\n\t\t\t\t? // biome-ignore lint/suspicious/noExplicitAny: ignore\n\t\t\t\t\tcloneElement(searchElement as ReactElement<any>, {\n\t\t\t\t\t\tonKeyDown: (e: KeyboardEvent) =>\n\t\t\t\t\t\t\thandleKeyboardFocusKeydown(e, {\n\t\t\t\t\t\t\t\thandleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n\t\t\t\t\t\t\t\thandleFocusForward: () => focusMenuItem(0),\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tref: searchRef,\n\t\t\t\t\t})\n\t\t\t\t: null,\n\t\t[searchElement, lastVirtualItemIndex, focusMenuItem],\n\t);\n\n\tconst renderItems = useMemo(\n\t\t() =>\n\t\t\trowVirtualizer.virtualItems.map((virtualRow) => {\n\t\t\t\tif (!items) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tconst elem = items[virtualRow.index];\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={virtualRow.index}\n\t\t\t\t\t\tref={virtualRow.measureRef}\n\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\tclassName={styles['VirtualMenu-item']}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\ttransform: `translateY(${virtualRow.start}px)`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{cloneElement(elem, getItemProps(elem, virtualRow.index))}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}),\n\t\t[rowVirtualizer.virtualItems, items, getItemProps],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{renderSearch}\n\t\t\t<MenuItemList ref={parentRef} role=\"presentation\">\n\t\t\t\t<div\n\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\tclassName={styles['VirtualMenu-item-list']}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\theight: `${rowVirtualizer.totalSize}px`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{renderItems}\n\t\t\t\t</div>\n\t\t\t</MenuItemList>\n\t\t</>\n\t);\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n"],"mappings":"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"}
package/dist/style.css CHANGED
@@ -1,2 +1,2 @@
1
- .C73R2W_Menu-item{border-radius:var(--lp-border-radius-regular);border-width:var(--lp-border-width-100);color:var(--lp-color-text-ui-primary-base);cursor:pointer;font:var(--lp-text-label-1-medium);padding-inline:var(--lp-spacing-300);padding-block:var(--lp-spacing-200);text-align:left;text-overflow:ellipsis;-webkit-user-select:none;user-select:none;white-space:nowrap;background-color:#0000;outline:none;width:100%;text-decoration:none;display:block;position:relative;overflow:hidden}.C73R2W_Menu-item-list{min-width:7.5rem;max-height:55vh;padding:var(--lp-spacing-200);overflow:auto}.C73R2W_Menu .C73R2W_Menu-item:not([disabled]):not([aria-disabled]):not(.C73R2W_Menu-item--header):active{background-color:var(--lp-color-bg-interactive-secondary-active);text-decoration:none}.C73R2W_Menu .C73R2W_Menu-item:not([disabled]):not([aria-disabled]):not(.C73R2W_Menu-item--header):hover:not(:active):not(.C73R2W_has-focus){background-color:var(--lp-color-bg-interactive-secondary-hover)}.C73R2W_Menu .C73R2W_Menu-item:not([disabled]):not([aria-disabled]):not(.C73R2W_Menu-item--header).C73R2W_has-focus{background-color:var(--lp-color-bg-interactive-secondary-hover);box-shadow:inset 0 0 0 2px var(--lp-color-shadow-interactive-focus)}.C73R2W_Menu{background:var(--lp-color-bg-overlay-secondary);border-radius:var(--lp-border-radius-medium);font-family:var(--lp-font-family-base)}.C73R2W_Menu:focus{outline:none}.C73R2W_Menu a.C73R2W_Menu-item:focus:not(:hover):not(.C73R2W_has-focus){box-shadow:none;text-decoration:none}.C73R2W_Menu a.C73R2W_Menu-item:active[disabled],.C73R2W_Menu a.C73R2W_Menu-item:active[aria-disabled]{color:var(--lp-color-text-interactive-disabled);text-decoration:none}.C73R2W_Menu-item--nested{padding-left:2.5rem}.C73R2W_Menu-item--header{font:var(--lp-text-small-1-regular);color:var(--lp-color-text-ui-tertiary)}.C73R2W_Menu-item-icon{margin-right:var(--lp-spacing-300)}.C73R2W_Menu-item .Gravatar{margin-right:.3125rem}.C73R2W_Menu-item.C73R2W_is-highlighted{background-color:var(--lp-color-bg-interactive-secondary-hover)}.C73R2W_Menu-item[aria-disabled],.C73R2W_Menu-item[disabled]{color:var(--lp-color-text-interactive-disabled);cursor:not-allowed}.C73R2W_Menu-divider{border-top:1px solid var(--lp-color-border-ui-secondary);margin:var(--lp-spacing-200)0}.C73R2W_Menu-search{border-bottom:1px solid var(--lp-color-border-ui-secondary);padding:var(--lp-spacing-300)}[class*=_Popover-content] .C73R2W_Menu-search{width:100%}[class*=_Popover-content] .C73R2W_Menu-search .C73R2W_Menu-search-hidden-placeholder{visibility:hidden;border:none;height:0;padding-top:0;padding-bottom:0}.C73R2W_Menu--isVirtual{flex-direction:column;align-items:stretch;display:flex}.C73R2W_MenuSize--xl{width:20rem}.C73R2W_MenuSize--lg{width:15rem}.C73R2W_MenuSize--md{width:10rem}.C73R2W_MenuSize--sm{width:7.5rem}.C73R2W_VirtualMenu-item-list{width:100%;position:relative}.C73R2W_VirtualMenu-item{width:100%;position:absolute;top:0;left:0}
1
+ .C73R2W_Menu-item{border-radius:var(--lp-border-radius-regular);border-width:var(--lp-border-width-100);color:var(--lp-color-text-ui-primary-base);cursor:pointer;font:var(--lp-text-label-1-medium);padding-inline:var(--lp-spacing-300);padding-block:var(--lp-spacing-200);text-align:left;text-overflow:ellipsis;-webkit-user-select:none;user-select:none;white-space:nowrap;background-color:#0000;outline:none;width:100%;text-decoration:none;display:block;position:relative;overflow:hidden}.C73R2W_Menu-item-list{min-width:7.5rem;max-height:55vh;padding:var(--lp-spacing-200);overflow:auto}.C73R2W_Menu .C73R2W_Menu-item:not([disabled]):not([aria-disabled]):not(.C73R2W_Menu-item--header):active{background-color:var(--lp-color-bg-interactive-secondary-active);text-decoration:none}.C73R2W_Menu .C73R2W_Menu-item:not([disabled]):not([aria-disabled]):not(.C73R2W_Menu-item--header):hover:not(:active):not(.C73R2W_has-focus){background-color:var(--lp-color-bg-interactive-secondary-hover)}.C73R2W_Menu .C73R2W_Menu-item:not([disabled]):not([aria-disabled]):not(.C73R2W_Menu-item--header).C73R2W_has-focus{background-color:var(--lp-color-bg-interactive-secondary-hover);box-shadow:inset 0 0 0 2px var(--lp-color-shadow-interactive-focus)}.C73R2W_Menu{background:var(--lp-color-bg-overlay-secondary);border-radius:var(--lp-border-radius-medium);font-family:var(--lp-font-family-base)}.C73R2W_Menu:focus{outline:none}.C73R2W_Menu a.C73R2W_Menu-item:focus:not(:hover):not(.C73R2W_has-focus){box-shadow:none;text-decoration:none}.C73R2W_Menu a.C73R2W_Menu-item:active[disabled],.C73R2W_Menu a.C73R2W_Menu-item:active[aria-disabled]{color:var(--lp-color-text-interactive-disabled);text-decoration:none}.C73R2W_Menu-item--nested{padding-left:2.5rem}.C73R2W_Menu-item--header{font:var(--lp-text-small-1-regular);color:var(--lp-color-text-ui-tertiary)}.C73R2W_Menu-item-icon{margin-right:var(--lp-spacing-300)}.C73R2W_Menu-item .Gravatar{margin-right:.3125rem}.C73R2W_Menu-item.C73R2W_is-highlighted{background-color:var(--lp-color-bg-interactive-secondary-hover)}.C73R2W_Menu-item[aria-disabled],.C73R2W_Menu-item[disabled]{color:var(--lp-color-text-interactive-disabled);cursor:not-allowed}.C73R2W_Menu-divider{border-top:1px solid var(--lp-color-border-ui-secondary);margin:var(--lp-spacing-200) 0}.C73R2W_Menu-search{border-bottom:1px solid var(--lp-color-border-ui-secondary);padding:var(--lp-spacing-300)}[class*=_Popover-content] .C73R2W_Menu-search{width:100%}[class*=_Popover-content] .C73R2W_Menu-search .C73R2W_Menu-search-hidden-placeholder{visibility:hidden;border:none;height:0;padding-top:0;padding-bottom:0}.C73R2W_Menu--isVirtual{flex-direction:column;align-items:stretch;display:flex}.C73R2W_MenuSize--xl{width:20rem}.C73R2W_MenuSize--lg{width:15rem}.C73R2W_MenuSize--md{width:10rem}.C73R2W_MenuSize--sm{width:7.5rem}.C73R2W_VirtualMenu-item-list{width:100%;position:relative}.C73R2W_VirtualMenu-item{width:100%;position:absolute;top:0;left:0}
2
2
  /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchpad-ui/menu",
3
- "version": "0.16.14",
3
+ "version": "0.16.15",
4
4
  "description": "An element that presents a list of items a user can choose from.",
5
5
  "repository": "launchdarkly/launchpad-ui",
6
6
  "license": "Apache-2.0",
@@ -20,23 +20,22 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "@radix-ui/react-slot": "1.2.0",
23
- "@react-aria/focus": "3.21.2",
24
- "@react-aria/separator": "3.4.13",
25
23
  "classix": "2.2.0",
24
+ "react-aria": "3.48.0",
26
25
  "react-virtual": "2.10.4",
27
- "@launchpad-ui/form": "~0.15.14",
28
- "@launchpad-ui/icons": "~0.25.5",
29
- "@launchpad-ui/popover": "~0.14.2",
26
+ "@launchpad-ui/form": "~0.15.15",
27
+ "@launchpad-ui/icons": "~0.25.6",
30
28
  "@launchpad-ui/tokens": "~0.15.1",
31
- "@launchpad-ui/tooltip": "~0.12.2"
29
+ "@launchpad-ui/popover": "~0.14.3",
30
+ "@launchpad-ui/tooltip": "~0.12.3"
32
31
  },
33
32
  "devDependencies": {
34
- "react": "19.2.0",
35
- "react-dom": "19.2.0"
33
+ "react": "19.2.6",
34
+ "react-dom": "19.2.6"
36
35
  },
37
36
  "peerDependencies": {
38
- "react": "19.2.0",
39
- "react-dom": "19.2.0"
37
+ "react": "19.2.6",
38
+ "react-dom": "19.2.6"
40
39
  },
41
40
  "exports": {
42
41
  ".": {