@launchpad-ui/menu 0.1.0

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/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # @launchpad-ui/menu
2
+
3
+ > An element that presents a list of items a user can choose from.
4
+
5
+ [![See it on NPM!](https://img.shields.io/npm/v/@launchpad-ui/menu?style=for-the-badge)](https://www.npmjs.com/package/@launchpad-ui/menu)
6
+ [![How big is this package in your project?](https://img.shields.io/bundlephobia/minzip/@launchpad-ui/menu?style=for-the-badge)](https://bundlephobia.com/result?p=@launchpad-ui/menu)
7
+
8
+ ## Installation
9
+
10
+ ```sh
11
+ $ yarn add @launchpad-ui/menu
12
+ # or
13
+ $ npm install @launchpad-ui/menu
14
+ ```
package/dist/Menu.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ import type { ReactElement } from 'react';
2
+ import { FocusManager } from '@react-aria/focus';
3
+ declare type ControlledMenuProps<T> = {
4
+ children: React.ReactNode;
5
+ onSelect?: (item: T) => void;
6
+ /**
7
+ * Menus items are rendered using react-virtual for
8
+ * additional rendering performance.
9
+ */
10
+ enableVirtualization?: boolean;
11
+ /**
12
+ * Class name to be applied to all MenuItem and MenuItemLink components
13
+ * in the menu.
14
+ */
15
+ menuItemClassName?: string;
16
+ /**
17
+ * Sets the width of the menu. This is especially useful when using virtual items
18
+ * since the width cannot be automatically set by the widest element.
19
+ */
20
+ menuWidth?: 'tiny' | 'small' | 'med' | 'large' | 'xLarge';
21
+ /**
22
+ * Sets the number out of elements rendered outside of the view window
23
+ * when using virtualization
24
+ */
25
+ overscan?: number;
26
+ /**
27
+ * Sets the height for each menu item when using virtualization.
28
+ *
29
+ */
30
+ itemHeight?: number;
31
+ };
32
+ declare type MenuProps<T extends number | string> = ControlledMenuProps<T>;
33
+ declare const Menu: <T extends string | number>(props: MenuProps<T>) => JSX.Element;
34
+ declare type ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {
35
+ items: ReactElement[] | null;
36
+ searchElement?: React.ReactElement | null;
37
+ focusManager: FocusManager;
38
+ };
39
+ declare const ItemVirtualizer: <T extends string | number>(props: ItemVirtualizerProps<T>) => JSX.Element;
40
+ export { Menu, ItemVirtualizer };
41
+ export type { MenuProps, ItemVirtualizerProps };
42
+ //# sourceMappingURL=Menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../src/Menu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AAmBlE,aAAK,mBAAmB,CAAC,CAAC,IAAI;IAC5B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,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,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC1D;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,aAAK,SAAS,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAEnE,QAAA,MAAM,IAAI,iEA6HT,CAAC;AAEF,aAAK,oBAAoB,CAAC,CAAC,IAAI,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG;IACxE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IAC1C,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,QAAA,MAAM,eAAe,4EAoNpB,CAAC;AAEF,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACjC,YAAY,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import './styles.css';
3
+ declare type MenuBaseProps = React.ComponentPropsWithRef<'div'>;
4
+ declare const MenuBase: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
5
+ export { MenuBase };
6
+ export type { MenuBaseProps };
7
+ //# sourceMappingURL=MenuBase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuBase.d.ts","sourceRoot":"","sources":["../src/MenuBase.tsx"],"names":[],"mappings":";AAGA,OAAO,cAAc,CAAC;AAEtB,aAAK,aAAa,GAAG,KAAK,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAGxD,QAAA,MAAM,QAAQ,2IASb,CAAC;AAIF,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import { SeparatorProps } from '@react-aria/separator';
3
+ import './styles.css';
4
+ declare type MenuDividerProps = SeparatorProps & {
5
+ innerRef?: React.RefObject<HTMLDivElement>;
6
+ };
7
+ declare const MenuDivider: ({ elementType, orientation, innerRef }: MenuDividerProps) => JSX.Element;
8
+ export { MenuDivider };
9
+ export type { MenuDividerProps };
10
+ //# sourceMappingURL=MenuDivider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuDivider.d.ts","sourceRoot":"","sources":["../src/MenuDivider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAErE,OAAO,cAAc,CAAC;AAEtB,aAAK,gBAAgB,GAAG,cAAc,GAAG;IACvC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;CAC5C,CAAC;AAEF,QAAA,MAAM,WAAW,2CAAoD,gBAAgB,gBAOpF,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,47 @@
1
+ /// <reference types="react" />
2
+ import type { PopoverPlacement } from '@launchpad-ui/popover';
3
+ import { Icon } from '@launchpad-ui/icons';
4
+ import { Tooltip } from '@launchpad-ui/tooltip';
5
+ import { Link } from 'react-router-dom';
6
+ import './styles.css';
7
+ declare type Merge<T, U> = Omit<T, keyof U> & U;
8
+ declare type PropsWithComponent<P, T extends React.ElementType> = P & {
9
+ component?: T;
10
+ };
11
+ declare type PolymorphicPropsWithRef<P, T extends React.ElementType> = Merge<T extends keyof JSX.IntrinsicElements ? React.PropsWithRef<JSX.IntrinsicElements[T]> : React.ComponentPropsWithRef<T>, PropsWithComponent<P, T>>;
12
+ declare type MenuItemOwnProps = {
13
+ isHighlighted?: boolean;
14
+ icon?: typeof Icon | null;
15
+ disabled?: boolean;
16
+ nested?: boolean;
17
+ groupHeader?: boolean;
18
+ innerRef?: React.RefObject<HTMLDivElement>;
19
+ tooltip?: string | React.ReactElement;
20
+ tooltipOptions?: typeof Tooltip;
21
+ tooltipPlacement?: PopoverPlacement;
22
+ };
23
+ declare const defaultElement = "button";
24
+ declare type MenuItemProps<P, T extends React.ElementType = typeof defaultElement> = PolymorphicPropsWithRef<(MenuItemOwnProps & {
25
+ item: P;
26
+ }) | (MenuItemOwnProps & {
27
+ item?: undefined;
28
+ }), T>;
29
+ declare const MenuItem: <P, T extends import("react").ElementType<any> = "button">({ ...props }: MenuItemProps<P, T>) => JSX.Element;
30
+ declare type MenuItemLinkOwnProps = {
31
+ disabled?: boolean;
32
+ useHistory?: boolean;
33
+ newTab?: boolean;
34
+ };
35
+ declare type MenuItemLinkProps<P, T extends React.ElementType = typeof Link> = Merge<Omit<MenuItemProps<P, T>, 'component' | 'item'>, MenuItemLinkOwnProps> & ({
36
+ item?: undefined;
37
+ } | {
38
+ item: P;
39
+ });
40
+ declare const MenuItemLink: <P, T extends import("react").ElementType<any> = typeof Link>({ to, disabled, useHistory, newTab, children, ...props }: Omit<Omit<MenuItemProps<P, T>, "item" | "component">, keyof MenuItemLinkOwnProps> & MenuItemLinkOwnProps & ({
41
+ item?: undefined;
42
+ } | {
43
+ item: P;
44
+ })) => JSX.Element;
45
+ export { MenuItem, MenuItemLink };
46
+ export type { MenuItemProps, MenuItemLinkProps };
47
+ //# sourceMappingURL=MenuItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuItem.d.ts","sourceRoot":"","sources":["../src/MenuItem.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,IAAI,EAAY,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGhD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,OAAO,cAAc,CAAC;AAGtB,aAAK,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;AAExC,aAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,CAAC,WAAW,IAAI,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEhF,aAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,CAAC,WAAW,IAAI,KAAK,CAClE,CAAC,SAAS,MAAM,GAAG,CAAC,iBAAiB,GACjC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAC5C,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAClC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CACzB,CAAC;AAEF,aAAK,gBAAgB,GAAG;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,OAAO,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC;IACtC,cAAc,CAAC,EAAE,OAAO,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,CAAC;AAEF,QAAA,MAAM,cAAc,WAAW,CAAC;AAEhC,aAAK,aAAa,CAChB,CAAC,EACD,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,OAAO,cAAc,IACjD,uBAAuB,CACvB,CAAC,gBAAgB,GAAG;IAClB,IAAI,EAAE,CAAC,CAAC;CACT,CAAC,GACF,CAAC,gBAAgB,GAAG;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,CAAC,EACJ,CAAC,CACF,CAAC;AAEF,QAAA,MAAM,QAAQ,8GAkEb,CAAC;AAEF,aAAK,oBAAoB,GAAG;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,aAAK,iBAAiB,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,OAAO,IAAI,IAC/D,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,EAAE,oBAAoB,CAAC,GAC1E,CACI;IACE,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,GACD;IACE,IAAI,EAAE,CAAC,CAAC;CACT,CACJ,CAAC;AAIR,QAAA,MAAM,YAAY;WATC,SAAS;;;kBA8B3B,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AAClC,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import './styles.css';
3
+ declare type MenuItemListProps = Omit<React.ComponentPropsWithRef<'div'>, 'className'>;
4
+ declare const MenuItemList: import("react").ForwardRefExoticComponent<Pick<MenuItemListProps, "key" | "id" | "color" | "translate" | "hidden" | "dir" | "slot" | "style" | "title" | "accessKey" | "draggable" | "lang" | "prefix" | "children" | "contentEditable" | "inputMode" | "tabIndex" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "contextMenu" | "placeholder" | "spellCheck" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture"> & import("react").RefAttributes<HTMLDivElement>>;
5
+ export { MenuItemList };
6
+ export type { MenuItemListProps };
7
+ //# sourceMappingURL=MenuItemList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuItemList.d.ts","sourceRoot":"","sources":["../src/MenuItemList.tsx"],"names":[],"mappings":";AAEA,OAAO,cAAc,CAAC;AAEtB,aAAK,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC;AAE/E,QAAA,MAAM,YAAY,4lJAIhB,CAAC;AAIH,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ChangeEvent } from 'react';
2
+ import './styles.css';
3
+ declare type MenuSearchProps = {
4
+ ariaLabel?: string;
5
+ value?: string;
6
+ placeholder?: string;
7
+ onChange?(event: ChangeEvent<HTMLInputElement>): void;
8
+ };
9
+ declare const MenuSearch: import("react").ForwardRefExoticComponent<MenuSearchProps & import("react").RefAttributes<HTMLInputElement>>;
10
+ export { MenuSearch };
11
+ export type { MenuSearchProps };
12
+ //# sourceMappingURL=MenuSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuSearch.d.ts","sourceRoot":"","sources":["../src/MenuSearch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAIzC,OAAO,cAAc,CAAC;AAEtB,aAAK,eAAe,GAAG;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;CACvD,CAAC;AAEF,QAAA,MAAM,UAAU,8GAsBd,CAAC;AAIH,OAAO,EAAE,UAAU,EAAE,CAAC;AACtB,YAAY,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ export type { MenuBaseProps } from './MenuBase';
2
+ export type { MenuDividerProps } from './MenuDivider';
3
+ export type { MenuItemProps, MenuItemLinkProps } from './MenuItem';
4
+ export type { MenuItemListProps } from './MenuItemList';
5
+ export type { MenuSearchProps } from './MenuSearch';
6
+ export type { MenuProps } from './Menu';
7
+ export { MenuBase } from './MenuBase';
8
+ export { MenuDivider } from './MenuDivider';
9
+ export { MenuItem, MenuItemLink } from './MenuItem';
10
+ export { MenuItemList } from './MenuItemList';
11
+ export { MenuSearch } from './MenuSearch';
12
+ export { Menu } from './Menu';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACnE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,418 @@
1
+ // ../../scripts/react-shim.js
2
+ import * as React from "react";
3
+
4
+ // src/MenuBase.tsx
5
+ import cx from "clsx";
6
+ import { forwardRef } from "react";
7
+ import "./styles.css";
8
+ var MenuBase = forwardRef(({ children, ...props }, ref) => {
9
+ const className = cx("Menu", props.className);
10
+ return /* @__PURE__ */ React.createElement("div", {
11
+ ...props,
12
+ className,
13
+ ref
14
+ }, children);
15
+ });
16
+ MenuBase.displayName = "MenuBase";
17
+
18
+ // src/MenuDivider.tsx
19
+ import { useSeparator } from "@react-aria/separator";
20
+ import "./styles.css";
21
+ var MenuDivider = ({ elementType = "div", orientation, innerRef }) => {
22
+ const { separatorProps } = useSeparator({
23
+ orientation,
24
+ elementType
25
+ });
26
+ return /* @__PURE__ */ React.createElement("div", {
27
+ ...separatorProps,
28
+ ref: innerRef,
29
+ className: "Menu-divider"
30
+ });
31
+ };
32
+
33
+ // src/MenuItem.tsx
34
+ import { IconSize } from "@launchpad-ui/icons";
35
+ import { Tooltip } from "@launchpad-ui/tooltip";
36
+ import { FocusRing } from "@react-aria/focus";
37
+ import cx2 from "clsx";
38
+ import { Link } from "react-router-dom";
39
+ import "./styles.css";
40
+ var defaultElement = "button";
41
+ var MenuItem = ({
42
+ ...props
43
+ }) => {
44
+ const {
45
+ component,
46
+ children,
47
+ isHighlighted,
48
+ icon: Icon2,
49
+ nested,
50
+ groupHeader,
51
+ item,
52
+ disabled,
53
+ className,
54
+ innerRef,
55
+ tooltip,
56
+ role = "menuitem",
57
+ tooltipPlacement,
58
+ onKeyDown,
59
+ tooltipOptions,
60
+ ...rest
61
+ } = props;
62
+ const Component = component || defaultElement;
63
+ const renderedItem = /* @__PURE__ */ React.createElement(FocusRing, {
64
+ focusRingClass: "has-focus"
65
+ }, /* @__PURE__ */ React.createElement(Component, {
66
+ ...rest,
67
+ ref: innerRef,
68
+ disabled,
69
+ "aria-disabled": disabled ? disabled : void 0,
70
+ className: cx2("Menu-item", className, { "is-highlighted": isHighlighted }, { "Menu-item--nested": nested }, { "u-fw-medium": groupHeader }),
71
+ role,
72
+ onKeyDown
73
+ }, Icon2 && /* @__PURE__ */ React.createElement("span", {
74
+ className: "Menu-item-icon"
75
+ }, /* @__PURE__ */ React.createElement(Icon2, {
76
+ size: IconSize.SMALL
77
+ })), children));
78
+ if (tooltip) {
79
+ return /* @__PURE__ */ React.createElement(Tooltip, {
80
+ content: tooltip,
81
+ rootElementStyle: { display: "block" },
82
+ allowBoundaryElementOverflow: true,
83
+ placement: tooltipPlacement ? tooltipPlacement : "bottom",
84
+ ...tooltipOptions || {}
85
+ }, renderedItem);
86
+ }
87
+ return renderedItem;
88
+ };
89
+ var MenuItemLink = ({
90
+ to,
91
+ disabled = false,
92
+ useHistory = true,
93
+ newTab = false,
94
+ children,
95
+ ...props
96
+ }) => {
97
+ const finalProps = {
98
+ ...props,
99
+ disabled,
100
+ component: useHistory ? Link : "a",
101
+ [useHistory ? "to" : "href"]: disabled ? "" : to,
102
+ rel: newTab ? "noopener noreferrer" : void 0,
103
+ target: newTab ? "_blank" : void 0
104
+ };
105
+ return /* @__PURE__ */ React.createElement(MenuItem, {
106
+ ...finalProps
107
+ }, children);
108
+ };
109
+
110
+ // src/MenuItemList.tsx
111
+ import { forwardRef as forwardRef2 } from "react";
112
+ import "./styles.css";
113
+ var MenuItemList = forwardRef2(({ children, ...rest }, ref) => /* @__PURE__ */ React.createElement("div", {
114
+ ...rest,
115
+ ref,
116
+ "data-test-id": "menu-item-list",
117
+ className: "Menu-item-list"
118
+ }, children));
119
+ MenuItemList.displayName = "MenuItemList";
120
+
121
+ // src/MenuSearch.tsx
122
+ import { forwardRef as forwardRef3 } from "react";
123
+ import "./styles.css";
124
+ var MenuSearch = forwardRef3((props, ref) => {
125
+ const { ariaLabel, placeholder, ...finalProps } = props;
126
+ return /* @__PURE__ */ React.createElement("div", {
127
+ className: "Menu-search"
128
+ }, /* @__PURE__ */ React.createElement("input", {
129
+ ...finalProps,
130
+ ref,
131
+ className: "Menu-search-input FormInput FormInput--tiny",
132
+ type: "search",
133
+ autoComplete: "off",
134
+ placeholder,
135
+ "aria-label": ariaLabel || "Search"
136
+ }), /* @__PURE__ */ React.createElement("div", {
137
+ className: "Menu-search-hidden-placeholder Menu-search-input FormInput FormInput--tiny",
138
+ "aria-hidden": "true"
139
+ }, placeholder));
140
+ });
141
+ MenuSearch.displayName = "MenuSearch";
142
+
143
+ // src/Menu.tsx
144
+ import { useFocusManager } from "@react-aria/focus";
145
+ import cx3 from "clsx";
146
+ import { isNil, noop } from "lodash-es";
147
+ import { Children, cloneElement, useCallback, useEffect, useMemo, useRef, useState } from "react";
148
+ import { useVirtual } from "react-virtual";
149
+ import { v4 } from "uuid";
150
+
151
+ // src/utils.ts
152
+ import { isFunction } from "lodash-es";
153
+ var createItemId = (index, id) => `${id}-item-${index}`;
154
+ var getNodeForIndex = (index, menuId) => index === null ? index : document.getElementById(createItemId(index, menuId));
155
+ var handleKeyboardInteractions = (event, keyHandlers) => {
156
+ const ops = {
157
+ ArrowUp: keyHandlers.handleUp,
158
+ ArrowDown: keyHandlers.handleDown,
159
+ Enter: keyHandlers.handleEnter
160
+ };
161
+ if (ops[event.key]) {
162
+ event.preventDefault();
163
+ ops[event.key]?.call(void 0, event);
164
+ }
165
+ };
166
+ var chainEventHandlers = (...handlers) => (event) => {
167
+ handlers.forEach((h) => isFunction(h) && h(event));
168
+ };
169
+
170
+ // src/Menu.tsx
171
+ var Menu = (props) => {
172
+ const {
173
+ children,
174
+ menuItemClassName,
175
+ onSelect,
176
+ enableVirtualization,
177
+ itemHeight,
178
+ menuWidth,
179
+ overscan = 1
180
+ } = props;
181
+ const focusManager = useFocusManager();
182
+ const handleArrowDown = useCallback(() => {
183
+ focusManager.focusNext({ wrap: true });
184
+ }, [focusManager]);
185
+ const handleArrowUp = useCallback(() => {
186
+ focusManager.focusPrevious({ wrap: true });
187
+ }, [focusManager]);
188
+ const reduceItems = useMemo(() => {
189
+ const childrenProps = Children.toArray(children);
190
+ if (enableVirtualization) {
191
+ let searchElem = null;
192
+ let elements = [];
193
+ childrenProps.forEach((child) => {
194
+ switch (child.type) {
195
+ case MenuSearch:
196
+ searchElem = child;
197
+ break;
198
+ case MenuItem:
199
+ case MenuItemLink:
200
+ case MenuDivider:
201
+ elements = elements.concat(child);
202
+ break;
203
+ default:
204
+ break;
205
+ }
206
+ });
207
+ return { items: elements, searchElement: searchElem };
208
+ }
209
+ return childrenProps.reduce(({ items, searchElement }, child) => {
210
+ switch (child.type) {
211
+ case MenuSearch:
212
+ return {
213
+ items,
214
+ searchElement: cloneElement(child, {
215
+ onKeyDown: (e) => handleKeyboardInteractions(e, {
216
+ handleDown: handleArrowDown,
217
+ handleUp: handleArrowUp
218
+ })
219
+ })
220
+ };
221
+ case MenuItem:
222
+ case MenuItemLink:
223
+ return {
224
+ items: items.concat(child.props.disabled ? cloneElement(child, {
225
+ onClick: noop,
226
+ onKeyDown: noop,
227
+ tabIndex: -1,
228
+ disabled: true
229
+ }) : cloneElement(child, {
230
+ className: cx3(child.props.className, menuItemClassName),
231
+ item: child.props.item ?? items.length,
232
+ onClick: chainEventHandlers(child.props.onClick, () => {
233
+ onSelect?.(child.props.item ?? items.length);
234
+ }),
235
+ onKeyDown: (e) => handleKeyboardInteractions(e, {
236
+ handleDown: handleArrowDown,
237
+ handleUp: handleArrowUp
238
+ })
239
+ })),
240
+ searchElement
241
+ };
242
+ case MenuDivider:
243
+ return { items: items.concat(child), searchElement };
244
+ default:
245
+ return { items, searchElement };
246
+ }
247
+ }, { items: [], searchElement: null });
248
+ }, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);
249
+ const menuClassName = cx3({ "Menu--isVirtual": enableVirtualization }, { [`MenuSize--${menuWidth}`]: menuWidth });
250
+ if (enableVirtualization) {
251
+ return /* @__PURE__ */ React.createElement(MenuBase, {
252
+ role: "menu",
253
+ className: menuClassName
254
+ }, /* @__PURE__ */ React.createElement(ItemVirtualizer, {
255
+ items: Children.toArray(reduceItems.items),
256
+ searchElement: reduceItems.searchElement,
257
+ overscan,
258
+ menuItemClassName,
259
+ onSelect,
260
+ itemHeight,
261
+ focusManager
262
+ }));
263
+ }
264
+ return /* @__PURE__ */ React.createElement(MenuBase, {
265
+ role: "menu",
266
+ className: menuClassName
267
+ }, reduceItems.searchElement, /* @__PURE__ */ React.createElement(MenuItemList, {
268
+ role: "presentation"
269
+ }, reduceItems.items));
270
+ };
271
+ var ItemVirtualizer = (props) => {
272
+ const {
273
+ overscan,
274
+ searchElement,
275
+ itemHeight = 33,
276
+ menuItemClassName,
277
+ items,
278
+ focusManager,
279
+ onSelect
280
+ } = props;
281
+ const menuId = useRef(`menu-ctrl-${v4()}`);
282
+ const focusedItemIndex = useRef(null);
283
+ const parentRef = useRef(null);
284
+ const searchRef = useRef();
285
+ const [nextFocusValue, setNextFocusValue] = useState(null);
286
+ const hasSearch = !!searchElement;
287
+ const lastVirtualItemIndex = items ? items.length - 1 : 0;
288
+ const rowVirtualizer = useVirtual({
289
+ size: items !== null ? items.length : 0,
290
+ parentRef,
291
+ estimateSize: useCallback(() => itemHeight, [itemHeight]),
292
+ overscan
293
+ });
294
+ const focusSearchBar = useCallback(() => {
295
+ rowVirtualizer.scrollToIndex(0);
296
+ searchRef.current?.focus?.();
297
+ }, [rowVirtualizer]);
298
+ const focusMenuItem = useCallback((index) => {
299
+ rowVirtualizer.scrollToIndex(index);
300
+ setNextFocusValue(index);
301
+ }, [rowVirtualizer]);
302
+ const handleKeyboardFocusInteraction = useCallback((direction) => {
303
+ if (isNil(focusedItemIndex.current)) {
304
+ return;
305
+ }
306
+ const nextIndex = direction === "next" ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;
307
+ const shouldWrap = direction === "next" && focusedItemIndex.current === lastVirtualItemIndex || direction === "previous" && focusedItemIndex.current === 0;
308
+ if (shouldWrap) {
309
+ if (hasSearch) {
310
+ focusSearchBar();
311
+ } else {
312
+ focusMenuItem(direction === "next" ? 0 : lastVirtualItemIndex);
313
+ }
314
+ return;
315
+ }
316
+ switch (direction) {
317
+ case "next":
318
+ rowVirtualizer.scrollToIndex(nextIndex);
319
+ focusManager.focusNext();
320
+ break;
321
+ case "previous":
322
+ rowVirtualizer.scrollToIndex(nextIndex);
323
+ focusManager.focusPrevious();
324
+ break;
325
+ default:
326
+ break;
327
+ }
328
+ }, [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]);
329
+ const getItemProps = useCallback((itemElem, index) => {
330
+ const childProps = itemElem.props;
331
+ switch (itemElem.type) {
332
+ case MenuItem:
333
+ case MenuItemLink:
334
+ return {
335
+ className: cx3(childProps.className, menuItemClassName),
336
+ onKeyDown: childProps.disabled ? noop : (e) => handleKeyboardFocusKeydown(e, {
337
+ handleFocusBackward: handleKeyboardFocusInteraction,
338
+ handleFocusForward: handleKeyboardFocusInteraction
339
+ }),
340
+ onFocus: chainEventHandlers(childProps.onFocus, () => {
341
+ focusedItemIndex.current = index;
342
+ }),
343
+ id: createItemId(index, menuId.current),
344
+ onBlur: chainEventHandlers(childProps.onBlur, () => {
345
+ focusedItemIndex.current = null;
346
+ }),
347
+ onClick: childProps.disabled ? noop : chainEventHandlers(childProps.onClick, () => {
348
+ onSelect?.(childProps.item);
349
+ })
350
+ };
351
+ default:
352
+ return {};
353
+ }
354
+ }, [handleKeyboardFocusInteraction, menuItemClassName, onSelect]);
355
+ useEffect(() => {
356
+ if (nextFocusValue !== null) {
357
+ requestAnimationFrame(() => {
358
+ const element = getNodeForIndex(nextFocusValue, menuId.current);
359
+ element?.focus();
360
+ });
361
+ setNextFocusValue(null);
362
+ }
363
+ }, [nextFocusValue]);
364
+ const handleKeyboardFocusKeydown = (e, callbacks) => {
365
+ const keyOps = ["Tab", "ArrowUp", "ArrowDown"];
366
+ if (keyOps.includes(e.key)) {
367
+ e.preventDefault();
368
+ e.stopPropagation();
369
+ if (e.key === "Tab" && e.shiftKey || e.key === "ArrowUp") {
370
+ callbacks.handleFocusBackward?.("previous");
371
+ } else if (e.key === "ArrowDown" || e.key === "Tab") {
372
+ callbacks.handleFocusForward?.("next");
373
+ }
374
+ }
375
+ };
376
+ const renderSearch = useMemo(() => searchElement ? cloneElement(searchElement, {
377
+ onKeyDown: (e) => handleKeyboardFocusKeydown(e, {
378
+ handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),
379
+ handleFocusForward: () => focusMenuItem(0)
380
+ }),
381
+ ref: searchRef
382
+ }) : null, [searchElement, lastVirtualItemIndex, focusMenuItem]);
383
+ const renderItems = useMemo(() => rowVirtualizer.virtualItems.map((virtualRow) => {
384
+ if (!items) {
385
+ return null;
386
+ }
387
+ const elem = items[virtualRow.index];
388
+ return /* @__PURE__ */ React.createElement("div", {
389
+ key: virtualRow.index,
390
+ ref: elem.type !== MenuItem || elem.type !== MenuItemLink ? virtualRow.measureRef : void 0,
391
+ role: "presentation",
392
+ className: cx3("VirtualMenu-item"),
393
+ style: {
394
+ transform: `translateY(${virtualRow.start}px)`
395
+ }
396
+ }, cloneElement(elem, getItemProps(elem, virtualRow.index)));
397
+ }), [rowVirtualizer.virtualItems, items, getItemProps]);
398
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, renderSearch, /* @__PURE__ */ React.createElement(MenuItemList, {
399
+ ref: parentRef,
400
+ role: "presentation"
401
+ }, /* @__PURE__ */ React.createElement("div", {
402
+ role: "presentation",
403
+ className: "VirtualMenu-item-list",
404
+ style: {
405
+ height: `${rowVirtualizer.totalSize}px`
406
+ }
407
+ }, renderItems)));
408
+ };
409
+ export {
410
+ Menu,
411
+ MenuBase,
412
+ MenuDivider,
413
+ MenuItem,
414
+ MenuItemLink,
415
+ MenuItemList,
416
+ MenuSearch
417
+ };
418
+ //# sourceMappingURL=index.es.js.map