@launchpad-ui/menu 0.1.0 → 0.2.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/dist/MenuBase.d.ts +1 -1
- package/dist/MenuBase.d.ts.map +1 -1
- package/dist/MenuDivider.d.ts +1 -1
- package/dist/MenuDivider.d.ts.map +1 -1
- package/dist/MenuItem.d.ts +1 -1
- package/dist/MenuItem.d.ts.map +1 -1
- package/dist/MenuItemList.d.ts +1 -1
- package/dist/MenuItemList.d.ts.map +1 -1
- package/dist/MenuSearch.d.ts +1 -1
- package/dist/MenuSearch.d.ts.map +1 -1
- package/dist/index.es.js +5 -5
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +2 -2
- package/dist/{styles.css → styles/Menu.css} +1 -1
- package/dist/styles/Menu.css.map +1 -0
- package/package.json +7 -7
- package/dist/styles.css.map +0 -1
package/dist/MenuBase.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/// <reference types="react" />
|
2
|
-
import './styles.css';
|
2
|
+
import './styles/Menu.css';
|
3
3
|
declare type MenuBaseProps = React.ComponentPropsWithRef<'div'>;
|
4
4
|
declare const MenuBase: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
5
5
|
export { MenuBase };
|
package/dist/MenuBase.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"MenuBase.d.ts","sourceRoot":"","sources":["../src/MenuBase.tsx"],"names":[],"mappings":";AAGA,OAAO,
|
1
|
+
{"version":3,"file":"MenuBase.d.ts","sourceRoot":"","sources":["../src/MenuBase.tsx"],"names":[],"mappings":";AAGA,OAAO,mBAAmB,CAAC;AAE3B,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"}
|
package/dist/MenuDivider.d.ts
CHANGED
@@ -1 +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,
|
1
|
+
{"version":3,"file":"MenuDivider.d.ts","sourceRoot":"","sources":["../src/MenuDivider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAErE,OAAO,mBAAmB,CAAC;AAE3B,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"}
|
package/dist/MenuItem.d.ts
CHANGED
@@ -3,7 +3,7 @@ import type { PopoverPlacement } from '@launchpad-ui/popover';
|
|
3
3
|
import { Icon } from '@launchpad-ui/icons';
|
4
4
|
import { Tooltip } from '@launchpad-ui/tooltip';
|
5
5
|
import { Link } from 'react-router-dom';
|
6
|
-
import './styles.css';
|
6
|
+
import './styles/Menu.css';
|
7
7
|
declare type Merge<T, U> = Omit<T, keyof U> & U;
|
8
8
|
declare type PropsWithComponent<P, T extends React.ElementType> = P & {
|
9
9
|
component?: T;
|
package/dist/MenuItem.d.ts.map
CHANGED
@@ -1 +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,
|
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,mBAAmB,CAAC;AAG3B,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"}
|
package/dist/MenuItemList.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/// <reference types="react" />
|
2
|
-
import './styles.css';
|
2
|
+
import './styles/Menu.css';
|
3
3
|
declare type MenuItemListProps = Omit<React.ComponentPropsWithRef<'div'>, 'className'>;
|
4
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
5
|
export { MenuItemList };
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"MenuItemList.d.ts","sourceRoot":"","sources":["../src/MenuItemList.tsx"],"names":[],"mappings":";AAEA,OAAO,
|
1
|
+
{"version":3,"file":"MenuItemList.d.ts","sourceRoot":"","sources":["../src/MenuItemList.tsx"],"names":[],"mappings":";AAEA,OAAO,mBAAmB,CAAC;AAE3B,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"}
|
package/dist/MenuSearch.d.ts
CHANGED
package/dist/MenuSearch.d.ts.map
CHANGED
@@ -1 +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,
|
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,mBAAmB,CAAC;AAE3B,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"}
|
package/dist/index.es.js
CHANGED
@@ -4,7 +4,7 @@ import * as React from "react";
|
|
4
4
|
// src/MenuBase.tsx
|
5
5
|
import cx from "clsx";
|
6
6
|
import { forwardRef } from "react";
|
7
|
-
import "./styles.css";
|
7
|
+
import "./styles/Menu.css";
|
8
8
|
var MenuBase = forwardRef(({ children, ...props }, ref) => {
|
9
9
|
const className = cx("Menu", props.className);
|
10
10
|
return /* @__PURE__ */ React.createElement("div", {
|
@@ -17,7 +17,7 @@ MenuBase.displayName = "MenuBase";
|
|
17
17
|
|
18
18
|
// src/MenuDivider.tsx
|
19
19
|
import { useSeparator } from "@react-aria/separator";
|
20
|
-
import "./styles.css";
|
20
|
+
import "./styles/Menu.css";
|
21
21
|
var MenuDivider = ({ elementType = "div", orientation, innerRef }) => {
|
22
22
|
const { separatorProps } = useSeparator({
|
23
23
|
orientation,
|
@@ -36,7 +36,7 @@ import { Tooltip } from "@launchpad-ui/tooltip";
|
|
36
36
|
import { FocusRing } from "@react-aria/focus";
|
37
37
|
import cx2 from "clsx";
|
38
38
|
import { Link } from "react-router-dom";
|
39
|
-
import "./styles.css";
|
39
|
+
import "./styles/Menu.css";
|
40
40
|
var defaultElement = "button";
|
41
41
|
var MenuItem = ({
|
42
42
|
...props
|
@@ -109,7 +109,7 @@ var MenuItemLink = ({
|
|
109
109
|
|
110
110
|
// src/MenuItemList.tsx
|
111
111
|
import { forwardRef as forwardRef2 } from "react";
|
112
|
-
import "./styles.css";
|
112
|
+
import "./styles/Menu.css";
|
113
113
|
var MenuItemList = forwardRef2(({ children, ...rest }, ref) => /* @__PURE__ */ React.createElement("div", {
|
114
114
|
...rest,
|
115
115
|
ref,
|
@@ -120,7 +120,7 @@ MenuItemList.displayName = "MenuItemList";
|
|
120
120
|
|
121
121
|
// src/MenuSearch.tsx
|
122
122
|
import { forwardRef as forwardRef3 } from "react";
|
123
|
-
import "./styles.css";
|
123
|
+
import "./styles/Menu.css";
|
124
124
|
var MenuSearch = forwardRef3((props, ref) => {
|
125
125
|
const { ariaLabel, placeholder, ...finalProps } = props;
|
126
126
|
return /* @__PURE__ */ React.createElement("div", {
|
package/dist/index.es.js.map
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../../../scripts/react-shim.js", "../src/MenuBase.tsx", "../src/MenuDivider.tsx", "../src/MenuItem.tsx", "../src/MenuItemList.tsx", "../src/MenuSearch.tsx", "../src/Menu.tsx", "../src/utils.ts"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import cx from 'clsx';\nimport { forwardRef } from 'react';\n\nimport './styles.css';\n\ntype MenuBaseProps = React.ComponentPropsWithRef<'div'>;\n\n// This is the pure presentational component that contains menu items\nconst MenuBase = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, ...props }, ref) => {\n const className = cx('Menu', props.className);\n return (\n <div {...props} className={className} ref={ref}>\n {children}\n </div>\n );\n }\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n", "import { SeparatorProps, useSeparator } from '@react-aria/separator';\n\nimport './styles.css';\n\ntype MenuDividerProps = SeparatorProps & {\n innerRef?: React.RefObject<HTMLDivElement>;\n};\n\nconst MenuDivider = ({ elementType = 'div', orientation, innerRef }: MenuDividerProps) => {\n const { separatorProps } = useSeparator({\n orientation,\n elementType,\n });\n\n return <div {...separatorProps} ref={innerRef} className=\"Menu-divider\" />;\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n", "import type { PopoverPlacement } from '@launchpad-ui/popover';\n\nimport { Icon, IconSize } from '@launchpad-ui/icons';\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { FocusRing } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { Link } from 'react-router-dom';\n\nimport './styles.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 React.ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends React.ElementType> = Merge<\n T extends keyof JSX.IntrinsicElements\n ? React.PropsWithRef<JSX.IntrinsicElements[T]>\n : React.ComponentPropsWithRef<T>,\n PropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n isHighlighted?: boolean;\n icon?: typeof Icon | null;\n disabled?: boolean;\n nested?: boolean;\n groupHeader?: boolean;\n innerRef?: React.RefObject<HTMLDivElement>;\n tooltip?: string | React.ReactElement;\n tooltipOptions?: typeof Tooltip;\n tooltipPlacement?: PopoverPlacement;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<\n P,\n T extends React.ElementType = typeof defaultElement\n> = PolymorphicPropsWithRef<\n | (MenuItemOwnProps & {\n item: P; // Infer the type if it is included\n })\n | (MenuItemOwnProps & {\n item?: undefined;\n }),\n T\n>;\n\nconst MenuItem = <P, T extends React.ElementType = typeof defaultElement>({\n ...props\n}: MenuItemProps<P, T>) => {\n const {\n component,\n children,\n isHighlighted,\n icon: Icon,\n nested,\n groupHeader,\n item,\n disabled,\n className,\n innerRef,\n tooltip,\n role = 'menuitem',\n tooltipPlacement,\n onKeyDown,\n tooltipOptions,\n ...rest\n } = props;\n\n const Component: React.ElementType = component || defaultElement;\n\n const renderedItem = (\n <FocusRing focusRingClass=\"has-focus\">\n <Component\n {...rest}\n ref={innerRef}\n disabled={disabled}\n aria-disabled={disabled ? disabled : undefined}\n className={cx(\n 'Menu-item',\n className,\n { 'is-highlighted': isHighlighted },\n { 'Menu-item--nested': nested },\n { 'u-fw-medium': groupHeader }\n )}\n role={role}\n onKeyDown={onKeyDown}\n >\n {Icon && (\n <span className=\"Menu-item-icon\">\n <Icon size={IconSize.SMALL} />\n </span>\n )}\n {children}\n </Component>\n </FocusRing>\n );\n\n if (tooltip) {\n return (\n <Tooltip\n content={tooltip}\n rootElementStyle={{ display: 'block' }}\n allowBoundaryElementOverflow\n placement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n {...(tooltipOptions || {})}\n >\n {renderedItem}\n </Tooltip>\n );\n }\n\n return renderedItem;\n};\n\ntype MenuItemLinkOwnProps = {\n disabled?: boolean;\n useHistory?: boolean;\n newTab?: boolean;\n};\n\ntype MenuItemLinkProps<P, T extends React.ElementType = typeof Link> =\n | Merge<Omit<MenuItemProps<P, T>, 'component' | 'item'>, MenuItemLinkOwnProps> &\n (\n | {\n item?: undefined;\n }\n | {\n item: P;\n }\n );\n\n// By default, this is a Link component whenever useHistory is\n// explicitly not false\nconst MenuItemLink = <P, T extends React.ElementType = typeof Link>({\n to,\n disabled = false,\n useHistory = true,\n newTab = false,\n children,\n ...props\n}: MenuItemLinkProps<P, T>) => {\n const finalProps = {\n ...props,\n disabled,\n component: useHistory ? Link : ('a' as const),\n [useHistory ? 'to' : 'href']: disabled ? '' : to,\n rel: newTab ? 'noopener noreferrer' : undefined,\n target: newTab ? '_blank' : undefined,\n };\n\n // Ideally if this item is disabled, it should be a button rather\n // than a link https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md\n\n return <MenuItem {...finalProps}>{children}</MenuItem>;\n};\n\nexport { MenuItem, MenuItemLink };\nexport type { MenuItemProps, MenuItemLinkProps };\n", "import { forwardRef } from 'react';\n\nimport './styles.css';\n\ntype MenuItemListProps = Omit<React.ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n <div {...rest} ref={ref} data-test-id=\"menu-item-list\" className=\"Menu-item-list\">\n {children}\n </div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n", "import type { ChangeEvent } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport './styles.css';\n\ntype MenuSearchProps = {\n ariaLabel?: string;\n value?: string;\n placeholder?: string;\n onChange?(event: ChangeEvent<HTMLInputElement>): void;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n const { ariaLabel, placeholder, ...finalProps } = props;\n\n return (\n <div className=\"Menu-search\">\n <input\n {...finalProps}\n ref={ref}\n className=\"Menu-search-input FormInput FormInput--tiny\"\n type=\"search\"\n autoComplete=\"off\"\n placeholder={placeholder}\n aria-label={ariaLabel || 'Search'}\n />\n <div\n className=\"Menu-search-hidden-placeholder Menu-search-input FormInput FormInput--tiny\"\n aria-hidden=\"true\"\n >\n {placeholder}\n </div>\n </div>\n );\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n", "import type { KeyboardEvent, ReactElement } from 'react';\n\nimport { FocusManager, useFocusManager } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { isNil, noop } from 'lodash-es';\nimport { Children, cloneElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useVirtual } from 'react-virtual';\nimport { v4 } from 'uuid';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem, MenuItemLink, MenuItemProps } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport {\n chainEventHandlers,\n createItemId,\n getNodeForIndex,\n handleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n children: React.ReactNode;\n onSelect?: (item: T) => void;\n /**\n * Menus items are rendered using react-virtual for\n * additional rendering performance.\n */\n enableVirtualization?: boolean;\n /**\n * Class name to be applied to all MenuItem and MenuItemLink components\n * in the menu.\n */\n menuItemClassName?: string;\n /**\n * Sets the width of the menu. This is especially useful when using virtual items\n * since the width cannot be automatically set by the widest element.\n */\n menuWidth?: 'tiny' | 'small' | 'med' | 'large' | 'xLarge';\n /**\n * Sets the number out of elements rendered outside of the view window\n * when using virtualization\n */\n overscan?: number;\n /**\n * Sets the height for each menu item when using virtualization.\n *\n */\n itemHeight?: number;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n const {\n children,\n menuItemClassName,\n onSelect,\n enableVirtualization,\n itemHeight,\n menuWidth,\n overscan = 1,\n } = props;\n\n const focusManager = useFocusManager();\n\n const handleArrowDown = useCallback(() => {\n focusManager.focusNext({ wrap: true });\n }, [focusManager]);\n\n const handleArrowUp = useCallback(() => {\n focusManager.focusPrevious({ wrap: true });\n }, [focusManager]);\n\n const reduceItems = useMemo(() => {\n const childrenProps = Children.toArray(children);\n if (enableVirtualization) {\n // the virtualized menu has its own handlers and props\n let searchElem = null;\n let elements: ReactElement[] = [];\n (childrenProps as ReactElement[]).forEach((child: ReactElement) => {\n switch (child.type) {\n case MenuSearch:\n searchElem = child;\n break;\n case MenuItem:\n case MenuItemLink:\n case MenuDivider:\n elements = elements.concat(child);\n break;\n default:\n break;\n }\n });\n return { items: elements, searchElement: searchElem };\n }\n\n return (childrenProps as ReactElement[]).reduce(\n (\n { items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n child\n ) => {\n switch (child.type) {\n case MenuSearch:\n return {\n items,\n searchElement: cloneElement(child, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n }),\n };\n case MenuItem:\n case MenuItemLink:\n return {\n items: items.concat(\n child.props.disabled\n ? cloneElement(child, {\n onClick: noop,\n onKeyDown: noop,\n tabIndex: -1,\n disabled: true,\n })\n : cloneElement(child, {\n className: cx(child.props.className, menuItemClassName),\n item: child.props.item ?? items.length,\n // set focus on the first menu item if there is no search input, and set in the tab order\n onClick: chainEventHandlers(child.props.onClick, () => {\n onSelect?.(child.props.item ?? items.length);\n }),\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n })\n ),\n searchElement,\n };\n case MenuDivider:\n return { items: items.concat(child), searchElement };\n default:\n return { items, searchElement };\n }\n },\n { items: [], searchElement: null }\n );\n }, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n const menuClassName = cx(\n { 'Menu--isVirtual': enableVirtualization },\n { [`MenuSize--${menuWidth}`]: menuWidth }\n );\n\n if (enableVirtualization) {\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n <ItemVirtualizer<T>\n items={Children.toArray(reduceItems.items) as ReactElement[]}\n searchElement={reduceItems.searchElement}\n overscan={overscan}\n menuItemClassName={menuItemClassName}\n onSelect={onSelect}\n itemHeight={itemHeight}\n focusManager={focusManager}\n />\n </MenuBase>\n );\n }\n\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n {reduceItems.searchElement}\n <MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n </MenuBase>\n );\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n items: ReactElement[] | null;\n searchElement?: React.ReactElement | null;\n focusManager: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n const {\n overscan,\n searchElement,\n itemHeight = 33,\n menuItemClassName,\n items: items,\n focusManager,\n onSelect,\n } = props;\n\n const menuId = useRef(`menu-ctrl-${v4()}`);\n\n const focusedItemIndex = useRef<number | null>(null);\n const parentRef = useRef<HTMLDivElement | null>(null);\n const searchRef = useRef<HTMLInputElement>();\n\n const [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n const hasSearch = !!searchElement;\n\n const lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n const rowVirtualizer = useVirtual({\n size: items !== null ? items.length : 0,\n parentRef,\n estimateSize: useCallback(() => itemHeight, [itemHeight]),\n overscan,\n });\n\n const focusSearchBar = useCallback(() => {\n rowVirtualizer.scrollToIndex(0);\n searchRef.current?.focus?.();\n }, [rowVirtualizer]);\n\n /**\n * Scrolls to the menu item with the index provided and\n * then manually focuses it using a side effect in useEffect\n */\n const focusMenuItem = useCallback(\n (index: number) => {\n rowVirtualizer.scrollToIndex(index);\n setNextFocusValue(index);\n },\n [rowVirtualizer]\n );\n\n const handleKeyboardFocusInteraction = useCallback(\n (direction: 'next' | 'previous') => {\n if (isNil(focusedItemIndex.current)) {\n return;\n }\n const nextIndex =\n direction === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n const shouldWrap =\n (direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n (direction === 'previous' && focusedItemIndex.current === 0);\n if (shouldWrap) {\n // we are at the end of the list so we will\n // scroll back to the beginning of the list\n if (hasSearch) {\n focusSearchBar();\n } else {\n // if at end, wrap to beginning, else focus last item\n focusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n }\n return;\n }\n switch (direction) {\n case 'next':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusNext();\n break;\n case 'previous':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusPrevious();\n break;\n default:\n break;\n }\n },\n [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]\n );\n\n const getItemProps = useCallback(\n (itemElem: ReactElement, index: number) => {\n const childProps = itemElem.props as MenuItemProps<T>;\n switch (itemElem.type) {\n case MenuItem:\n case MenuItemLink:\n return {\n className: cx(childProps.className, menuItemClassName),\n // set focus on the first menu item if there is no search input, and set in the tab order\n onKeyDown: childProps.disabled\n ? noop\n : (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: handleKeyboardFocusInteraction,\n handleFocusForward: handleKeyboardFocusInteraction,\n }),\n onFocus: chainEventHandlers(childProps.onFocus, () => {\n focusedItemIndex.current = index;\n }),\n id: createItemId(index, menuId.current),\n onBlur: chainEventHandlers(childProps.onBlur, () => {\n focusedItemIndex.current = null;\n }),\n onClick: childProps.disabled\n ? noop\n : chainEventHandlers(childProps.onClick, () => {\n onSelect?.(childProps.item as T);\n }),\n } as MenuItemProps<T>;\n default:\n return {};\n }\n },\n [handleKeyboardFocusInteraction, menuItemClassName, onSelect]\n );\n\n useEffect(() => {\n if (nextFocusValue !== null) {\n requestAnimationFrame(() => {\n const element = getNodeForIndex(nextFocusValue, menuId.current);\n element?.focus();\n });\n setNextFocusValue(null);\n }\n }, [nextFocusValue]);\n\n /**\n * Calls handleFocusForward when the user is attempting to focus forward using\n * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n */\n const handleKeyboardFocusKeydown = (\n e: KeyboardEvent,\n callbacks: Record<\n 'handleFocusForward' | 'handleFocusBackward',\n (direction: 'next' | 'previous') => void\n >\n ) => {\n const keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n if (keyOps.includes(e.key)) {\n e.preventDefault();\n e.stopPropagation();\n if ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n callbacks.handleFocusBackward?.('previous');\n } else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n callbacks.handleFocusForward?.('next');\n }\n }\n };\n\n const renderSearch = useMemo(\n () =>\n searchElement\n ? cloneElement(searchElement, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n handleFocusForward: () => focusMenuItem(0),\n }),\n ref: searchRef,\n })\n : null,\n [searchElement, lastVirtualItemIndex, focusMenuItem]\n );\n\n const renderItems = useMemo(\n () =>\n rowVirtualizer.virtualItems.map((virtualRow) => {\n if (!items) {\n return null;\n }\n const elem = items[virtualRow.index];\n return (\n <div\n key={virtualRow.index}\n ref={\n elem.type !== MenuItem || elem.type !== MenuItemLink\n ? virtualRow.measureRef\n : undefined\n }\n role=\"presentation\"\n className={cx('VirtualMenu-item')}\n style={{\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n {cloneElement(elem, getItemProps(elem, virtualRow.index))}\n </div>\n );\n }),\n [rowVirtualizer.virtualItems, items, getItemProps]\n );\n\n return (\n <>\n {renderSearch}\n <MenuItemList ref={parentRef} role=\"presentation\">\n <div\n role=\"presentation\"\n className=\"VirtualMenu-item-list\"\n style={{\n height: `${rowVirtualizer.totalSize}px`,\n }}\n >\n {renderItems}\n </div>\n </MenuItemList>\n </>\n );\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n", "import type { KeyboardEvent } from 'react';\n\nimport { isFunction } from 'lodash-es';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any;\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n index === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst normalizeIndex = (index: undefined | null | number, delta: number, count: number) => {\n if (index === undefined || index === null) {\n if (delta < 0) {\n return count - 1;\n } else {\n return 0;\n }\n }\n\n let normalized = index + delta;\n if (normalized > count - 1) {\n normalized = 0;\n } else if (normalized < 0) {\n normalized = count - 1;\n }\n return normalized;\n};\n\nconst handleKeyboardInteractions = (\n event: React.KeyboardEvent,\n keyHandlers: Partial<\n Record<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n >\n) => {\n const ops = {\n ArrowUp: keyHandlers.handleUp,\n ArrowDown: keyHandlers.handleDown,\n Enter: keyHandlers.handleEnter,\n } as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n if (ops[event.key]) {\n event.preventDefault();\n ops[event.key]?.call(this, event);\n }\n};\n\nconst chainEventHandlers =\n (...handlers: Array<AnyFunction | undefined>) =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (event: any) => {\n handlers.forEach((h) => isFunction(h) && h(event));\n };\n\nexport {\n createItemId,\n getNodeForIndex,\n normalizeIndex,\n handleKeyboardInteractions,\n chainEventHandlers,\n};\n"],
|
4
|
+
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import cx from 'clsx';\nimport { forwardRef } from 'react';\n\nimport './styles/Menu.css';\n\ntype MenuBaseProps = React.ComponentPropsWithRef<'div'>;\n\n// This is the pure presentational component that contains menu items\nconst MenuBase = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, ...props }, ref) => {\n const className = cx('Menu', props.className);\n return (\n <div {...props} className={className} ref={ref}>\n {children}\n </div>\n );\n }\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n", "import { SeparatorProps, useSeparator } from '@react-aria/separator';\n\nimport './styles/Menu.css';\n\ntype MenuDividerProps = SeparatorProps & {\n innerRef?: React.RefObject<HTMLDivElement>;\n};\n\nconst MenuDivider = ({ elementType = 'div', orientation, innerRef }: MenuDividerProps) => {\n const { separatorProps } = useSeparator({\n orientation,\n elementType,\n });\n\n return <div {...separatorProps} ref={innerRef} className=\"Menu-divider\" />;\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n", "import type { PopoverPlacement } from '@launchpad-ui/popover';\n\nimport { Icon, IconSize } from '@launchpad-ui/icons';\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { FocusRing } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { Link } from 'react-router-dom';\n\nimport './styles/Menu.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 React.ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends React.ElementType> = Merge<\n T extends keyof JSX.IntrinsicElements\n ? React.PropsWithRef<JSX.IntrinsicElements[T]>\n : React.ComponentPropsWithRef<T>,\n PropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n isHighlighted?: boolean;\n icon?: typeof Icon | null;\n disabled?: boolean;\n nested?: boolean;\n groupHeader?: boolean;\n innerRef?: React.RefObject<HTMLDivElement>;\n tooltip?: string | React.ReactElement;\n tooltipOptions?: typeof Tooltip;\n tooltipPlacement?: PopoverPlacement;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<\n P,\n T extends React.ElementType = typeof defaultElement\n> = PolymorphicPropsWithRef<\n | (MenuItemOwnProps & {\n item: P; // Infer the type if it is included\n })\n | (MenuItemOwnProps & {\n item?: undefined;\n }),\n T\n>;\n\nconst MenuItem = <P, T extends React.ElementType = typeof defaultElement>({\n ...props\n}: MenuItemProps<P, T>) => {\n const {\n component,\n children,\n isHighlighted,\n icon: Icon,\n nested,\n groupHeader,\n item,\n disabled,\n className,\n innerRef,\n tooltip,\n role = 'menuitem',\n tooltipPlacement,\n onKeyDown,\n tooltipOptions,\n ...rest\n } = props;\n\n const Component: React.ElementType = component || defaultElement;\n\n const renderedItem = (\n <FocusRing focusRingClass=\"has-focus\">\n <Component\n {...rest}\n ref={innerRef}\n disabled={disabled}\n aria-disabled={disabled ? disabled : undefined}\n className={cx(\n 'Menu-item',\n className,\n { 'is-highlighted': isHighlighted },\n { 'Menu-item--nested': nested },\n { 'u-fw-medium': groupHeader }\n )}\n role={role}\n onKeyDown={onKeyDown}\n >\n {Icon && (\n <span className=\"Menu-item-icon\">\n <Icon size={IconSize.SMALL} />\n </span>\n )}\n {children}\n </Component>\n </FocusRing>\n );\n\n if (tooltip) {\n return (\n <Tooltip\n content={tooltip}\n rootElementStyle={{ display: 'block' }}\n allowBoundaryElementOverflow\n placement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n {...(tooltipOptions || {})}\n >\n {renderedItem}\n </Tooltip>\n );\n }\n\n return renderedItem;\n};\n\ntype MenuItemLinkOwnProps = {\n disabled?: boolean;\n useHistory?: boolean;\n newTab?: boolean;\n};\n\ntype MenuItemLinkProps<P, T extends React.ElementType = typeof Link> =\n | Merge<Omit<MenuItemProps<P, T>, 'component' | 'item'>, MenuItemLinkOwnProps> &\n (\n | {\n item?: undefined;\n }\n | {\n item: P;\n }\n );\n\n// By default, this is a Link component whenever useHistory is\n// explicitly not false\nconst MenuItemLink = <P, T extends React.ElementType = typeof Link>({\n to,\n disabled = false,\n useHistory = true,\n newTab = false,\n children,\n ...props\n}: MenuItemLinkProps<P, T>) => {\n const finalProps = {\n ...props,\n disabled,\n component: useHistory ? Link : ('a' as const),\n [useHistory ? 'to' : 'href']: disabled ? '' : to,\n rel: newTab ? 'noopener noreferrer' : undefined,\n target: newTab ? '_blank' : undefined,\n };\n\n // Ideally if this item is disabled, it should be a button rather\n // than a link https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md\n\n return <MenuItem {...finalProps}>{children}</MenuItem>;\n};\n\nexport { MenuItem, MenuItemLink };\nexport type { MenuItemProps, MenuItemLinkProps };\n", "import { forwardRef } from 'react';\n\nimport './styles/Menu.css';\n\ntype MenuItemListProps = Omit<React.ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n <div {...rest} ref={ref} data-test-id=\"menu-item-list\" className=\"Menu-item-list\">\n {children}\n </div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n", "import type { ChangeEvent } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport './styles/Menu.css';\n\ntype MenuSearchProps = {\n ariaLabel?: string;\n value?: string;\n placeholder?: string;\n onChange?(event: ChangeEvent<HTMLInputElement>): void;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n const { ariaLabel, placeholder, ...finalProps } = props;\n\n return (\n <div className=\"Menu-search\">\n <input\n {...finalProps}\n ref={ref}\n className=\"Menu-search-input FormInput FormInput--tiny\"\n type=\"search\"\n autoComplete=\"off\"\n placeholder={placeholder}\n aria-label={ariaLabel || 'Search'}\n />\n <div\n className=\"Menu-search-hidden-placeholder Menu-search-input FormInput FormInput--tiny\"\n aria-hidden=\"true\"\n >\n {placeholder}\n </div>\n </div>\n );\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n", "import type { KeyboardEvent, ReactElement } from 'react';\n\nimport { FocusManager, useFocusManager } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { isNil, noop } from 'lodash-es';\nimport { Children, cloneElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useVirtual } from 'react-virtual';\nimport { v4 } from 'uuid';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem, MenuItemLink, MenuItemProps } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport {\n chainEventHandlers,\n createItemId,\n getNodeForIndex,\n handleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n children: React.ReactNode;\n onSelect?: (item: T) => void;\n /**\n * Menus items are rendered using react-virtual for\n * additional rendering performance.\n */\n enableVirtualization?: boolean;\n /**\n * Class name to be applied to all MenuItem and MenuItemLink components\n * in the menu.\n */\n menuItemClassName?: string;\n /**\n * Sets the width of the menu. This is especially useful when using virtual items\n * since the width cannot be automatically set by the widest element.\n */\n menuWidth?: 'tiny' | 'small' | 'med' | 'large' | 'xLarge';\n /**\n * Sets the number out of elements rendered outside of the view window\n * when using virtualization\n */\n overscan?: number;\n /**\n * Sets the height for each menu item when using virtualization.\n *\n */\n itemHeight?: number;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n const {\n children,\n menuItemClassName,\n onSelect,\n enableVirtualization,\n itemHeight,\n menuWidth,\n overscan = 1,\n } = props;\n\n const focusManager = useFocusManager();\n\n const handleArrowDown = useCallback(() => {\n focusManager.focusNext({ wrap: true });\n }, [focusManager]);\n\n const handleArrowUp = useCallback(() => {\n focusManager.focusPrevious({ wrap: true });\n }, [focusManager]);\n\n const reduceItems = useMemo(() => {\n const childrenProps = Children.toArray(children);\n if (enableVirtualization) {\n // the virtualized menu has its own handlers and props\n let searchElem = null;\n let elements: ReactElement[] = [];\n (childrenProps as ReactElement[]).forEach((child: ReactElement) => {\n switch (child.type) {\n case MenuSearch:\n searchElem = child;\n break;\n case MenuItem:\n case MenuItemLink:\n case MenuDivider:\n elements = elements.concat(child);\n break;\n default:\n break;\n }\n });\n return { items: elements, searchElement: searchElem };\n }\n\n return (childrenProps as ReactElement[]).reduce(\n (\n { items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n child\n ) => {\n switch (child.type) {\n case MenuSearch:\n return {\n items,\n searchElement: cloneElement(child, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n }),\n };\n case MenuItem:\n case MenuItemLink:\n return {\n items: items.concat(\n child.props.disabled\n ? cloneElement(child, {\n onClick: noop,\n onKeyDown: noop,\n tabIndex: -1,\n disabled: true,\n })\n : cloneElement(child, {\n className: cx(child.props.className, menuItemClassName),\n item: child.props.item ?? items.length,\n // set focus on the first menu item if there is no search input, and set in the tab order\n onClick: chainEventHandlers(child.props.onClick, () => {\n onSelect?.(child.props.item ?? items.length);\n }),\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n })\n ),\n searchElement,\n };\n case MenuDivider:\n return { items: items.concat(child), searchElement };\n default:\n return { items, searchElement };\n }\n },\n { items: [], searchElement: null }\n );\n }, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n const menuClassName = cx(\n { 'Menu--isVirtual': enableVirtualization },\n { [`MenuSize--${menuWidth}`]: menuWidth }\n );\n\n if (enableVirtualization) {\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n <ItemVirtualizer<T>\n items={Children.toArray(reduceItems.items) as ReactElement[]}\n searchElement={reduceItems.searchElement}\n overscan={overscan}\n menuItemClassName={menuItemClassName}\n onSelect={onSelect}\n itemHeight={itemHeight}\n focusManager={focusManager}\n />\n </MenuBase>\n );\n }\n\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n {reduceItems.searchElement}\n <MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n </MenuBase>\n );\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n items: ReactElement[] | null;\n searchElement?: React.ReactElement | null;\n focusManager: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n const {\n overscan,\n searchElement,\n itemHeight = 33,\n menuItemClassName,\n items: items,\n focusManager,\n onSelect,\n } = props;\n\n const menuId = useRef(`menu-ctrl-${v4()}`);\n\n const focusedItemIndex = useRef<number | null>(null);\n const parentRef = useRef<HTMLDivElement | null>(null);\n const searchRef = useRef<HTMLInputElement>();\n\n const [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n const hasSearch = !!searchElement;\n\n const lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n const rowVirtualizer = useVirtual({\n size: items !== null ? items.length : 0,\n parentRef,\n estimateSize: useCallback(() => itemHeight, [itemHeight]),\n overscan,\n });\n\n const focusSearchBar = useCallback(() => {\n rowVirtualizer.scrollToIndex(0);\n searchRef.current?.focus?.();\n }, [rowVirtualizer]);\n\n /**\n * Scrolls to the menu item with the index provided and\n * then manually focuses it using a side effect in useEffect\n */\n const focusMenuItem = useCallback(\n (index: number) => {\n rowVirtualizer.scrollToIndex(index);\n setNextFocusValue(index);\n },\n [rowVirtualizer]\n );\n\n const handleKeyboardFocusInteraction = useCallback(\n (direction: 'next' | 'previous') => {\n if (isNil(focusedItemIndex.current)) {\n return;\n }\n const nextIndex =\n direction === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n const shouldWrap =\n (direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n (direction === 'previous' && focusedItemIndex.current === 0);\n if (shouldWrap) {\n // we are at the end of the list so we will\n // scroll back to the beginning of the list\n if (hasSearch) {\n focusSearchBar();\n } else {\n // if at end, wrap to beginning, else focus last item\n focusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n }\n return;\n }\n switch (direction) {\n case 'next':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusNext();\n break;\n case 'previous':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusPrevious();\n break;\n default:\n break;\n }\n },\n [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]\n );\n\n const getItemProps = useCallback(\n (itemElem: ReactElement, index: number) => {\n const childProps = itemElem.props as MenuItemProps<T>;\n switch (itemElem.type) {\n case MenuItem:\n case MenuItemLink:\n return {\n className: cx(childProps.className, menuItemClassName),\n // set focus on the first menu item if there is no search input, and set in the tab order\n onKeyDown: childProps.disabled\n ? noop\n : (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: handleKeyboardFocusInteraction,\n handleFocusForward: handleKeyboardFocusInteraction,\n }),\n onFocus: chainEventHandlers(childProps.onFocus, () => {\n focusedItemIndex.current = index;\n }),\n id: createItemId(index, menuId.current),\n onBlur: chainEventHandlers(childProps.onBlur, () => {\n focusedItemIndex.current = null;\n }),\n onClick: childProps.disabled\n ? noop\n : chainEventHandlers(childProps.onClick, () => {\n onSelect?.(childProps.item as T);\n }),\n } as MenuItemProps<T>;\n default:\n return {};\n }\n },\n [handleKeyboardFocusInteraction, menuItemClassName, onSelect]\n );\n\n useEffect(() => {\n if (nextFocusValue !== null) {\n requestAnimationFrame(() => {\n const element = getNodeForIndex(nextFocusValue, menuId.current);\n element?.focus();\n });\n setNextFocusValue(null);\n }\n }, [nextFocusValue]);\n\n /**\n * Calls handleFocusForward when the user is attempting to focus forward using\n * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n */\n const handleKeyboardFocusKeydown = (\n e: KeyboardEvent,\n callbacks: Record<\n 'handleFocusForward' | 'handleFocusBackward',\n (direction: 'next' | 'previous') => void\n >\n ) => {\n const keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n if (keyOps.includes(e.key)) {\n e.preventDefault();\n e.stopPropagation();\n if ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n callbacks.handleFocusBackward?.('previous');\n } else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n callbacks.handleFocusForward?.('next');\n }\n }\n };\n\n const renderSearch = useMemo(\n () =>\n searchElement\n ? cloneElement(searchElement, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n handleFocusForward: () => focusMenuItem(0),\n }),\n ref: searchRef,\n })\n : null,\n [searchElement, lastVirtualItemIndex, focusMenuItem]\n );\n\n const renderItems = useMemo(\n () =>\n rowVirtualizer.virtualItems.map((virtualRow) => {\n if (!items) {\n return null;\n }\n const elem = items[virtualRow.index];\n return (\n <div\n key={virtualRow.index}\n ref={\n elem.type !== MenuItem || elem.type !== MenuItemLink\n ? virtualRow.measureRef\n : undefined\n }\n role=\"presentation\"\n className={cx('VirtualMenu-item')}\n style={{\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n {cloneElement(elem, getItemProps(elem, virtualRow.index))}\n </div>\n );\n }),\n [rowVirtualizer.virtualItems, items, getItemProps]\n );\n\n return (\n <>\n {renderSearch}\n <MenuItemList ref={parentRef} role=\"presentation\">\n <div\n role=\"presentation\"\n className=\"VirtualMenu-item-list\"\n style={{\n height: `${rowVirtualizer.totalSize}px`,\n }}\n >\n {renderItems}\n </div>\n </MenuItemList>\n </>\n );\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n", "import type { KeyboardEvent } from 'react';\n\nimport { isFunction } from 'lodash-es';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any;\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n index === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst normalizeIndex = (index: undefined | null | number, delta: number, count: number) => {\n if (index === undefined || index === null) {\n if (delta < 0) {\n return count - 1;\n } else {\n return 0;\n }\n }\n\n let normalized = index + delta;\n if (normalized > count - 1) {\n normalized = 0;\n } else if (normalized < 0) {\n normalized = count - 1;\n }\n return normalized;\n};\n\nconst handleKeyboardInteractions = (\n event: React.KeyboardEvent,\n keyHandlers: Partial<\n Record<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n >\n) => {\n const ops = {\n ArrowUp: keyHandlers.handleUp,\n ArrowDown: keyHandlers.handleDown,\n Enter: keyHandlers.handleEnter,\n } as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n if (ops[event.key]) {\n event.preventDefault();\n ops[event.key]?.call(this, event);\n }\n};\n\nconst chainEventHandlers =\n (...handlers: Array<AnyFunction | undefined>) =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (event: any) => {\n handlers.forEach((h) => isFunction(h) && h(event));\n };\n\nexport {\n createItemId,\n getNodeForIndex,\n normalizeIndex,\n handleKeyboardInteractions,\n chainEventHandlers,\n};\n"],
|
5
5
|
"mappings": ";AAAA;;;ACAA;AACA;AAEA;AAKA,IAAM,WAAW,WACf,CAAC,EAAE,aAAa,SAAS,QAAQ;AAC/B,QAAM,YAAY,GAAG,QAAQ,MAAM,SAAS;AAC5C,SACE,oCAAC;AAAA,IAAK,GAAG;AAAA,IAAO;AAAA,IAAsB;AAAA,KACnC,QACH;AAEJ,CACF;AAEA,SAAS,cAAc;;;ACnBvB;AAEA;AAMA,IAAM,cAAc,CAAC,EAAE,cAAc,OAAO,aAAa,eAAiC;AACxF,QAAM,EAAE,mBAAmB,aAAa;AAAA,IACtC;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,oCAAC;AAAA,IAAK,GAAG;AAAA,IAAgB,KAAK;AAAA,IAAU,WAAU;AAAA,GAAe;AAC1E;;;ACbA;AACA;AACA;AACA;AACA;AAEA;AA0BA,IAAM,iBAAiB;AAevB,IAAM,WAAW,CAAyD;AAAA,KACrE;AAAA,MACsB;AACzB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,OACG;AAAA,MACD;AAEJ,QAAM,YAA+B,aAAa;AAElD,QAAM,eACJ,oCAAC;AAAA,IAAU,gBAAe;AAAA,KACxB,oCAAC;AAAA,IACE,GAAG;AAAA,IACJ,KAAK;AAAA,IACL;AAAA,IACA,iBAAe,WAAW,WAAW;AAAA,IACrC,WAAW,IACT,aACA,WACA,EAAE,kBAAkB,cAAc,GAClC,EAAE,qBAAqB,OAAO,GAC9B,EAAE,eAAe,YAAY,CAC/B;AAAA,IACA;AAAA,IACA;AAAA,KAEC,SACC,oCAAC;AAAA,IAAK,WAAU;AAAA,KACd,oCAAC;AAAA,IAAK,MAAM,SAAS;AAAA,GAAO,CAC9B,GAED,QACH,CACF;AAGF,MAAI,SAAS;AACX,WACE,oCAAC;AAAA,MACC,SAAS;AAAA,MACT,kBAAkB,EAAE,SAAS,QAAQ;AAAA,MACrC,8BAA4B;AAAA,MAC5B,WAAW,mBAAmB,mBAAmB;AAAA,MAChD,GAAI,kBAAkB,CAAC;AAAA,OAEvB,YACH;AAAA,EAEJ;AAEA,SAAO;AACT;AAqBA,IAAM,eAAe,CAA+C;AAAA,EAClE;AAAA,EACA,WAAW;AAAA,EACX,aAAa;AAAA,EACb,SAAS;AAAA,EACT;AAAA,KACG;AAAA,MAC0B;AAC7B,QAAM,aAAa;AAAA,IACjB,GAAG;AAAA,IACH;AAAA,IACA,WAAW,aAAa,OAAQ;AAAA,IAChC,CAAC,aAAa,OAAO,SAAS,WAAW,KAAK;AAAA,IAC9C,KAAK,SAAS,wBAAwB;AAAA,IACtC,QAAQ,SAAS,WAAW;AAAA,EAC9B;AAKA,SAAO,oCAAC;AAAA,IAAU,GAAG;AAAA,KAAa,QAAS;AAC7C;;;AC7JA;AAEA;AAIA,IAAM,eAAe,YAA8C,CAAC,EAAE,aAAa,QAAQ,QACzF,oCAAC;AAAA,EAAK,GAAG;AAAA,EAAM;AAAA,EAAU,gBAAa;AAAA,EAAiB,WAAU;AAAA,GAC9D,QACH,CACD;AAED,aAAa,cAAc;;;ACV3B;AAEA;AASA,IAAM,aAAa,YAA8C,CAAC,OAAO,QAAQ;AAC/E,QAAM,EAAE,WAAW,gBAAgB,eAAe;AAElD,SACE,oCAAC;AAAA,IAAI,WAAU;AAAA,KACb,oCAAC;AAAA,IACE,GAAG;AAAA,IACJ;AAAA,IACA,WAAU;AAAA,IACV,MAAK;AAAA,IACL,cAAa;AAAA,IACb;AAAA,IACA,cAAY,aAAa;AAAA,GAC3B,GACA,oCAAC;AAAA,IACC,WAAU;AAAA,IACV,eAAY;AAAA,KAEX,WACH,CACF;AAEJ,CAAC;AAED,WAAW,cAAc;;;ACnCzB;AACA;AACA;AACA;AACA;AACA;;;ACLA;AAKA,IAAM,eAAe,CAAC,OAAe,OAAe,GAAG,WAAW;AAElE,IAAM,kBAAkB,CAAC,OAAsB,WAC7C,UAAU,OAAO,QAAQ,SAAS,eAAe,aAAa,OAAO,MAAM,CAAC;AAoB9E,IAAM,6BAA6B,CACjC,OACA,gBAGG;AACH,QAAM,MAAM;AAAA,IACV,SAAS,YAAY;AAAA,IACrB,WAAW,YAAY;AAAA,IACvB,OAAO,YAAY;AAAA,EACrB;AAEA,MAAI,IAAI,MAAM,MAAM;AAClB,UAAM,eAAe;AACrB,QAAI,MAAM,MAAM,KAAK,QAAM,KAAK;AAAA,EAClC;AACF;AAEA,IAAM,qBACJ,IAAI,aAEJ,CAAC,UAAe;AACd,WAAS,QAAQ,CAAC,MAAM,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC;AACnD;;;ADAF,IAAM,OAAO,CAA4B,UAAwB;AAC/D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,MACT;AAEJ,QAAM,eAAe,gBAAgB;AAErC,QAAM,kBAAkB,YAAY,MAAM;AACxC,iBAAa,UAAU,EAAE,MAAM,KAAK,CAAC;AAAA,EACvC,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,gBAAgB,YAAY,MAAM;AACtC,iBAAa,cAAc,EAAE,MAAM,KAAK,CAAC;AAAA,EAC3C,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,gBAAgB,SAAS,QAAQ,QAAQ;AAC/C,QAAI,sBAAsB;AAExB,UAAI,aAAa;AACjB,UAAI,WAA2B,CAAC;AAChC,MAAC,cAAiC,QAAQ,CAAC,UAAwB;AACjE,gBAAQ,MAAM;AAAA,eACP;AACH,yBAAa;AACb;AAAA,eACG;AAAA,eACA;AAAA,eACA;AACH,uBAAW,SAAS,OAAO,KAAK;AAChC;AAAA;AAEA;AAAA;AAAA,MAEN,CAAC;AACD,aAAO,EAAE,OAAO,UAAU,eAAe,WAAW;AAAA,IACtD;AAEA,WAAQ,cAAiC,OACvC,CACE,EAAE,OAAO,iBACT,UACG;AACH,cAAQ,MAAM;AAAA,aACP;AACH,iBAAO;AAAA,YACL;AAAA,YACA,eAAe,aAAa,OAAO;AAAA,cACjC,WAAW,CAAC,MACV,2BAA2B,GAAG;AAAA,gBAC5B,YAAY;AAAA,gBACZ,UAAU;AAAA,cACZ,CAAC;AAAA,YACL,CAAC;AAAA,UACH;AAAA,aACG;AAAA,aACA;AACH,iBAAO;AAAA,YACL,OAAO,MAAM,OACX,MAAM,MAAM,WACR,aAAa,OAAO;AAAA,cAClB,SAAS;AAAA,cACT,WAAW;AAAA,cACX,UAAU;AAAA,cACV,UAAU;AAAA,YACZ,CAAC,IACD,aAAa,OAAO;AAAA,cAClB,WAAW,IAAG,MAAM,MAAM,WAAW,iBAAiB;AAAA,cACtD,MAAM,MAAM,MAAM,QAAQ,MAAM;AAAA,cAEhC,SAAS,mBAAmB,MAAM,MAAM,SAAS,MAAM;AACrD,2BAAW,MAAM,MAAM,QAAQ,MAAM,MAAM;AAAA,cAC7C,CAAC;AAAA,cACD,WAAW,CAAC,MACV,2BAA2B,GAAG;AAAA,gBAC5B,YAAY;AAAA,gBACZ,UAAU;AAAA,cACZ,CAAC;AAAA,YACL,CAAC,CACP;AAAA,YACA;AAAA,UACF;AAAA,aACG;AACH,iBAAO,EAAE,OAAO,MAAM,OAAO,KAAK,GAAG,cAAc;AAAA;AAEnD,iBAAO,EAAE,OAAO,cAAc;AAAA;AAAA,IAEpC,GACA,EAAE,OAAO,CAAC,GAAG,eAAe,KAAK,CACnC;AAAA,EACF,GAAG,CAAC,UAAU,sBAAsB,mBAAmB,iBAAiB,eAAe,QAAQ,CAAC;AAEhG,QAAM,gBAAgB,IACpB,EAAE,mBAAmB,qBAAqB,GAC1C,EAAE,CAAC,aAAa,cAAc,UAAU,CAC1C;AAEA,MAAI,sBAAsB;AACxB,WACE,oCAAC;AAAA,MAAS,MAAK;AAAA,MAAO,WAAW;AAAA,OAC/B,oCAAC;AAAA,MACC,OAAO,SAAS,QAAQ,YAAY,KAAK;AAAA,MACzC,eAAe,YAAY;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,KACF,CACF;AAAA,EAEJ;AAEA,SACE,oCAAC;AAAA,IAAS,MAAK;AAAA,IAAO,WAAW;AAAA,KAC9B,YAAY,eACb,oCAAC;AAAA,IAAa,MAAK;AAAA,KAAgB,YAAY,KAAM,CACvD;AAEJ;AAQA,IAAM,kBAAkB,CAA4B,UAAmC;AACrF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAEJ,QAAM,SAAS,OAAO,aAAa,GAAG,GAAG;AAEzC,QAAM,mBAAmB,OAAsB,IAAI;AACnD,QAAM,YAAY,OAA8B,IAAI;AACpD,QAAM,YAAY,OAAyB;AAE3C,QAAM,CAAC,gBAAgB,qBAAqB,SAAwB,IAAI;AAExE,QAAM,YAAY,CAAC,CAAC;AAEpB,QAAM,uBAAuB,QAAQ,MAAM,SAAS,IAAI;AAExD,QAAM,iBAAiB,WAAW;AAAA,IAChC,MAAM,UAAU,OAAO,MAAM,SAAS;AAAA,IACtC;AAAA,IACA,cAAc,YAAY,MAAM,YAAY,CAAC,UAAU,CAAC;AAAA,IACxD;AAAA,EACF,CAAC;AAED,QAAM,iBAAiB,YAAY,MAAM;AACvC,mBAAe,cAAc,CAAC;AAC9B,cAAU,SAAS,QAAQ;AAAA,EAC7B,GAAG,CAAC,cAAc,CAAC;AAMnB,QAAM,gBAAgB,YACpB,CAAC,UAAkB;AACjB,mBAAe,cAAc,KAAK;AAClC,sBAAkB,KAAK;AAAA,EACzB,GACA,CAAC,cAAc,CACjB;AAEA,QAAM,iCAAiC,YACrC,CAAC,cAAmC;AAClC,QAAI,MAAM,iBAAiB,OAAO,GAAG;AACnC;AAAA,IACF;AACA,UAAM,YACJ,cAAc,SAAS,iBAAiB,UAAU,IAAI,iBAAiB,UAAU;AACnF,UAAM,aACH,cAAc,UAAU,iBAAiB,YAAY,wBACrD,cAAc,cAAc,iBAAiB,YAAY;AAC5D,QAAI,YAAY;AAGd,UAAI,WAAW;AACb,uBAAe;AAAA,MACjB,OAAO;AAEL,sBAAc,cAAc,SAAS,IAAI,oBAAoB;AAAA,MAC/D;AACA;AAAA,IACF;AACA,YAAQ;AAAA,WACD;AACH,uBAAe,cAAc,SAAS;AACtC,qBAAa,UAAU;AACvB;AAAA,WACG;AACH,uBAAe,cAAc,SAAS;AACtC,qBAAa,cAAc;AAC3B;AAAA;AAEA;AAAA;AAAA,EAEN,GACA,CAAC,cAAc,eAAe,gBAAgB,WAAW,sBAAsB,cAAc,CAC/F;AAEA,QAAM,eAAe,YACnB,CAAC,UAAwB,UAAkB;AACzC,UAAM,aAAa,SAAS;AAC5B,YAAQ,SAAS;AAAA,WACV;AAAA,WACA;AACH,eAAO;AAAA,UACL,WAAW,IAAG,WAAW,WAAW,iBAAiB;AAAA,UAErD,WAAW,WAAW,WAClB,OACA,CAAC,MACC,2BAA2B,GAAG;AAAA,YAC5B,qBAAqB;AAAA,YACrB,oBAAoB;AAAA,UACtB,CAAC;AAAA,UACP,SAAS,mBAAmB,WAAW,SAAS,MAAM;AACpD,6BAAiB,UAAU;AAAA,UAC7B,CAAC;AAAA,UACD,IAAI,aAAa,OAAO,OAAO,OAAO;AAAA,UACtC,QAAQ,mBAAmB,WAAW,QAAQ,MAAM;AAClD,6BAAiB,UAAU;AAAA,UAC7B,CAAC;AAAA,UACD,SAAS,WAAW,WAChB,OACA,mBAAmB,WAAW,SAAS,MAAM;AAC3C,uBAAW,WAAW,IAAS;AAAA,UACjC,CAAC;AAAA,QACP;AAAA;AAEA,eAAO,CAAC;AAAA;AAAA,EAEd,GACA,CAAC,gCAAgC,mBAAmB,QAAQ,CAC9D;AAEA,YAAU,MAAM;AACd,QAAI,mBAAmB,MAAM;AAC3B,4BAAsB,MAAM;AAC1B,cAAM,UAAU,gBAAgB,gBAAgB,OAAO,OAAO;AAC9D,iBAAS,MAAM;AAAA,MACjB,CAAC;AACD,wBAAkB,IAAI;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAMnB,QAAM,6BAA6B,CACjC,GACA,cAIG;AACH,UAAM,SAAS,CAAC,OAAO,WAAW,WAAW;AAC7C,QAAI,OAAO,SAAS,EAAE,GAAG,GAAG;AAC1B,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,UAAK,EAAE,QAAQ,SAAS,EAAE,YAAa,EAAE,QAAQ,WAAW;AAC1D,kBAAU,sBAAsB,UAAU;AAAA,MAC5C,WAAW,EAAE,QAAQ,eAAe,EAAE,QAAQ,OAAO;AACnD,kBAAU,qBAAqB,MAAM;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,QACnB,MACE,gBACI,aAAa,eAAe;AAAA,IAC1B,WAAW,CAAC,MACV,2BAA2B,GAAG;AAAA,MAC5B,qBAAqB,MAAM,cAAc,oBAAoB;AAAA,MAC7D,oBAAoB,MAAM,cAAc,CAAC;AAAA,IAC3C,CAAC;AAAA,IACH,KAAK;AAAA,EACP,CAAC,IACD,MACN,CAAC,eAAe,sBAAsB,aAAa,CACrD;AAEA,QAAM,cAAc,QAClB,MACE,eAAe,aAAa,IAAI,CAAC,eAAe;AAC9C,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AACA,UAAM,OAAO,MAAM,WAAW;AAC9B,WACE,oCAAC;AAAA,MACC,KAAK,WAAW;AAAA,MAChB,KACE,KAAK,SAAS,YAAY,KAAK,SAAS,eACpC,WAAW,aACX;AAAA,MAEN,MAAK;AAAA,MACL,WAAW,IAAG,kBAAkB;AAAA,MAChC,OAAO;AAAA,QACL,WAAW,cAAc,WAAW;AAAA,MACtC;AAAA,OAEC,aAAa,MAAM,aAAa,MAAM,WAAW,KAAK,CAAC,CAC1D;AAAA,EAEJ,CAAC,GACH,CAAC,eAAe,cAAc,OAAO,YAAY,CACnD;AAEA,SACE,0DACG,cACD,oCAAC;AAAA,IAAa,KAAK;AAAA,IAAW,MAAK;AAAA,KACjC,oCAAC;AAAA,IACC,MAAK;AAAA,IACL,WAAU;AAAA,IACV,OAAO;AAAA,MACL,QAAQ,GAAG,eAAe;AAAA,IAC5B;AAAA,KAEC,WACH,CACF,CACF;AAEJ;",
|
6
6
|
"names": []
|
7
7
|
}
|
package/dist/index.js
CHANGED
@@ -38,7 +38,7 @@ var React = __toESM(require("react"));
|
|
38
38
|
// src/MenuBase.tsx
|
39
39
|
var import_clsx = __toESM(require("clsx"));
|
40
40
|
var import_react = require("react");
|
41
|
-
var
|
41
|
+
var import_Menu = require("./styles/Menu.css");
|
42
42
|
var MenuBase = (0, import_react.forwardRef)(({ children, ...props }, ref) => {
|
43
43
|
const className = (0, import_clsx.default)("Menu", props.className);
|
44
44
|
return /* @__PURE__ */ React.createElement("div", {
|
@@ -51,7 +51,7 @@ MenuBase.displayName = "MenuBase";
|
|
51
51
|
|
52
52
|
// src/MenuDivider.tsx
|
53
53
|
var import_separator = require("@react-aria/separator");
|
54
|
-
var
|
54
|
+
var import_Menu2 = require("./styles/Menu.css");
|
55
55
|
var MenuDivider = ({ elementType = "div", orientation, innerRef }) => {
|
56
56
|
const { separatorProps } = (0, import_separator.useSeparator)({
|
57
57
|
orientation,
|
@@ -70,7 +70,7 @@ var import_tooltip = require("@launchpad-ui/tooltip");
|
|
70
70
|
var import_focus = require("@react-aria/focus");
|
71
71
|
var import_clsx2 = __toESM(require("clsx"));
|
72
72
|
var import_react_router_dom = require("react-router-dom");
|
73
|
-
var
|
73
|
+
var import_Menu3 = require("./styles/Menu.css");
|
74
74
|
var defaultElement = "button";
|
75
75
|
var MenuItem = ({
|
76
76
|
...props
|
@@ -143,7 +143,7 @@ var MenuItemLink = ({
|
|
143
143
|
|
144
144
|
// src/MenuItemList.tsx
|
145
145
|
var import_react2 = require("react");
|
146
|
-
var
|
146
|
+
var import_Menu4 = require("./styles/Menu.css");
|
147
147
|
var MenuItemList = (0, import_react2.forwardRef)(({ children, ...rest }, ref) => /* @__PURE__ */ React.createElement("div", {
|
148
148
|
...rest,
|
149
149
|
ref,
|
@@ -154,7 +154,7 @@ MenuItemList.displayName = "MenuItemList";
|
|
154
154
|
|
155
155
|
// src/MenuSearch.tsx
|
156
156
|
var import_react3 = require("react");
|
157
|
-
var
|
157
|
+
var import_Menu5 = require("./styles/Menu.css");
|
158
158
|
var MenuSearch = (0, import_react3.forwardRef)((props, ref) => {
|
159
159
|
const { ariaLabel, placeholder, ...finalProps } = props;
|
160
160
|
return /* @__PURE__ */ React.createElement("div", {
|
package/dist/index.js.map
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"version": 3,
|
3
3
|
"sources": ["../src/index.ts", "../../../scripts/react-shim.js", "../src/MenuBase.tsx", "../src/MenuDivider.tsx", "../src/MenuItem.tsx", "../src/MenuItemList.tsx", "../src/MenuSearch.tsx", "../src/Menu.tsx", "../src/utils.ts"],
|
4
|
-
"sourcesContent": ["export type { MenuBaseProps } from './MenuBase';\nexport type { MenuDividerProps } from './MenuDivider';\nexport type { MenuItemProps, MenuItemLinkProps } from './MenuItem';\nexport type { MenuItemListProps } from './MenuItemList';\nexport type { MenuSearchProps } from './MenuSearch';\nexport type { MenuProps } from './Menu';\nexport { MenuBase } from './MenuBase';\nexport { MenuDivider } from './MenuDivider';\nexport { MenuItem, MenuItemLink } from './MenuItem';\nexport { MenuItemList } from './MenuItemList';\nexport { MenuSearch } from './MenuSearch';\nexport { Menu } from './Menu';\n", "import * as React from 'react';\nexport { React };\n", "import cx from 'clsx';\nimport { forwardRef } from 'react';\n\nimport './styles.css';\n\ntype MenuBaseProps = React.ComponentPropsWithRef<'div'>;\n\n// This is the pure presentational component that contains menu items\nconst MenuBase = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, ...props }, ref) => {\n const className = cx('Menu', props.className);\n return (\n <div {...props} className={className} ref={ref}>\n {children}\n </div>\n );\n }\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n", "import { SeparatorProps, useSeparator } from '@react-aria/separator';\n\nimport './styles.css';\n\ntype MenuDividerProps = SeparatorProps & {\n innerRef?: React.RefObject<HTMLDivElement>;\n};\n\nconst MenuDivider = ({ elementType = 'div', orientation, innerRef }: MenuDividerProps) => {\n const { separatorProps } = useSeparator({\n orientation,\n elementType,\n });\n\n return <div {...separatorProps} ref={innerRef} className=\"Menu-divider\" />;\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n", "import type { PopoverPlacement } from '@launchpad-ui/popover';\n\nimport { Icon, IconSize } from '@launchpad-ui/icons';\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { FocusRing } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { Link } from 'react-router-dom';\n\nimport './styles.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 React.ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends React.ElementType> = Merge<\n T extends keyof JSX.IntrinsicElements\n ? React.PropsWithRef<JSX.IntrinsicElements[T]>\n : React.ComponentPropsWithRef<T>,\n PropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n isHighlighted?: boolean;\n icon?: typeof Icon | null;\n disabled?: boolean;\n nested?: boolean;\n groupHeader?: boolean;\n innerRef?: React.RefObject<HTMLDivElement>;\n tooltip?: string | React.ReactElement;\n tooltipOptions?: typeof Tooltip;\n tooltipPlacement?: PopoverPlacement;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<\n P,\n T extends React.ElementType = typeof defaultElement\n> = PolymorphicPropsWithRef<\n | (MenuItemOwnProps & {\n item: P; // Infer the type if it is included\n })\n | (MenuItemOwnProps & {\n item?: undefined;\n }),\n T\n>;\n\nconst MenuItem = <P, T extends React.ElementType = typeof defaultElement>({\n ...props\n}: MenuItemProps<P, T>) => {\n const {\n component,\n children,\n isHighlighted,\n icon: Icon,\n nested,\n groupHeader,\n item,\n disabled,\n className,\n innerRef,\n tooltip,\n role = 'menuitem',\n tooltipPlacement,\n onKeyDown,\n tooltipOptions,\n ...rest\n } = props;\n\n const Component: React.ElementType = component || defaultElement;\n\n const renderedItem = (\n <FocusRing focusRingClass=\"has-focus\">\n <Component\n {...rest}\n ref={innerRef}\n disabled={disabled}\n aria-disabled={disabled ? disabled : undefined}\n className={cx(\n 'Menu-item',\n className,\n { 'is-highlighted': isHighlighted },\n { 'Menu-item--nested': nested },\n { 'u-fw-medium': groupHeader }\n )}\n role={role}\n onKeyDown={onKeyDown}\n >\n {Icon && (\n <span className=\"Menu-item-icon\">\n <Icon size={IconSize.SMALL} />\n </span>\n )}\n {children}\n </Component>\n </FocusRing>\n );\n\n if (tooltip) {\n return (\n <Tooltip\n content={tooltip}\n rootElementStyle={{ display: 'block' }}\n allowBoundaryElementOverflow\n placement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n {...(tooltipOptions || {})}\n >\n {renderedItem}\n </Tooltip>\n );\n }\n\n return renderedItem;\n};\n\ntype MenuItemLinkOwnProps = {\n disabled?: boolean;\n useHistory?: boolean;\n newTab?: boolean;\n};\n\ntype MenuItemLinkProps<P, T extends React.ElementType = typeof Link> =\n | Merge<Omit<MenuItemProps<P, T>, 'component' | 'item'>, MenuItemLinkOwnProps> &\n (\n | {\n item?: undefined;\n }\n | {\n item: P;\n }\n );\n\n// By default, this is a Link component whenever useHistory is\n// explicitly not false\nconst MenuItemLink = <P, T extends React.ElementType = typeof Link>({\n to,\n disabled = false,\n useHistory = true,\n newTab = false,\n children,\n ...props\n}: MenuItemLinkProps<P, T>) => {\n const finalProps = {\n ...props,\n disabled,\n component: useHistory ? Link : ('a' as const),\n [useHistory ? 'to' : 'href']: disabled ? '' : to,\n rel: newTab ? 'noopener noreferrer' : undefined,\n target: newTab ? '_blank' : undefined,\n };\n\n // Ideally if this item is disabled, it should be a button rather\n // than a link https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md\n\n return <MenuItem {...finalProps}>{children}</MenuItem>;\n};\n\nexport { MenuItem, MenuItemLink };\nexport type { MenuItemProps, MenuItemLinkProps };\n", "import { forwardRef } from 'react';\n\nimport './styles.css';\n\ntype MenuItemListProps = Omit<React.ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n <div {...rest} ref={ref} data-test-id=\"menu-item-list\" className=\"Menu-item-list\">\n {children}\n </div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n", "import type { ChangeEvent } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport './styles.css';\n\ntype MenuSearchProps = {\n ariaLabel?: string;\n value?: string;\n placeholder?: string;\n onChange?(event: ChangeEvent<HTMLInputElement>): void;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n const { ariaLabel, placeholder, ...finalProps } = props;\n\n return (\n <div className=\"Menu-search\">\n <input\n {...finalProps}\n ref={ref}\n className=\"Menu-search-input FormInput FormInput--tiny\"\n type=\"search\"\n autoComplete=\"off\"\n placeholder={placeholder}\n aria-label={ariaLabel || 'Search'}\n />\n <div\n className=\"Menu-search-hidden-placeholder Menu-search-input FormInput FormInput--tiny\"\n aria-hidden=\"true\"\n >\n {placeholder}\n </div>\n </div>\n );\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n", "import type { KeyboardEvent, ReactElement } from 'react';\n\nimport { FocusManager, useFocusManager } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { isNil, noop } from 'lodash-es';\nimport { Children, cloneElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useVirtual } from 'react-virtual';\nimport { v4 } from 'uuid';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem, MenuItemLink, MenuItemProps } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport {\n chainEventHandlers,\n createItemId,\n getNodeForIndex,\n handleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n children: React.ReactNode;\n onSelect?: (item: T) => void;\n /**\n * Menus items are rendered using react-virtual for\n * additional rendering performance.\n */\n enableVirtualization?: boolean;\n /**\n * Class name to be applied to all MenuItem and MenuItemLink components\n * in the menu.\n */\n menuItemClassName?: string;\n /**\n * Sets the width of the menu. This is especially useful when using virtual items\n * since the width cannot be automatically set by the widest element.\n */\n menuWidth?: 'tiny' | 'small' | 'med' | 'large' | 'xLarge';\n /**\n * Sets the number out of elements rendered outside of the view window\n * when using virtualization\n */\n overscan?: number;\n /**\n * Sets the height for each menu item when using virtualization.\n *\n */\n itemHeight?: number;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n const {\n children,\n menuItemClassName,\n onSelect,\n enableVirtualization,\n itemHeight,\n menuWidth,\n overscan = 1,\n } = props;\n\n const focusManager = useFocusManager();\n\n const handleArrowDown = useCallback(() => {\n focusManager.focusNext({ wrap: true });\n }, [focusManager]);\n\n const handleArrowUp = useCallback(() => {\n focusManager.focusPrevious({ wrap: true });\n }, [focusManager]);\n\n const reduceItems = useMemo(() => {\n const childrenProps = Children.toArray(children);\n if (enableVirtualization) {\n // the virtualized menu has its own handlers and props\n let searchElem = null;\n let elements: ReactElement[] = [];\n (childrenProps as ReactElement[]).forEach((child: ReactElement) => {\n switch (child.type) {\n case MenuSearch:\n searchElem = child;\n break;\n case MenuItem:\n case MenuItemLink:\n case MenuDivider:\n elements = elements.concat(child);\n break;\n default:\n break;\n }\n });\n return { items: elements, searchElement: searchElem };\n }\n\n return (childrenProps as ReactElement[]).reduce(\n (\n { items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n child\n ) => {\n switch (child.type) {\n case MenuSearch:\n return {\n items,\n searchElement: cloneElement(child, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n }),\n };\n case MenuItem:\n case MenuItemLink:\n return {\n items: items.concat(\n child.props.disabled\n ? cloneElement(child, {\n onClick: noop,\n onKeyDown: noop,\n tabIndex: -1,\n disabled: true,\n })\n : cloneElement(child, {\n className: cx(child.props.className, menuItemClassName),\n item: child.props.item ?? items.length,\n // set focus on the first menu item if there is no search input, and set in the tab order\n onClick: chainEventHandlers(child.props.onClick, () => {\n onSelect?.(child.props.item ?? items.length);\n }),\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n })\n ),\n searchElement,\n };\n case MenuDivider:\n return { items: items.concat(child), searchElement };\n default:\n return { items, searchElement };\n }\n },\n { items: [], searchElement: null }\n );\n }, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n const menuClassName = cx(\n { 'Menu--isVirtual': enableVirtualization },\n { [`MenuSize--${menuWidth}`]: menuWidth }\n );\n\n if (enableVirtualization) {\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n <ItemVirtualizer<T>\n items={Children.toArray(reduceItems.items) as ReactElement[]}\n searchElement={reduceItems.searchElement}\n overscan={overscan}\n menuItemClassName={menuItemClassName}\n onSelect={onSelect}\n itemHeight={itemHeight}\n focusManager={focusManager}\n />\n </MenuBase>\n );\n }\n\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n {reduceItems.searchElement}\n <MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n </MenuBase>\n );\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n items: ReactElement[] | null;\n searchElement?: React.ReactElement | null;\n focusManager: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n const {\n overscan,\n searchElement,\n itemHeight = 33,\n menuItemClassName,\n items: items,\n focusManager,\n onSelect,\n } = props;\n\n const menuId = useRef(`menu-ctrl-${v4()}`);\n\n const focusedItemIndex = useRef<number | null>(null);\n const parentRef = useRef<HTMLDivElement | null>(null);\n const searchRef = useRef<HTMLInputElement>();\n\n const [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n const hasSearch = !!searchElement;\n\n const lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n const rowVirtualizer = useVirtual({\n size: items !== null ? items.length : 0,\n parentRef,\n estimateSize: useCallback(() => itemHeight, [itemHeight]),\n overscan,\n });\n\n const focusSearchBar = useCallback(() => {\n rowVirtualizer.scrollToIndex(0);\n searchRef.current?.focus?.();\n }, [rowVirtualizer]);\n\n /**\n * Scrolls to the menu item with the index provided and\n * then manually focuses it using a side effect in useEffect\n */\n const focusMenuItem = useCallback(\n (index: number) => {\n rowVirtualizer.scrollToIndex(index);\n setNextFocusValue(index);\n },\n [rowVirtualizer]\n );\n\n const handleKeyboardFocusInteraction = useCallback(\n (direction: 'next' | 'previous') => {\n if (isNil(focusedItemIndex.current)) {\n return;\n }\n const nextIndex =\n direction === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n const shouldWrap =\n (direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n (direction === 'previous' && focusedItemIndex.current === 0);\n if (shouldWrap) {\n // we are at the end of the list so we will\n // scroll back to the beginning of the list\n if (hasSearch) {\n focusSearchBar();\n } else {\n // if at end, wrap to beginning, else focus last item\n focusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n }\n return;\n }\n switch (direction) {\n case 'next':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusNext();\n break;\n case 'previous':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusPrevious();\n break;\n default:\n break;\n }\n },\n [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]\n );\n\n const getItemProps = useCallback(\n (itemElem: ReactElement, index: number) => {\n const childProps = itemElem.props as MenuItemProps<T>;\n switch (itemElem.type) {\n case MenuItem:\n case MenuItemLink:\n return {\n className: cx(childProps.className, menuItemClassName),\n // set focus on the first menu item if there is no search input, and set in the tab order\n onKeyDown: childProps.disabled\n ? noop\n : (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: handleKeyboardFocusInteraction,\n handleFocusForward: handleKeyboardFocusInteraction,\n }),\n onFocus: chainEventHandlers(childProps.onFocus, () => {\n focusedItemIndex.current = index;\n }),\n id: createItemId(index, menuId.current),\n onBlur: chainEventHandlers(childProps.onBlur, () => {\n focusedItemIndex.current = null;\n }),\n onClick: childProps.disabled\n ? noop\n : chainEventHandlers(childProps.onClick, () => {\n onSelect?.(childProps.item as T);\n }),\n } as MenuItemProps<T>;\n default:\n return {};\n }\n },\n [handleKeyboardFocusInteraction, menuItemClassName, onSelect]\n );\n\n useEffect(() => {\n if (nextFocusValue !== null) {\n requestAnimationFrame(() => {\n const element = getNodeForIndex(nextFocusValue, menuId.current);\n element?.focus();\n });\n setNextFocusValue(null);\n }\n }, [nextFocusValue]);\n\n /**\n * Calls handleFocusForward when the user is attempting to focus forward using\n * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n */\n const handleKeyboardFocusKeydown = (\n e: KeyboardEvent,\n callbacks: Record<\n 'handleFocusForward' | 'handleFocusBackward',\n (direction: 'next' | 'previous') => void\n >\n ) => {\n const keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n if (keyOps.includes(e.key)) {\n e.preventDefault();\n e.stopPropagation();\n if ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n callbacks.handleFocusBackward?.('previous');\n } else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n callbacks.handleFocusForward?.('next');\n }\n }\n };\n\n const renderSearch = useMemo(\n () =>\n searchElement\n ? cloneElement(searchElement, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n handleFocusForward: () => focusMenuItem(0),\n }),\n ref: searchRef,\n })\n : null,\n [searchElement, lastVirtualItemIndex, focusMenuItem]\n );\n\n const renderItems = useMemo(\n () =>\n rowVirtualizer.virtualItems.map((virtualRow) => {\n if (!items) {\n return null;\n }\n const elem = items[virtualRow.index];\n return (\n <div\n key={virtualRow.index}\n ref={\n elem.type !== MenuItem || elem.type !== MenuItemLink\n ? virtualRow.measureRef\n : undefined\n }\n role=\"presentation\"\n className={cx('VirtualMenu-item')}\n style={{\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n {cloneElement(elem, getItemProps(elem, virtualRow.index))}\n </div>\n );\n }),\n [rowVirtualizer.virtualItems, items, getItemProps]\n );\n\n return (\n <>\n {renderSearch}\n <MenuItemList ref={parentRef} role=\"presentation\">\n <div\n role=\"presentation\"\n className=\"VirtualMenu-item-list\"\n style={{\n height: `${rowVirtualizer.totalSize}px`,\n }}\n >\n {renderItems}\n </div>\n </MenuItemList>\n </>\n );\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n", "import type { KeyboardEvent } from 'react';\n\nimport { isFunction } from 'lodash-es';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any;\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n index === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst normalizeIndex = (index: undefined | null | number, delta: number, count: number) => {\n if (index === undefined || index === null) {\n if (delta < 0) {\n return count - 1;\n } else {\n return 0;\n }\n }\n\n let normalized = index + delta;\n if (normalized > count - 1) {\n normalized = 0;\n } else if (normalized < 0) {\n normalized = count - 1;\n }\n return normalized;\n};\n\nconst handleKeyboardInteractions = (\n event: React.KeyboardEvent,\n keyHandlers: Partial<\n Record<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n >\n) => {\n const ops = {\n ArrowUp: keyHandlers.handleUp,\n ArrowDown: keyHandlers.handleDown,\n Enter: keyHandlers.handleEnter,\n } as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n if (ops[event.key]) {\n event.preventDefault();\n ops[event.key]?.call(this, event);\n }\n};\n\nconst chainEventHandlers =\n (...handlers: Array<AnyFunction | undefined>) =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (event: any) => {\n handlers.forEach((h) => isFunction(h) && h(event));\n };\n\nexport {\n createItemId,\n getNodeForIndex,\n normalizeIndex,\n handleKeyboardInteractions,\n chainEventHandlers,\n};\n"],
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;;;ACAvB,kBAAe;AACf,mBAA2B;AAE3B,
|
4
|
+
"sourcesContent": ["export type { MenuBaseProps } from './MenuBase';\nexport type { MenuDividerProps } from './MenuDivider';\nexport type { MenuItemProps, MenuItemLinkProps } from './MenuItem';\nexport type { MenuItemListProps } from './MenuItemList';\nexport type { MenuSearchProps } from './MenuSearch';\nexport type { MenuProps } from './Menu';\nexport { MenuBase } from './MenuBase';\nexport { MenuDivider } from './MenuDivider';\nexport { MenuItem, MenuItemLink } from './MenuItem';\nexport { MenuItemList } from './MenuItemList';\nexport { MenuSearch } from './MenuSearch';\nexport { Menu } from './Menu';\n", "import * as React from 'react';\nexport { React };\n", "import cx from 'clsx';\nimport { forwardRef } from 'react';\n\nimport './styles/Menu.css';\n\ntype MenuBaseProps = React.ComponentPropsWithRef<'div'>;\n\n// This is the pure presentational component that contains menu items\nconst MenuBase = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ children, ...props }, ref) => {\n const className = cx('Menu', props.className);\n return (\n <div {...props} className={className} ref={ref}>\n {children}\n </div>\n );\n }\n);\n\nMenuBase.displayName = 'MenuBase';\n\nexport { MenuBase };\nexport type { MenuBaseProps };\n", "import { SeparatorProps, useSeparator } from '@react-aria/separator';\n\nimport './styles/Menu.css';\n\ntype MenuDividerProps = SeparatorProps & {\n innerRef?: React.RefObject<HTMLDivElement>;\n};\n\nconst MenuDivider = ({ elementType = 'div', orientation, innerRef }: MenuDividerProps) => {\n const { separatorProps } = useSeparator({\n orientation,\n elementType,\n });\n\n return <div {...separatorProps} ref={innerRef} className=\"Menu-divider\" />;\n};\n\nexport { MenuDivider };\nexport type { MenuDividerProps };\n", "import type { PopoverPlacement } from '@launchpad-ui/popover';\n\nimport { Icon, IconSize } from '@launchpad-ui/icons';\nimport { Tooltip } from '@launchpad-ui/tooltip';\nimport { FocusRing } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { Link } from 'react-router-dom';\n\nimport './styles/Menu.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 React.ElementType> = P & { component?: T };\n\ntype PolymorphicPropsWithRef<P, T extends React.ElementType> = Merge<\n T extends keyof JSX.IntrinsicElements\n ? React.PropsWithRef<JSX.IntrinsicElements[T]>\n : React.ComponentPropsWithRef<T>,\n PropsWithComponent<P, T>\n>;\n\ntype MenuItemOwnProps = {\n isHighlighted?: boolean;\n icon?: typeof Icon | null;\n disabled?: boolean;\n nested?: boolean;\n groupHeader?: boolean;\n innerRef?: React.RefObject<HTMLDivElement>;\n tooltip?: string | React.ReactElement;\n tooltipOptions?: typeof Tooltip;\n tooltipPlacement?: PopoverPlacement;\n};\n\nconst defaultElement = 'button';\n\ntype MenuItemProps<\n P,\n T extends React.ElementType = typeof defaultElement\n> = PolymorphicPropsWithRef<\n | (MenuItemOwnProps & {\n item: P; // Infer the type if it is included\n })\n | (MenuItemOwnProps & {\n item?: undefined;\n }),\n T\n>;\n\nconst MenuItem = <P, T extends React.ElementType = typeof defaultElement>({\n ...props\n}: MenuItemProps<P, T>) => {\n const {\n component,\n children,\n isHighlighted,\n icon: Icon,\n nested,\n groupHeader,\n item,\n disabled,\n className,\n innerRef,\n tooltip,\n role = 'menuitem',\n tooltipPlacement,\n onKeyDown,\n tooltipOptions,\n ...rest\n } = props;\n\n const Component: React.ElementType = component || defaultElement;\n\n const renderedItem = (\n <FocusRing focusRingClass=\"has-focus\">\n <Component\n {...rest}\n ref={innerRef}\n disabled={disabled}\n aria-disabled={disabled ? disabled : undefined}\n className={cx(\n 'Menu-item',\n className,\n { 'is-highlighted': isHighlighted },\n { 'Menu-item--nested': nested },\n { 'u-fw-medium': groupHeader }\n )}\n role={role}\n onKeyDown={onKeyDown}\n >\n {Icon && (\n <span className=\"Menu-item-icon\">\n <Icon size={IconSize.SMALL} />\n </span>\n )}\n {children}\n </Component>\n </FocusRing>\n );\n\n if (tooltip) {\n return (\n <Tooltip\n content={tooltip}\n rootElementStyle={{ display: 'block' }}\n allowBoundaryElementOverflow\n placement={tooltipPlacement ? tooltipPlacement : 'bottom'}\n {...(tooltipOptions || {})}\n >\n {renderedItem}\n </Tooltip>\n );\n }\n\n return renderedItem;\n};\n\ntype MenuItemLinkOwnProps = {\n disabled?: boolean;\n useHistory?: boolean;\n newTab?: boolean;\n};\n\ntype MenuItemLinkProps<P, T extends React.ElementType = typeof Link> =\n | Merge<Omit<MenuItemProps<P, T>, 'component' | 'item'>, MenuItemLinkOwnProps> &\n (\n | {\n item?: undefined;\n }\n | {\n item: P;\n }\n );\n\n// By default, this is a Link component whenever useHistory is\n// explicitly not false\nconst MenuItemLink = <P, T extends React.ElementType = typeof Link>({\n to,\n disabled = false,\n useHistory = true,\n newTab = false,\n children,\n ...props\n}: MenuItemLinkProps<P, T>) => {\n const finalProps = {\n ...props,\n disabled,\n component: useHistory ? Link : ('a' as const),\n [useHistory ? 'to' : 'href']: disabled ? '' : to,\n rel: newTab ? 'noopener noreferrer' : undefined,\n target: newTab ? '_blank' : undefined,\n };\n\n // Ideally if this item is disabled, it should be a button rather\n // than a link https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md\n\n return <MenuItem {...finalProps}>{children}</MenuItem>;\n};\n\nexport { MenuItem, MenuItemLink };\nexport type { MenuItemProps, MenuItemLinkProps };\n", "import { forwardRef } from 'react';\n\nimport './styles/Menu.css';\n\ntype MenuItemListProps = Omit<React.ComponentPropsWithRef<'div'>, 'className'>;\n\nconst MenuItemList = forwardRef<HTMLDivElement, MenuItemListProps>(({ children, ...rest }, ref) => (\n <div {...rest} ref={ref} data-test-id=\"menu-item-list\" className=\"Menu-item-list\">\n {children}\n </div>\n));\n\nMenuItemList.displayName = 'MenuItemList';\n\nexport { MenuItemList };\nexport type { MenuItemListProps };\n", "import type { ChangeEvent } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport './styles/Menu.css';\n\ntype MenuSearchProps = {\n ariaLabel?: string;\n value?: string;\n placeholder?: string;\n onChange?(event: ChangeEvent<HTMLInputElement>): void;\n};\n\nconst MenuSearch = forwardRef<HTMLInputElement, MenuSearchProps>((props, ref) => {\n const { ariaLabel, placeholder, ...finalProps } = props;\n\n return (\n <div className=\"Menu-search\">\n <input\n {...finalProps}\n ref={ref}\n className=\"Menu-search-input FormInput FormInput--tiny\"\n type=\"search\"\n autoComplete=\"off\"\n placeholder={placeholder}\n aria-label={ariaLabel || 'Search'}\n />\n <div\n className=\"Menu-search-hidden-placeholder Menu-search-input FormInput FormInput--tiny\"\n aria-hidden=\"true\"\n >\n {placeholder}\n </div>\n </div>\n );\n});\n\nMenuSearch.displayName = 'MenuSearch';\n\nexport { MenuSearch };\nexport type { MenuSearchProps };\n", "import type { KeyboardEvent, ReactElement } from 'react';\n\nimport { FocusManager, useFocusManager } from '@react-aria/focus';\nimport cx from 'clsx';\nimport { isNil, noop } from 'lodash-es';\nimport { Children, cloneElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useVirtual } from 'react-virtual';\nimport { v4 } from 'uuid';\n\nimport { MenuBase } from './MenuBase';\nimport { MenuDivider } from './MenuDivider';\nimport { MenuItem, MenuItemLink, MenuItemProps } from './MenuItem';\nimport { MenuItemList } from './MenuItemList';\nimport { MenuSearch } from './MenuSearch';\nimport {\n chainEventHandlers,\n createItemId,\n getNodeForIndex,\n handleKeyboardInteractions,\n} from './utils';\n\ntype ControlledMenuProps<T> = {\n children: React.ReactNode;\n onSelect?: (item: T) => void;\n /**\n * Menus items are rendered using react-virtual for\n * additional rendering performance.\n */\n enableVirtualization?: boolean;\n /**\n * Class name to be applied to all MenuItem and MenuItemLink components\n * in the menu.\n */\n menuItemClassName?: string;\n /**\n * Sets the width of the menu. This is especially useful when using virtual items\n * since the width cannot be automatically set by the widest element.\n */\n menuWidth?: 'tiny' | 'small' | 'med' | 'large' | 'xLarge';\n /**\n * Sets the number out of elements rendered outside of the view window\n * when using virtualization\n */\n overscan?: number;\n /**\n * Sets the height for each menu item when using virtualization.\n *\n */\n itemHeight?: number;\n};\n\ntype MenuProps<T extends number | string> = ControlledMenuProps<T>;\n\nconst Menu = <T extends number | string>(props: MenuProps<T>) => {\n const {\n children,\n menuItemClassName,\n onSelect,\n enableVirtualization,\n itemHeight,\n menuWidth,\n overscan = 1,\n } = props;\n\n const focusManager = useFocusManager();\n\n const handleArrowDown = useCallback(() => {\n focusManager.focusNext({ wrap: true });\n }, [focusManager]);\n\n const handleArrowUp = useCallback(() => {\n focusManager.focusPrevious({ wrap: true });\n }, [focusManager]);\n\n const reduceItems = useMemo(() => {\n const childrenProps = Children.toArray(children);\n if (enableVirtualization) {\n // the virtualized menu has its own handlers and props\n let searchElem = null;\n let elements: ReactElement[] = [];\n (childrenProps as ReactElement[]).forEach((child: ReactElement) => {\n switch (child.type) {\n case MenuSearch:\n searchElem = child;\n break;\n case MenuItem:\n case MenuItemLink:\n case MenuDivider:\n elements = elements.concat(child);\n break;\n default:\n break;\n }\n });\n return { items: elements, searchElement: searchElem };\n }\n\n return (childrenProps as ReactElement[]).reduce(\n (\n { items, searchElement }: { items: ReactElement[]; searchElement: null | ReactElement },\n child\n ) => {\n switch (child.type) {\n case MenuSearch:\n return {\n items,\n searchElement: cloneElement(child, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n }),\n };\n case MenuItem:\n case MenuItemLink:\n return {\n items: items.concat(\n child.props.disabled\n ? cloneElement(child, {\n onClick: noop,\n onKeyDown: noop,\n tabIndex: -1,\n disabled: true,\n })\n : cloneElement(child, {\n className: cx(child.props.className, menuItemClassName),\n item: child.props.item ?? items.length,\n // set focus on the first menu item if there is no search input, and set in the tab order\n onClick: chainEventHandlers(child.props.onClick, () => {\n onSelect?.(child.props.item ?? items.length);\n }),\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardInteractions(e, {\n handleDown: handleArrowDown,\n handleUp: handleArrowUp,\n }),\n })\n ),\n searchElement,\n };\n case MenuDivider:\n return { items: items.concat(child), searchElement };\n default:\n return { items, searchElement };\n }\n },\n { items: [], searchElement: null }\n );\n }, [children, enableVirtualization, menuItemClassName, handleArrowDown, handleArrowUp, onSelect]);\n\n const menuClassName = cx(\n { 'Menu--isVirtual': enableVirtualization },\n { [`MenuSize--${menuWidth}`]: menuWidth }\n );\n\n if (enableVirtualization) {\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n <ItemVirtualizer<T>\n items={Children.toArray(reduceItems.items) as ReactElement[]}\n searchElement={reduceItems.searchElement}\n overscan={overscan}\n menuItemClassName={menuItemClassName}\n onSelect={onSelect}\n itemHeight={itemHeight}\n focusManager={focusManager}\n />\n </MenuBase>\n );\n }\n\n return (\n <MenuBase role=\"menu\" className={menuClassName}>\n {reduceItems.searchElement}\n <MenuItemList role=\"presentation\">{reduceItems.items}</MenuItemList>\n </MenuBase>\n );\n};\n\ntype ItemVirtualizerProps<T> = Omit<ControlledMenuProps<T>, 'children'> & {\n items: ReactElement[] | null;\n searchElement?: React.ReactElement | null;\n focusManager: FocusManager;\n};\n\nconst ItemVirtualizer = <T extends number | string>(props: ItemVirtualizerProps<T>) => {\n const {\n overscan,\n searchElement,\n itemHeight = 33,\n menuItemClassName,\n items: items,\n focusManager,\n onSelect,\n } = props;\n\n const menuId = useRef(`menu-ctrl-${v4()}`);\n\n const focusedItemIndex = useRef<number | null>(null);\n const parentRef = useRef<HTMLDivElement | null>(null);\n const searchRef = useRef<HTMLInputElement>();\n\n const [nextFocusValue, setNextFocusValue] = useState<number | null>(null);\n\n const hasSearch = !!searchElement;\n\n const lastVirtualItemIndex = items ? items.length - 1 : 0;\n\n const rowVirtualizer = useVirtual({\n size: items !== null ? items.length : 0,\n parentRef,\n estimateSize: useCallback(() => itemHeight, [itemHeight]),\n overscan,\n });\n\n const focusSearchBar = useCallback(() => {\n rowVirtualizer.scrollToIndex(0);\n searchRef.current?.focus?.();\n }, [rowVirtualizer]);\n\n /**\n * Scrolls to the menu item with the index provided and\n * then manually focuses it using a side effect in useEffect\n */\n const focusMenuItem = useCallback(\n (index: number) => {\n rowVirtualizer.scrollToIndex(index);\n setNextFocusValue(index);\n },\n [rowVirtualizer]\n );\n\n const handleKeyboardFocusInteraction = useCallback(\n (direction: 'next' | 'previous') => {\n if (isNil(focusedItemIndex.current)) {\n return;\n }\n const nextIndex =\n direction === 'next' ? focusedItemIndex.current + 1 : focusedItemIndex.current - 1;\n const shouldWrap =\n (direction === 'next' && focusedItemIndex.current === lastVirtualItemIndex) ||\n (direction === 'previous' && focusedItemIndex.current === 0);\n if (shouldWrap) {\n // we are at the end of the list so we will\n // scroll back to the beginning of the list\n if (hasSearch) {\n focusSearchBar();\n } else {\n // if at end, wrap to beginning, else focus last item\n focusMenuItem(direction === 'next' ? 0 : lastVirtualItemIndex);\n }\n return;\n }\n switch (direction) {\n case 'next':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusNext();\n break;\n case 'previous':\n rowVirtualizer.scrollToIndex(nextIndex);\n focusManager.focusPrevious();\n break;\n default:\n break;\n }\n },\n [focusManager, focusMenuItem, focusSearchBar, hasSearch, lastVirtualItemIndex, rowVirtualizer]\n );\n\n const getItemProps = useCallback(\n (itemElem: ReactElement, index: number) => {\n const childProps = itemElem.props as MenuItemProps<T>;\n switch (itemElem.type) {\n case MenuItem:\n case MenuItemLink:\n return {\n className: cx(childProps.className, menuItemClassName),\n // set focus on the first menu item if there is no search input, and set in the tab order\n onKeyDown: childProps.disabled\n ? noop\n : (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: handleKeyboardFocusInteraction,\n handleFocusForward: handleKeyboardFocusInteraction,\n }),\n onFocus: chainEventHandlers(childProps.onFocus, () => {\n focusedItemIndex.current = index;\n }),\n id: createItemId(index, menuId.current),\n onBlur: chainEventHandlers(childProps.onBlur, () => {\n focusedItemIndex.current = null;\n }),\n onClick: childProps.disabled\n ? noop\n : chainEventHandlers(childProps.onClick, () => {\n onSelect?.(childProps.item as T);\n }),\n } as MenuItemProps<T>;\n default:\n return {};\n }\n },\n [handleKeyboardFocusInteraction, menuItemClassName, onSelect]\n );\n\n useEffect(() => {\n if (nextFocusValue !== null) {\n requestAnimationFrame(() => {\n const element = getNodeForIndex(nextFocusValue, menuId.current);\n element?.focus();\n });\n setNextFocusValue(null);\n }\n }, [nextFocusValue]);\n\n /**\n * Calls handleFocusForward when the user is attempting to focus forward using\n * tab or arrow keys. Calls handleFocusBackward when the users wants to move backward.\n */\n const handleKeyboardFocusKeydown = (\n e: KeyboardEvent,\n callbacks: Record<\n 'handleFocusForward' | 'handleFocusBackward',\n (direction: 'next' | 'previous') => void\n >\n ) => {\n const keyOps = ['Tab', 'ArrowUp', 'ArrowDown'];\n if (keyOps.includes(e.key)) {\n e.preventDefault();\n e.stopPropagation();\n if ((e.key === 'Tab' && e.shiftKey) || e.key === 'ArrowUp') {\n callbacks.handleFocusBackward?.('previous');\n } else if (e.key === 'ArrowDown' || e.key === 'Tab') {\n callbacks.handleFocusForward?.('next');\n }\n }\n };\n\n const renderSearch = useMemo(\n () =>\n searchElement\n ? cloneElement(searchElement, {\n onKeyDown: (e: KeyboardEvent) =>\n handleKeyboardFocusKeydown(e, {\n handleFocusBackward: () => focusMenuItem(lastVirtualItemIndex),\n handleFocusForward: () => focusMenuItem(0),\n }),\n ref: searchRef,\n })\n : null,\n [searchElement, lastVirtualItemIndex, focusMenuItem]\n );\n\n const renderItems = useMemo(\n () =>\n rowVirtualizer.virtualItems.map((virtualRow) => {\n if (!items) {\n return null;\n }\n const elem = items[virtualRow.index];\n return (\n <div\n key={virtualRow.index}\n ref={\n elem.type !== MenuItem || elem.type !== MenuItemLink\n ? virtualRow.measureRef\n : undefined\n }\n role=\"presentation\"\n className={cx('VirtualMenu-item')}\n style={{\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n {cloneElement(elem, getItemProps(elem, virtualRow.index))}\n </div>\n );\n }),\n [rowVirtualizer.virtualItems, items, getItemProps]\n );\n\n return (\n <>\n {renderSearch}\n <MenuItemList ref={parentRef} role=\"presentation\">\n <div\n role=\"presentation\"\n className=\"VirtualMenu-item-list\"\n style={{\n height: `${rowVirtualizer.totalSize}px`,\n }}\n >\n {renderItems}\n </div>\n </MenuItemList>\n </>\n );\n};\n\nexport { Menu, ItemVirtualizer };\nexport type { MenuProps, ItemVirtualizerProps };\n", "import type { KeyboardEvent } from 'react';\n\nimport { isFunction } from 'lodash-es';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFunction = (...args: any[]) => any;\n\nconst createItemId = (index: number, id: string) => `${id}-item-${index}`;\n\nconst getNodeForIndex = (index: number | null, menuId: string) =>\n index === null ? index : document.getElementById(createItemId(index, menuId));\n\nconst normalizeIndex = (index: undefined | null | number, delta: number, count: number) => {\n if (index === undefined || index === null) {\n if (delta < 0) {\n return count - 1;\n } else {\n return 0;\n }\n }\n\n let normalized = index + delta;\n if (normalized > count - 1) {\n normalized = 0;\n } else if (normalized < 0) {\n normalized = count - 1;\n }\n return normalized;\n};\n\nconst handleKeyboardInteractions = (\n event: React.KeyboardEvent,\n keyHandlers: Partial<\n Record<'handleUp' | 'handleDown' | 'handleEnter', (e: KeyboardEvent) => void>\n >\n) => {\n const ops = {\n ArrowUp: keyHandlers.handleUp,\n ArrowDown: keyHandlers.handleDown,\n Enter: keyHandlers.handleEnter,\n } as Record<string, (e: KeyboardEvent) => void | undefined>;\n\n if (ops[event.key]) {\n event.preventDefault();\n ops[event.key]?.call(this, event);\n }\n};\n\nconst chainEventHandlers =\n (...handlers: Array<AnyFunction | undefined>) =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (event: any) => {\n handlers.forEach((h) => isFunction(h) && h(event));\n };\n\nexport {\n createItemId,\n getNodeForIndex,\n normalizeIndex,\n handleKeyboardInteractions,\n chainEventHandlers,\n};\n"],
|
5
|
+
"mappings": "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",
|
6
6
|
"names": []
|
7
7
|
}
|
@@ -1,2 +1,2 @@
|
|
1
1
|
.Menu:focus{outline:none}:is(.Menu [hidden]:first-child+.Menu .Menu-item-list,.Menu .Menu-item-list:first-child)>.Menu-item:first-child,:is(.Menu [hidden]:first-child+.Menu .Menu-item-list,.Menu .Menu-item-list:first-child)>.VirtualMenu-item-list .VirtualMenu-item:first-child .Menu-item{border-top-left-radius:var(--border-radius);border-top-right-radius:var(--border-radius)}.Menu-item-list{min-width:12rem;max-height:55vh;overflow:auto}.Menu-item-list>.Menu-item:last-child,.Menu-item-list>.VirtualMenu-item-list .VirtualMenu-item:last-child .Menu-item{border-bottom-left-radius:var(--border-radius);border-bottom-right-radius:var(--border-radius)}.Menu-item-list:first-child{border-top-left-radius:var(--border-radius);border-top-right-radius:var(--border-radius)}.Menu-item-list:last-child{border-bottom-left-radius:var(--border-radius);border-bottom-right-radius:var(--border-radius)}.Menu-item{color:var(--color-black-300);background:var(--color-white);cursor:pointer;text-align:left;text-overflow:ellipsis;white-space:nowrap;-webkit-user-select:none;user-select:none;font-size:1.3rem;line-height:inherit;width:100%;border-width:0;outline:none;padding:.6rem 2.5rem;text-decoration:none;display:block;position:relative;overflow:hidden}.Menu .Menu-item:not([disabled],[aria-disabled]):hover:not(:active,.has-focus){background-color:var(--color-gray-100);box-shadow:inset 0 0 0 1px var(--color-gray-600)}.Menu .Menu-item:not([disabled],[aria-disabled]).has-focus{background-color:var(--color-gray-100);box-shadow:inset 0 0 0 2px var(--color-blue-500)}.Menu .Menu-item:not([disabled],[aria-disabled]):active{box-shadow:none;background-color:var(--color-blue-200);color:var(--color-blue-600);text-decoration:none}.Menu a.Menu-item:focus:not(:hover,.has-focus){box-shadow:none;text-decoration:none}.Menu a.Menu-item:active[disabled],.Menu a.Menu-item:active[aria-disabled]{color:var(--color-gray-800);text-decoration:none}.Menu-item--nested{padding-left:4rem}.Menu-item .Gravatar{margin-right:.5rem}.Menu-item.is-highlighted{background-color:var(--color-gray-100);box-shadow:inset 0 0 0 1px var(--color-gray-600)}.Menu-item.is-highlighted:active{background-color:var(--color-blue-200);color:var(--color-blue-600);box-shadow:none}.Menu-item[aria-disabled],.Menu-item[disabled]{color:var(--color-gray-800);cursor:default}.Menu-item-icon{position:absolute;top:50%;left:.5rem;transform:translateY(-50%)}.Menu-divider{border-top:1px solid var(--color-gray-200)}.Menu-search{border-bottom:1px solid var(--color-gray-200);padding:1rem;font-size:1.3rem}.Menu-search:first-child{border-top-left-radius:var(--border-radius);border-top-right-radius:var(--border-radius)}.Menu-clear.Button{color:var(--color-system-red-600);font-size:1.3rem;font-weight:var(--font-weight-medium);width:100%;border-bottom:1px solid var(--color-gray-200);padding:1rem;text-decoration:none}.Menu-clear.Button:active,.Menu-clear.Button:focus,.Menu-clear.Button:hover{box-shadow:unset;color:var(--color-system-red-600);border-bottom-color:var(--color-gray-200);background-color:var(--color-gray-100);outline:none}.Popover-content .Menu-search{width:100%}.Popover-content .Menu-search .Menu-search-hidden-placeholder{height:0;visibility:hidden;border:none;padding-top:0;padding-bottom:0}.Menu--isVirtual{flex-direction:column;align-items:stretch;display:flex}.MenuSize--xLarge{width:32rem}.MenuSize--large{width:24rem}.MenuSize--med{width:16rem}.MenuSize--small{width:12rem}.VirtualMenu-item-list{width:100%;position:relative}.VirtualMenu-item{width:100%;position:absolute;top:0;left:0}
|
2
|
-
/*# sourceMappingURL=
|
2
|
+
/*# sourceMappingURL=Menu.css.map */
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"mappings":"AAEE,yBAME,gWAYJ,8DAME,oNAWF,qHAKA,0HAKA,+VAuBI,uKAKA,mJAKA,gKAUA,oFAMA,4HAQJ,qCAIA,wCAIA,kHAIE,oHAOF,0FAMA,gFAOA,yDAIA,yFAMA,kHAKA,uMAUA,6NAUA,yCAIE,oIASF,wEAMA,8BAIA,6BAIA,2BAIA,6BAIA,oDAKA","sources":["src/styles/Menu.css"],"sourcesContent":["/* stylelint-disable no-descending-specificity */\n.Menu {\n &:focus {\n outline: none;\n }\n\n & [hidden]:first-child + & .Menu-item-list,\n & .Menu-item-list:first-child {\n & > .Menu-item:first-child {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n }\n\n & > .VirtualMenu-item-list .VirtualMenu-item:first-child .Menu-item {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n }\n }\n}\n\n.Menu-item-list {\n min-width: 12rem;\n overflow: auto;\n max-height: 55vh;\n\n /* use the child selector due to MenuItems being nested in divs for virtualization */\n & > .Menu-item:last-child {\n border-bottom-left-radius: var(--border-radius);\n border-bottom-right-radius: var(--border-radius);\n }\n\n & > .VirtualMenu-item-list .VirtualMenu-item:last-child .Menu-item {\n border-bottom-left-radius: var(--border-radius);\n border-bottom-right-radius: var(--border-radius);\n }\n}\n\n.Menu-item-list:first-child {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n}\n\n.Menu-item-list:last-child {\n border-bottom-left-radius: var(--border-radius);\n border-bottom-right-radius: var(--border-radius);\n}\n\n.Menu-item {\n display: block;\n position: relative;\n color: var(--color-black-300);\n background: var(--color-white);\n text-decoration: none;\n cursor: pointer;\n outline: none;\n padding: 0.6rem 2.5rem;\n text-align: left;\n font-size: 1.3rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n user-select: none;\n line-height: inherit;\n border-width: 0;\n width: 100%;\n}\n\n/* stylelint-disable-next-line no-duplicate-selectors */\n.Menu {\n & .Menu-item:not([disabled], [aria-disabled]) {\n &:hover:not(:active, .has-focus) {\n background-color: var(--color-gray-100);\n box-shadow: inset 0 0 0 1px var(--color-gray-600);\n }\n\n &.has-focus {\n background-color: var(--color-gray-100);\n box-shadow: inset 0 0 0 2px var(--color-blue-500);\n }\n\n &:active {\n text-decoration: none;\n box-shadow: none;\n background-color: var(--color-blue-200);\n color: var(--color-blue-600);\n }\n }\n\n /* Override our link styles for MenuItemLink component */\n & a.Menu-item {\n &:focus:not(:hover, .has-focus) {\n text-decoration: none;\n box-shadow: none;\n }\n\n /* Ensures that links that are disabled don't show active styles */\n &:active[disabled],\n &:active[aria-disabled] {\n text-decoration: none;\n color: var(--color-gray-800);\n }\n }\n}\n\n.Menu-item--nested {\n padding-left: 4rem;\n}\n\n.Menu-item .Gravatar {\n margin-right: 0.5rem;\n}\n\n.Menu-item.is-highlighted {\n background-color: var(--color-gray-100);\n box-shadow: inset 0 0 0 1px var(--color-gray-600);\n\n &:active {\n background-color: var(--color-blue-200);\n color: var(--color-blue-600);\n box-shadow: none;\n }\n}\n\n.Menu-item[aria-disabled],\n.Menu-item[disabled] {\n color: var(--color-gray-800);\n cursor: default;\n}\n\n.Menu-item-icon {\n position: absolute;\n left: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.Menu-divider {\n border-top: 1px solid var(--color-gray-200);\n}\n\n.Menu-search {\n padding: 1rem;\n font-size: 1.3rem;\n border-bottom: 1px solid var(--color-gray-200);\n}\n\n.Menu-search:first-child {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n}\n\n.Menu-clear.Button {\n text-decoration: none;\n color: var(--color-system-red-600);\n font-size: 1.3rem;\n font-weight: var(--font-weight-medium);\n padding: 1rem;\n width: 100%;\n border-bottom: 1px solid var(--color-gray-200);\n}\n\n.Menu-clear.Button:active,\n.Menu-clear.Button:focus,\n.Menu-clear.Button:hover {\n outline: none;\n box-shadow: unset;\n color: var(--color-system-red-600);\n border-bottom-color: var(--color-gray-200);\n background-color: var(--color-gray-100);\n}\n\n.Popover-content .Menu-search {\n width: 100%;\n\n /* Removing anything that could give it some height */\n & .Menu-search-hidden-placeholder {\n padding-top: 0;\n padding-bottom: 0;\n height: 0;\n border: none;\n visibility: hidden;\n }\n}\n\n.Menu--isVirtual {\n display: flex;\n align-items: stretch;\n flex-direction: column;\n}\n\n.MenuSize--xLarge {\n width: 32rem;\n}\n\n.MenuSize--large {\n width: 24rem;\n}\n\n.MenuSize--med {\n width: 16rem;\n}\n\n.MenuSize--small {\n width: 12rem;\n}\n\n.VirtualMenu-item-list {\n width: 100%;\n position: relative;\n}\n\n.VirtualMenu-item {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n}\n"],"names":[]}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@launchpad-ui/menu",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.2.0",
|
4
4
|
"publishConfig": {
|
5
5
|
"access": "public"
|
6
6
|
},
|
@@ -21,14 +21,14 @@
|
|
21
21
|
"require": "./dist/index.js"
|
22
22
|
},
|
23
23
|
"./package.json": "./package.json",
|
24
|
-
"./styles
|
24
|
+
"./styles/*": "./dist/styles/*"
|
25
25
|
},
|
26
26
|
"source": "src/index.ts",
|
27
27
|
"dependencies": {
|
28
|
-
"@launchpad-ui/icons": "~0.
|
29
|
-
"@launchpad-ui/popover": "~0.
|
28
|
+
"@launchpad-ui/icons": "~0.2.0",
|
29
|
+
"@launchpad-ui/popover": "~0.2.0",
|
30
30
|
"@launchpad-ui/tokens": "~0.1.4",
|
31
|
-
"@launchpad-ui/tooltip": "~0.
|
31
|
+
"@launchpad-ui/tooltip": "~0.2.0",
|
32
32
|
"@react-aria/focus": "^3.6.0",
|
33
33
|
"@react-aria/separator": "^3.2.0",
|
34
34
|
"clsx": "^1.1.1",
|
@@ -45,8 +45,8 @@
|
|
45
45
|
"@types/lodash-es": "^4.17.6",
|
46
46
|
"@types/react-router-dom": "^5.3.3",
|
47
47
|
"@types/uuid": "^8.3.4",
|
48
|
-
"react": "^18.
|
49
|
-
"react-dom": "^18.
|
48
|
+
"react": "^18.2.0",
|
49
|
+
"react-dom": "^18.2.0"
|
50
50
|
},
|
51
51
|
"scripts": {
|
52
52
|
"build": "tsc --project tsconfig.build.json && node build.js",
|
package/dist/styles.css.map
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"mappings":"AAEE,yBAME,gWAYJ,8DAME,oNAWF,qHAKA,0HAKA,+VAuBI,uKAKA,mJAKA,gKAUA,oFAMA,4HAQJ,qCAIA,wCAIA,kHAIE,oHAOF,0FAMA,gFAOA,yDAIA,yFAMA,kHAKA,uMAUA,6NAUA,yCAIE,oIASF,wEAMA,8BAIA,6BAIA,2BAIA,6BAIA,oDAKA","sources":["src/styles.css"],"sourcesContent":["/* stylelint-disable no-descending-specificity */\n.Menu {\n &:focus {\n outline: none;\n }\n\n & [hidden]:first-child + & .Menu-item-list,\n & .Menu-item-list:first-child {\n & > .Menu-item:first-child {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n }\n\n & > .VirtualMenu-item-list .VirtualMenu-item:first-child .Menu-item {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n }\n }\n}\n\n.Menu-item-list {\n min-width: 12rem;\n overflow: auto;\n max-height: 55vh;\n\n /* use the child selector due to MenuItems being nested in divs for virtualization */\n & > .Menu-item:last-child {\n border-bottom-left-radius: var(--border-radius);\n border-bottom-right-radius: var(--border-radius);\n }\n\n & > .VirtualMenu-item-list .VirtualMenu-item:last-child .Menu-item {\n border-bottom-left-radius: var(--border-radius);\n border-bottom-right-radius: var(--border-radius);\n }\n}\n\n.Menu-item-list:first-child {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n}\n\n.Menu-item-list:last-child {\n border-bottom-left-radius: var(--border-radius);\n border-bottom-right-radius: var(--border-radius);\n}\n\n.Menu-item {\n display: block;\n position: relative;\n color: var(--color-black-300);\n background: var(--color-white);\n text-decoration: none;\n cursor: pointer;\n outline: none;\n padding: 0.6rem 2.5rem;\n text-align: left;\n font-size: 1.3rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n user-select: none;\n line-height: inherit;\n border-width: 0;\n width: 100%;\n}\n\n/* stylelint-disable-next-line no-duplicate-selectors */\n.Menu {\n & .Menu-item:not([disabled], [aria-disabled]) {\n &:hover:not(:active, .has-focus) {\n background-color: var(--color-gray-100);\n box-shadow: inset 0 0 0 1px var(--color-gray-600);\n }\n\n &.has-focus {\n background-color: var(--color-gray-100);\n box-shadow: inset 0 0 0 2px var(--color-blue-500);\n }\n\n &:active {\n text-decoration: none;\n box-shadow: none;\n background-color: var(--color-blue-200);\n color: var(--color-blue-600);\n }\n }\n\n /* Override our link styles for MenuItemLink component */\n & a.Menu-item {\n &:focus:not(:hover, .has-focus) {\n text-decoration: none;\n box-shadow: none;\n }\n\n /* Ensures that links that are disabled don't show active styles */\n &:active[disabled],\n &:active[aria-disabled] {\n text-decoration: none;\n color: var(--color-gray-800);\n }\n }\n}\n\n.Menu-item--nested {\n padding-left: 4rem;\n}\n\n.Menu-item .Gravatar {\n margin-right: 0.5rem;\n}\n\n.Menu-item.is-highlighted {\n background-color: var(--color-gray-100);\n box-shadow: inset 0 0 0 1px var(--color-gray-600);\n\n &:active {\n background-color: var(--color-blue-200);\n color: var(--color-blue-600);\n box-shadow: none;\n }\n}\n\n.Menu-item[aria-disabled],\n.Menu-item[disabled] {\n color: var(--color-gray-800);\n cursor: default;\n}\n\n.Menu-item-icon {\n position: absolute;\n left: 0.5rem;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.Menu-divider {\n border-top: 1px solid var(--color-gray-200);\n}\n\n.Menu-search {\n padding: 1rem;\n font-size: 1.3rem;\n border-bottom: 1px solid var(--color-gray-200);\n}\n\n.Menu-search:first-child {\n border-top-left-radius: var(--border-radius);\n border-top-right-radius: var(--border-radius);\n}\n\n.Menu-clear.Button {\n text-decoration: none;\n color: var(--color-system-red-600);\n font-size: 1.3rem;\n font-weight: var(--font-weight-medium);\n padding: 1rem;\n width: 100%;\n border-bottom: 1px solid var(--color-gray-200);\n}\n\n.Menu-clear.Button:active,\n.Menu-clear.Button:focus,\n.Menu-clear.Button:hover {\n outline: none;\n box-shadow: unset;\n color: var(--color-system-red-600);\n border-bottom-color: var(--color-gray-200);\n background-color: var(--color-gray-100);\n}\n\n.Popover-content .Menu-search {\n width: 100%;\n\n /* Removing anything that could give it some height */\n & .Menu-search-hidden-placeholder {\n padding-top: 0;\n padding-bottom: 0;\n height: 0;\n border: none;\n visibility: hidden;\n }\n}\n\n.Menu--isVirtual {\n display: flex;\n align-items: stretch;\n flex-direction: column;\n}\n\n.MenuSize--xLarge {\n width: 32rem;\n}\n\n.MenuSize--large {\n width: 24rem;\n}\n\n.MenuSize--med {\n width: 16rem;\n}\n\n.MenuSize--small {\n width: 12rem;\n}\n\n.VirtualMenu-item-list {\n width: 100%;\n position: relative;\n}\n\n.VirtualMenu-item {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n}\n"],"names":[]}
|