@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 +1 -1
- package/dist/Menu.d.ts.map +1 -1
- package/dist/MenuDivider.d.ts +1 -1
- package/dist/MenuDivider.d.ts.map +1 -1
- package/dist/index.es.js +21 -36
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +32 -66
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +10 -11
package/dist/Menu.d.ts
CHANGED
package/dist/Menu.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
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"}
|
package/dist/MenuDivider.d.ts
CHANGED
|
@@ -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,
|
|
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 "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
const { component, children, isHighlighted, icon, nested, groupHeader, item, disabled, className, tooltip, role = "menuitem", tooltipPlacement, onKeyDown, tooltipOptions, asChild, "data-test-id": testId = "menu-item"
|
|
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
|
-
|
|
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
|
-
|
|
95
|
-
const { ariaLabel, placeholder, id, "data-test-id": testId = "menu-search"
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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");
|
package/dist/index.es.js.map
CHANGED
|
@@ -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":"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"}
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
64
|
-
const { separatorProps } = (0,
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
const { component, children, isHighlighted, icon, nested, groupHeader, item, disabled, className, tooltip, role = "menuitem", tooltipPlacement, onKeyDown, tooltipOptions, asChild, "data-test-id": testId = "menu-item"
|
|
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)(
|
|
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
|
-
|
|
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
|
-
|
|
115
|
-
const { ariaLabel, placeholder, id, "data-test-id": testId = "menu-search"
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
28
|
-
"@launchpad-ui/icons": "~0.25.
|
|
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/
|
|
29
|
+
"@launchpad-ui/popover": "~0.14.3",
|
|
30
|
+
"@launchpad-ui/tooltip": "~0.12.3"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
34
|
-
"react": "19.2.
|
|
35
|
-
"react-dom": "19.2.
|
|
33
|
+
"react": "19.2.6",
|
|
34
|
+
"react-dom": "19.2.6"
|
|
36
35
|
},
|
|
37
36
|
"peerDependencies": {
|
|
38
|
-
"react": "19.2.
|
|
39
|
-
"react-dom": "19.2.
|
|
37
|
+
"react": "19.2.6",
|
|
38
|
+
"react-dom": "19.2.6"
|
|
40
39
|
},
|
|
41
40
|
"exports": {
|
|
42
41
|
".": {
|