@launchpad-ui/dropdown 0.3.5 → 0.4.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/Dropdown.d.ts.map +1 -1
- package/dist/DropdownButton.d.ts +4 -4
- package/dist/DropdownButton.d.ts.map +1 -1
- package/dist/index.es.js +32 -40
- package/dist/index.es.js.map +1 -7
- package/dist/index.js +47 -89
- package/dist/index.js.map +1 -7
- package/package.json +6 -6
package/dist/Dropdown.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../src/Dropdown.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
1
|
+
{"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../src/Dropdown.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAO1D,aAAK,aAAa,GAAG;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,aAAK,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,YAAY,GAAG;IACtE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,YAAY,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF,QAAA,MAAM,QAAQ,8EAoGb,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,CAAC"}
|
package/dist/DropdownButton.d.ts
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
/// <reference types="react" />
|
2
1
|
import type { ButtonKind, ButtonSize } from '@launchpad-ui/button';
|
2
|
+
import type { MouseEvent, ReactNode } from 'react';
|
3
3
|
declare type DropdownButtonProps = {
|
4
4
|
hideCaret?: boolean;
|
5
5
|
kind?: ButtonKind;
|
6
6
|
size?: ButtonSize;
|
7
7
|
className?: string;
|
8
8
|
disabled?: boolean;
|
9
|
-
children?:
|
10
|
-
onClick?(v:
|
9
|
+
children?: ReactNode;
|
10
|
+
onClick?(v: MouseEvent): void;
|
11
11
|
testId?: string;
|
12
12
|
'aria-label'?: string;
|
13
13
|
};
|
14
|
-
declare const DropdownButton: import("react").ForwardRefExoticComponent<DropdownButtonProps & import("react").RefAttributes<
|
14
|
+
declare const DropdownButton: import("react").ForwardRefExoticComponent<DropdownButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
15
15
|
export { DropdownButton };
|
16
16
|
export type { DropdownButtonProps };
|
17
17
|
//# sourceMappingURL=DropdownButton.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"DropdownButton.d.ts","sourceRoot":"","sources":["../src/DropdownButton.tsx"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"DropdownButton.d.ts","sourceRoot":"","sources":["../src/DropdownButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAc,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAM/D,aAAK,mBAAmB,GAAG;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,QAAA,MAAM,cAAc,mHAQlB,CAAC;AAIH,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
package/dist/index.es.js
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
// ../../scripts/react-shim.js
|
2
|
-
import * as React from "react";
|
3
|
-
|
4
|
-
// src/Dropdown.tsx
|
5
1
|
import { Popover } from "@launchpad-ui/popover";
|
6
|
-
import cx from "
|
7
|
-
import {
|
8
|
-
import { jsxs } from "react/jsx-runtime";
|
9
|
-
|
2
|
+
import { cx } from "classix";
|
3
|
+
import { useRef, useState, useEffect, cloneElement, Children, forwardRef } from "react";
|
4
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
5
|
+
import { Button } from "@launchpad-ui/button";
|
6
|
+
import { ExpandMore, IconSize } from "@launchpad-ui/icons";
|
7
|
+
const Dropdown = (props) => {
|
10
8
|
const {
|
11
9
|
placement,
|
12
10
|
disabled,
|
@@ -20,7 +18,7 @@ var Dropdown = (props) => {
|
|
20
18
|
...rest
|
21
19
|
} = props;
|
22
20
|
const triggerRef = useRef(null);
|
23
|
-
const [isOpen, setIsOpen] = useState(isOpenProp
|
21
|
+
const [isOpen, setIsOpen] = useState(isOpenProp != null ? isOpenProp : false);
|
24
22
|
const [hasOpened, setHasOpened] = useState(isOpen);
|
25
23
|
useEffect(() => {
|
26
24
|
if (isOpenProp !== void 0) {
|
@@ -30,25 +28,28 @@ var Dropdown = (props) => {
|
|
30
28
|
useEffect(() => {
|
31
29
|
if (hasOpened && isOpen === false) {
|
32
30
|
setTimeout(() => {
|
31
|
+
var _a, _b;
|
33
32
|
const current = triggerRef.current;
|
34
33
|
if (!current) {
|
35
34
|
return;
|
36
35
|
}
|
37
|
-
const hasModal = current.closest
|
38
|
-
!hasModal && current.focus
|
36
|
+
const hasModal = (_a = current.closest) == null ? void 0 : _a.call(current, ".has-modal");
|
37
|
+
!hasModal && ((_b = current.focus) == null ? void 0 : _b.call(current));
|
39
38
|
});
|
40
39
|
}
|
41
40
|
}, [isOpen, hasOpened]);
|
42
41
|
useEffect(() => {
|
43
42
|
setHasOpened(isOpen);
|
44
|
-
onStateChange
|
43
|
+
onStateChange == null ? void 0 : onStateChange({
|
44
|
+
isOpen
|
45
|
+
});
|
45
46
|
}, [isOpen]);
|
46
47
|
const renderTrigger = () => {
|
47
48
|
return cloneElement(parseChildren().target, {
|
48
49
|
"aria-haspopup": true,
|
49
50
|
"aria-expanded": isOpen ? true : false,
|
50
51
|
ref: triggerRef,
|
51
|
-
isopen: isOpen
|
52
|
+
isopen: isOpen == null ? void 0 : isOpen.toString()
|
52
53
|
});
|
53
54
|
};
|
54
55
|
const renderContent = () => {
|
@@ -58,7 +59,9 @@ var Dropdown = (props) => {
|
|
58
59
|
};
|
59
60
|
const handleSelect = (item) => {
|
60
61
|
setIsOpen(false);
|
61
|
-
onSelect
|
62
|
+
onSelect == null ? void 0 : onSelect(item, {
|
63
|
+
isOpen: false
|
64
|
+
});
|
62
65
|
};
|
63
66
|
const handlePopoverInteraction = (nextIsOpen) => {
|
64
67
|
setIsOpen(nextIsOpen);
|
@@ -81,34 +84,23 @@ var Dropdown = (props) => {
|
|
81
84
|
targetClassName: popoverTargetClasses,
|
82
85
|
popoverClassName: popoverClasses,
|
83
86
|
...rest,
|
84
|
-
children: [
|
85
|
-
renderTrigger(),
|
86
|
-
renderContent()
|
87
|
-
]
|
87
|
+
children: [renderTrigger(), renderContent()]
|
88
88
|
});
|
89
89
|
};
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
" ",
|
105
|
-
!hideCaret && /* @__PURE__ */ jsx(ExpandMore, {
|
106
|
-
size: IconSize.SMALL
|
107
|
-
})
|
108
|
-
]
|
109
|
-
});
|
110
|
-
}
|
111
|
-
);
|
90
|
+
const DropdownButton = forwardRef((props, ref) => {
|
91
|
+
const {
|
92
|
+
children,
|
93
|
+
hideCaret,
|
94
|
+
...rest
|
95
|
+
} = props;
|
96
|
+
return /* @__PURE__ */ jsxs(Button, {
|
97
|
+
...rest,
|
98
|
+
ref,
|
99
|
+
children: [children, " ", !hideCaret && /* @__PURE__ */ jsx(ExpandMore, {
|
100
|
+
size: IconSize.SMALL
|
101
|
+
})]
|
102
|
+
});
|
103
|
+
});
|
112
104
|
DropdownButton.displayName = "DropdownButton";
|
113
105
|
export {
|
114
106
|
Dropdown,
|
package/dist/index.es.js.map
CHANGED
@@ -1,7 +1 @@
|
|
1
|
-
{
|
2
|
-
"version": 3,
|
3
|
-
"sources": ["../../../scripts/react-shim.js", "../src/Dropdown.tsx", "../src/DropdownButton.tsx"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import type { PopoverProps } from '@launchpad-ui/popover';\n\nimport { Popover } from '@launchpad-ui/popover';\nimport cx from 'clsx';\nimport { Children, cloneElement, useEffect, useRef, useState } from 'react';\n\ntype DropdownState = {\n isOpen?: boolean;\n};\n\ntype DropdownProps<T extends string | object | number> = PopoverProps & {\n onSelect?: (item: T, stateChanges: DropdownState) => void;\n onStateChange?: (state: DropdownState) => void;\n};\n\nconst Dropdown = <T extends string | object | number>(props: DropdownProps<T>) => {\n const {\n placement,\n disabled,\n targetClassName,\n popoverClassName,\n isOpen: isOpenProp,\n onInteraction,\n onSelect,\n onStateChange,\n children,\n ...rest\n } = props;\n\n const triggerRef = useRef<HTMLElement>(null);\n const [isOpen, setIsOpen] = useState(isOpenProp ?? false);\n const [hasOpened, setHasOpened] = useState(isOpen);\n\n useEffect(() => {\n if (isOpenProp !== undefined) {\n setIsOpen(isOpenProp);\n }\n }, [isOpenProp]);\n\n useEffect(() => {\n // Focus the button upon closing for convenient tabbing\n if (hasOpened && isOpen === false) {\n setTimeout(() => {\n const current = triggerRef.current;\n if (!current) {\n return;\n }\n\n // If a dropdown menu item triggers a modal, we do not want to focus the trigger. Instead\n // we let the modal components control their own focus.\n // Note that this is not ideal since closing the modal will not cause the dropdown trigger\n // to regain focus.\n const hasModal = current.closest?.('.has-modal');\n\n !hasModal && current.focus?.();\n });\n }\n }, [isOpen, hasOpened]);\n\n useEffect(() => {\n setHasOpened(isOpen);\n onStateChange?.({ isOpen });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n const renderTrigger = () => {\n return cloneElement(parseChildren().target, {\n 'aria-haspopup': true,\n 'aria-expanded': isOpen ? true : false,\n ref: triggerRef,\n isopen: isOpen?.toString(),\n });\n };\n\n const renderContent = () => {\n return cloneElement(parseChildren().content, {\n onSelect: handleSelect,\n });\n };\n\n const handleSelect = (item: T) => {\n setIsOpen(false);\n onSelect?.(item, { isOpen: false });\n };\n\n const handlePopoverInteraction = (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen);\n };\n\n const parseChildren = () => {\n const [targetChild, contentChild] = Children.toArray(children);\n return {\n target: targetChild as React.ReactElement,\n content: contentChild as React.ReactElement,\n };\n };\n\n const popoverTargetClasses = cx('Dropdown-target', targetClassName);\n const popoverClasses = cx('Dropdown', popoverClassName);\n\n return (\n <Popover\n isOpen={isOpen}\n placement={placement}\n onInteraction={onInteraction || handlePopoverInteraction}\n restrictHeight={false}\n disabled={disabled}\n targetClassName={popoverTargetClasses}\n popoverClassName={popoverClasses}\n {...rest}\n >\n {renderTrigger()}\n {renderContent()}\n </Popover>\n );\n};\n\nexport { Dropdown };\nexport type { DropdownProps };\n", "import type { ButtonKind, ButtonSize } from '@launchpad-ui/button';\n\nimport { Button } from '@launchpad-ui/button';\nimport { ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport { forwardRef } from 'react';\n\ntype DropdownButtonProps = {\n hideCaret?: boolean;\n kind?: ButtonKind;\n size?: ButtonSize;\n className?: string;\n disabled?: boolean;\n children?: React.ReactNode;\n onClick?(v: React.MouseEvent): void;\n testId?: string;\n 'aria-label'?: string;\n};\n\nconst DropdownButton = forwardRef<React.ElementRef<typeof Button>, DropdownButtonProps>(\n (props, ref) => {\n const { children, hideCaret, ...rest } = props;\n\n return (\n <Button {...rest} ref={ref}>\n {children} {!hideCaret && <ExpandMore size={IconSize.SMALL} />}\n </Button>\n );\n }\n);\n\nDropdownButton.displayName = 'DropdownButton';\n\nexport { DropdownButton };\nexport type { DropdownButtonProps };\n"],
|
5
|
-
"mappings": ";AAAA,YAAY,WAAW;;;ACEvB,SAAS,eAAe;AACxB,OAAO,QAAQ;AACf,SAAS,UAAU,cAAc,WAAW,QAAQ,gBAAgB;AAiGhE;AAtFJ,IAAM,WAAW,CAAqC,UAA4B;AAChF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,OACG;AAAA,EACL,IAAI;AAEJ,QAAM,aAAa,OAAoB,IAAI;AAC3C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,cAAc,KAAK;AACxD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,MAAM;AAEjD,YAAU,MAAM;AACd,QAAI,eAAe,QAAW;AAC5B,gBAAU,UAAU;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,YAAU,MAAM;AAEd,QAAI,aAAa,WAAW,OAAO;AACjC,iBAAW,MAAM;AACf,cAAM,UAAU,WAAW;AAC3B,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AAMA,cAAM,WAAW,QAAQ,UAAU,YAAY;AAE/C,SAAC,YAAY,QAAQ,QAAQ;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,YAAU,MAAM;AACd,iBAAa,MAAM;AACnB,oBAAgB,EAAE,OAAO,CAAC;AAAA,EAE5B,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,gBAAgB,MAAM;AAC1B,WAAO,aAAa,cAAc,EAAE,QAAQ;AAAA,MAC1C,iBAAiB;AAAA,MACjB,iBAAiB,SAAS,OAAO;AAAA,MACjC,KAAK;AAAA,MACL,QAAQ,QAAQ,SAAS;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgB,MAAM;AAC1B,WAAO,aAAa,cAAc,EAAE,SAAS;AAAA,MAC3C,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,QAAM,eAAe,CAAC,SAAY;AAChC,cAAU,KAAK;AACf,eAAW,MAAM,EAAE,QAAQ,MAAM,CAAC;AAAA,EACpC;AAEA,QAAM,2BAA2B,CAAC,eAAwB;AACxD,cAAU,UAAU;AAAA,EACtB;AAEA,QAAM,gBAAgB,MAAM;AAC1B,UAAM,CAAC,aAAa,YAAY,IAAI,SAAS,QAAQ,QAAQ;AAC7D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,uBAAuB,GAAG,mBAAmB,eAAe;AAClE,QAAM,iBAAiB,GAAG,YAAY,gBAAgB;AAEtD,SACE,qBAAC;AAAA,IACC;AAAA,IACA;AAAA,IACA,eAAe,iBAAiB;AAAA,IAChC,gBAAgB;AAAA,IAChB;AAAA,IACA,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IACjB,GAAG;AAAA,IAEH;AAAA,oBAAc;AAAA,MACd,cAAc;AAAA;AAAA,GACjB;AAEJ;;;ACjHA,SAAS,cAAc;AACvB,SAAS,YAAY,gBAAgB;AACrC,SAAS,kBAAkB;AAmBrB,SAC4B,KAD5B,QAAAA,aAAA;AALN,IAAM,iBAAiB;AAAA,EACrB,CAAC,OAAO,QAAQ;AACd,UAAM,EAAE,UAAU,cAAc,KAAK,IAAI;AAEzC,WACE,gBAAAA,MAAC;AAAA,MAAQ,GAAG;AAAA,MAAM;AAAA,MACf;AAAA;AAAA,QAAS;AAAA,QAAE,CAAC,aAAa,oBAAC;AAAA,UAAW,MAAM,SAAS;AAAA,SAAO;AAAA;AAAA,KAC9D;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;",
|
6
|
-
"names": ["jsxs"]
|
7
|
-
}
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/Dropdown.tsx","../src/DropdownButton.tsx"],"sourcesContent":["import type { PopoverProps } from '@launchpad-ui/popover';\nimport type { ReactElement } from 'react';\n\nimport { Popover } from '@launchpad-ui/popover';\nimport { cx } from 'classix';\nimport { Children, cloneElement, useEffect, useRef, useState } from 'react';\n\ntype DropdownState = {\n isOpen?: boolean;\n};\n\ntype DropdownProps<T extends string | object | number> = PopoverProps & {\n onSelect?: (item: T, stateChanges: DropdownState) => void;\n onStateChange?: (state: DropdownState) => void;\n};\n\nconst Dropdown = <T extends string | object | number>(props: DropdownProps<T>) => {\n const {\n placement,\n disabled,\n targetClassName,\n popoverClassName,\n isOpen: isOpenProp,\n onInteraction,\n onSelect,\n onStateChange,\n children,\n ...rest\n } = props;\n\n const triggerRef = useRef<HTMLElement>(null);\n const [isOpen, setIsOpen] = useState(isOpenProp ?? false);\n const [hasOpened, setHasOpened] = useState(isOpen);\n\n useEffect(() => {\n if (isOpenProp !== undefined) {\n setIsOpen(isOpenProp);\n }\n }, [isOpenProp]);\n\n useEffect(() => {\n // Focus the button upon closing for convenient tabbing\n if (hasOpened && isOpen === false) {\n setTimeout(() => {\n const current = triggerRef.current;\n if (!current) {\n return;\n }\n\n // If a dropdown menu item triggers a modal, we do not want to focus the trigger. Instead\n // we let the modal components control their own focus.\n // Note that this is not ideal since closing the modal will not cause the dropdown trigger\n // to regain focus.\n const hasModal = current.closest?.('.has-modal');\n\n !hasModal && current.focus?.();\n });\n }\n }, [isOpen, hasOpened]);\n\n useEffect(() => {\n setHasOpened(isOpen);\n onStateChange?.({ isOpen });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n const renderTrigger = () => {\n return cloneElement(parseChildren().target, {\n 'aria-haspopup': true,\n 'aria-expanded': isOpen ? true : false,\n ref: triggerRef,\n isopen: isOpen?.toString(),\n });\n };\n\n const renderContent = () => {\n return cloneElement(parseChildren().content, {\n onSelect: handleSelect,\n });\n };\n\n const handleSelect = (item: T) => {\n setIsOpen(false);\n onSelect?.(item, { isOpen: false });\n };\n\n const handlePopoverInteraction = (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen);\n };\n\n const parseChildren = () => {\n const [targetChild, contentChild] = Children.toArray(children);\n return {\n target: targetChild as ReactElement,\n content: contentChild as ReactElement,\n };\n };\n\n const popoverTargetClasses = cx('Dropdown-target', targetClassName);\n const popoverClasses = cx('Dropdown', popoverClassName);\n\n return (\n <Popover\n isOpen={isOpen}\n placement={placement}\n onInteraction={onInteraction || handlePopoverInteraction}\n restrictHeight={false}\n disabled={disabled}\n targetClassName={popoverTargetClasses}\n popoverClassName={popoverClasses}\n {...rest}\n >\n {renderTrigger()}\n {renderContent()}\n </Popover>\n );\n};\n\nexport { Dropdown };\nexport type { DropdownProps };\n","import type { ButtonKind, ButtonSize } from '@launchpad-ui/button';\nimport type { ElementRef, MouseEvent, ReactNode } from 'react';\n\nimport { Button } from '@launchpad-ui/button';\nimport { ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport { forwardRef } from 'react';\n\ntype DropdownButtonProps = {\n hideCaret?: boolean;\n kind?: ButtonKind;\n size?: ButtonSize;\n className?: string;\n disabled?: boolean;\n children?: ReactNode;\n onClick?(v: MouseEvent): void;\n testId?: string;\n 'aria-label'?: string;\n};\n\nconst DropdownButton = forwardRef<ElementRef<typeof Button>, DropdownButtonProps>((props, ref) => {\n const { children, hideCaret, ...rest } = props;\n\n return (\n <Button {...rest} ref={ref}>\n {children} {!hideCaret && <ExpandMore size={IconSize.SMALL} />}\n </Button>\n );\n});\n\nDropdownButton.displayName = 'DropdownButton';\n\nexport { DropdownButton };\nexport type { DropdownButtonProps };\n"],"names":["Dropdown","props","placement","disabled","targetClassName","popoverClassName","isOpen","isOpenProp","onInteraction","onSelect","onStateChange","children","rest","triggerRef","useRef","setIsOpen","useState","hasOpened","setHasOpened","useEffect","undefined","setTimeout","current","hasModal","closest","focus","renderTrigger","cloneElement","parseChildren","target","ref","isopen","toString","renderContent","content","handleSelect","item","handlePopoverInteraction","nextIsOpen","targetChild","contentChild","Children","toArray","popoverTargetClasses","cx","popoverClasses","DropdownButton","forwardRef","hideCaret","IconSize","SMALL","displayName"],"mappings":";;;;;;AAgBMA,MAAAA,WAAW,CAAqCC,UAA4B;AAC1E,QAAA;AAAA,IACJC;AAAAA,IACAC;AAAAA,IACAC;AAAAA,IACAC;AAAAA,IACAC,QAAQC;AAAAA,IACRC;AAAAA,IACAC;AAAAA,IACAC;AAAAA,IACAC;AAAAA,OACGC;AAAAA,MACDX;AAEEY,QAAAA,aAAaC,OAAoB,IAAd;AACzB,QAAM,CAACR,QAAQS,aAAaC,SAAST,kCAAc,KAAf;AACpC,QAAM,CAACU,WAAWC,gBAAgBF,SAASV,MAAD;AAE1Ca,YAAU,MAAM;AACd,QAAIZ,eAAea,QAAW;AAC5BL,gBAAUR,UAAD;AAAA,IACV;AAAA,EAAA,GACA,CAACA,UAAD,CAJM;AAMTY,YAAU,MAAM;AAEVF,QAAAA,aAAaX,WAAW,OAAO;AACjCe,iBAAW,MAAM;;AACf,cAAMC,UAAUT,WAAWS;AAC3B,YAAI,CAACA,SAAS;AACZ;AAAA,QACD;AAMKC,cAAAA,WAAWD,cAAQE,YAARF,iCAAkB;AAElCC,SAAAA,YAAYD,eAAQG,UAARH;AAAAA,MAAb,CAZQ;AAAA,IAcX;AAAA,EAAA,GACA,CAAChB,QAAQW,SAAT,CAlBM;AAoBTE,YAAU,MAAM;AACdD,iBAAaZ,MAAD;AACI,mDAAA;AAAA,MAAEA;AAAAA,IAAAA;AAAAA,EAAL,GAEZ,CAACA,MAAD,CAJM;AAMT,QAAMoB,gBAAgB,MAAM;AACnBC,WAAAA,aAAaC,cAAa,EAAGC,QAAQ;AAAA,MAC1C,iBAAiB;AAAA,MACjB,iBAAiBvB,SAAS,OAAO;AAAA,MACjCwB,KAAKjB;AAAAA,MACLkB,QAAQzB,iCAAQ0B;AAAAA,IAAR,CAJS;AAAA,EAAA;AAQrB,QAAMC,gBAAgB,MAAM;AACnBN,WAAAA,aAAaC,cAAa,EAAGM,SAAS;AAAA,MAC3CzB,UAAU0B;AAAAA,IAAAA,CADO;AAAA,EAAA;AAKfA,QAAAA,eAAe,CAACC,SAAY;AAChCrB,cAAU,KAAD;AACTN,yCAAW2B,MAAM;AAAA,MAAE9B,QAAQ;AAAA,IAAA;AAAA,EAAnB;AAGJ+B,QAAAA,2BAA2B,CAACC,eAAwB;AACxDvB,cAAUuB,UAAD;AAAA,EAAA;AAGX,QAAMV,gBAAgB,MAAM;AAC1B,UAAM,CAACW,aAAaC,gBAAgBC,SAASC,QAAQ/B,QAAjB;AAC7B,WAAA;AAAA,MACLkB,QAAQU;AAAAA,MACRL,SAASM;AAAAA,IAAAA;AAAAA,EAFJ;AAMHG,QAAAA,uBAAuBC,GAAG,mBAAmBxC,eAApB;AACzByC,QAAAA,iBAAiBD,GAAG,YAAYvC,gBAAb;AAEzB,8BACG,SAAD;AAAA,IACE;AAAA,IACA;AAAA,IACA,eAAeG,iBAAiB6B;AAAAA,IAChC,gBAAgB;AAAA,IAChB;AAAA,IACA,iBAAiBM;AAAAA,IACjB,kBAAkBE;AAAAA,IAPpB,GAQMjC;AAAAA,IARN,UAAA,CAUGc,iBACAO,eAXH;AAAA,EAAA,CADF;AAeD;ACjGD,MAAMa,iBAAiBC,WAA2D,CAAC9C,OAAO6B,QAAQ;AAC1F,QAAA;AAAA,IAAEnB;AAAAA,IAAUqC;AAAAA,OAAcpC;AAAAA,MAASX;AAEzC,8BACG,QAAD;AAAA,IAAA,GAAYW;AAAAA,IAAM;AAAA,IAAlB,UAAA,CACGD,UAAW,KAAA,CAACqC,iCAAc,YAAD;AAAA,MAAY,MAAMC,SAASC;AAAAA,IAAAA,CADvD,CAAA;AAAA,EAAA,CADF;AAKD,CARgC;AAUjCJ,eAAeK,cAAc;"}
|
package/dist/index.js
CHANGED
@@ -1,45 +1,12 @@
|
|
1
1
|
"use strict";
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
11
|
-
};
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
14
|
-
for (let key of __getOwnPropNames(from))
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
17
|
-
}
|
18
|
-
return to;
|
19
|
-
};
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
21
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
22
|
-
mod
|
23
|
-
));
|
24
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
25
|
-
|
26
|
-
// src/index.ts
|
27
|
-
var src_exports = {};
|
28
|
-
__export(src_exports, {
|
29
|
-
Dropdown: () => Dropdown,
|
30
|
-
DropdownButton: () => DropdownButton
|
31
|
-
});
|
32
|
-
module.exports = __toCommonJS(src_exports);
|
33
|
-
|
34
|
-
// ../../scripts/react-shim.js
|
35
|
-
var React = __toESM(require("react"));
|
36
|
-
|
37
|
-
// src/Dropdown.tsx
|
38
|
-
var import_popover = require("@launchpad-ui/popover");
|
39
|
-
var import_clsx = __toESM(require("clsx"));
|
40
|
-
var import_react = require("react");
|
41
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
42
|
-
var Dropdown = (props) => {
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
3
|
+
const popover = require("@launchpad-ui/popover");
|
4
|
+
const classix = require("classix");
|
5
|
+
const react = require("react");
|
6
|
+
const jsxRuntime = require("react/jsx-runtime");
|
7
|
+
const button = require("@launchpad-ui/button");
|
8
|
+
const icons = require("@launchpad-ui/icons");
|
9
|
+
const Dropdown = (props) => {
|
43
10
|
const {
|
44
11
|
placement,
|
45
12
|
disabled,
|
@@ -52,60 +19,65 @@ var Dropdown = (props) => {
|
|
52
19
|
children,
|
53
20
|
...rest
|
54
21
|
} = props;
|
55
|
-
const triggerRef =
|
56
|
-
const [isOpen, setIsOpen] =
|
57
|
-
const [hasOpened, setHasOpened] =
|
58
|
-
|
22
|
+
const triggerRef = react.useRef(null);
|
23
|
+
const [isOpen, setIsOpen] = react.useState(isOpenProp != null ? isOpenProp : false);
|
24
|
+
const [hasOpened, setHasOpened] = react.useState(isOpen);
|
25
|
+
react.useEffect(() => {
|
59
26
|
if (isOpenProp !== void 0) {
|
60
27
|
setIsOpen(isOpenProp);
|
61
28
|
}
|
62
29
|
}, [isOpenProp]);
|
63
|
-
|
30
|
+
react.useEffect(() => {
|
64
31
|
if (hasOpened && isOpen === false) {
|
65
32
|
setTimeout(() => {
|
33
|
+
var _a, _b;
|
66
34
|
const current = triggerRef.current;
|
67
35
|
if (!current) {
|
68
36
|
return;
|
69
37
|
}
|
70
|
-
const hasModal = current.closest
|
71
|
-
!hasModal && current.focus
|
38
|
+
const hasModal = (_a = current.closest) == null ? void 0 : _a.call(current, ".has-modal");
|
39
|
+
!hasModal && ((_b = current.focus) == null ? void 0 : _b.call(current));
|
72
40
|
});
|
73
41
|
}
|
74
42
|
}, [isOpen, hasOpened]);
|
75
|
-
|
43
|
+
react.useEffect(() => {
|
76
44
|
setHasOpened(isOpen);
|
77
|
-
onStateChange
|
45
|
+
onStateChange == null ? void 0 : onStateChange({
|
46
|
+
isOpen
|
47
|
+
});
|
78
48
|
}, [isOpen]);
|
79
49
|
const renderTrigger = () => {
|
80
|
-
return
|
50
|
+
return react.cloneElement(parseChildren().target, {
|
81
51
|
"aria-haspopup": true,
|
82
52
|
"aria-expanded": isOpen ? true : false,
|
83
53
|
ref: triggerRef,
|
84
|
-
isopen: isOpen
|
54
|
+
isopen: isOpen == null ? void 0 : isOpen.toString()
|
85
55
|
});
|
86
56
|
};
|
87
57
|
const renderContent = () => {
|
88
|
-
return
|
58
|
+
return react.cloneElement(parseChildren().content, {
|
89
59
|
onSelect: handleSelect
|
90
60
|
});
|
91
61
|
};
|
92
62
|
const handleSelect = (item) => {
|
93
63
|
setIsOpen(false);
|
94
|
-
onSelect
|
64
|
+
onSelect == null ? void 0 : onSelect(item, {
|
65
|
+
isOpen: false
|
66
|
+
});
|
95
67
|
};
|
96
68
|
const handlePopoverInteraction = (nextIsOpen) => {
|
97
69
|
setIsOpen(nextIsOpen);
|
98
70
|
};
|
99
71
|
const parseChildren = () => {
|
100
|
-
const [targetChild, contentChild] =
|
72
|
+
const [targetChild, contentChild] = react.Children.toArray(children);
|
101
73
|
return {
|
102
74
|
target: targetChild,
|
103
75
|
content: contentChild
|
104
76
|
};
|
105
77
|
};
|
106
|
-
const popoverTargetClasses =
|
107
|
-
const popoverClasses =
|
108
|
-
return /* @__PURE__ */
|
78
|
+
const popoverTargetClasses = classix.cx("Dropdown-target", targetClassName);
|
79
|
+
const popoverClasses = classix.cx("Dropdown", popoverClassName);
|
80
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(popover.Popover, {
|
109
81
|
isOpen,
|
110
82
|
placement,
|
111
83
|
onInteraction: onInteraction || handlePopoverInteraction,
|
@@ -114,38 +86,24 @@ var Dropdown = (props) => {
|
|
114
86
|
targetClassName: popoverTargetClasses,
|
115
87
|
popoverClassName: popoverClasses,
|
116
88
|
...rest,
|
117
|
-
children: [
|
118
|
-
renderTrigger(),
|
119
|
-
renderContent()
|
120
|
-
]
|
89
|
+
children: [renderTrigger(), renderContent()]
|
121
90
|
});
|
122
91
|
};
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
children,
|
137
|
-
" ",
|
138
|
-
!hideCaret && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.ExpandMore, {
|
139
|
-
size: import_icons.IconSize.SMALL
|
140
|
-
})
|
141
|
-
]
|
142
|
-
});
|
143
|
-
}
|
144
|
-
);
|
145
|
-
DropdownButton.displayName = "DropdownButton";
|
146
|
-
// Annotate the CommonJS export names for ESM import in node:
|
147
|
-
0 && (module.exports = {
|
148
|
-
Dropdown,
|
149
|
-
DropdownButton
|
92
|
+
const DropdownButton = react.forwardRef((props, ref) => {
|
93
|
+
const {
|
94
|
+
children,
|
95
|
+
hideCaret,
|
96
|
+
...rest
|
97
|
+
} = props;
|
98
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(button.Button, {
|
99
|
+
...rest,
|
100
|
+
ref,
|
101
|
+
children: [children, " ", !hideCaret && /* @__PURE__ */ jsxRuntime.jsx(icons.ExpandMore, {
|
102
|
+
size: icons.IconSize.SMALL
|
103
|
+
})]
|
104
|
+
});
|
150
105
|
});
|
106
|
+
DropdownButton.displayName = "DropdownButton";
|
107
|
+
exports.Dropdown = Dropdown;
|
108
|
+
exports.DropdownButton = DropdownButton;
|
151
109
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1,7 +1 @@
|
|
1
|
-
{
|
2
|
-
"version": 3,
|
3
|
-
"sources": ["../src/index.ts", "../../../scripts/react-shim.js", "../src/Dropdown.tsx", "../src/DropdownButton.tsx"],
|
4
|
-
"sourcesContent": ["export type { DropdownProps } from './Dropdown';\nexport type { DropdownButtonProps } from './DropdownButton';\nexport { Dropdown } from './Dropdown';\nexport { DropdownButton } from './DropdownButton';\n", "import * as React from 'react';\nexport { React };\n", "import type { PopoverProps } from '@launchpad-ui/popover';\n\nimport { Popover } from '@launchpad-ui/popover';\nimport cx from 'clsx';\nimport { Children, cloneElement, useEffect, useRef, useState } from 'react';\n\ntype DropdownState = {\n isOpen?: boolean;\n};\n\ntype DropdownProps<T extends string | object | number> = PopoverProps & {\n onSelect?: (item: T, stateChanges: DropdownState) => void;\n onStateChange?: (state: DropdownState) => void;\n};\n\nconst Dropdown = <T extends string | object | number>(props: DropdownProps<T>) => {\n const {\n placement,\n disabled,\n targetClassName,\n popoverClassName,\n isOpen: isOpenProp,\n onInteraction,\n onSelect,\n onStateChange,\n children,\n ...rest\n } = props;\n\n const triggerRef = useRef<HTMLElement>(null);\n const [isOpen, setIsOpen] = useState(isOpenProp ?? false);\n const [hasOpened, setHasOpened] = useState(isOpen);\n\n useEffect(() => {\n if (isOpenProp !== undefined) {\n setIsOpen(isOpenProp);\n }\n }, [isOpenProp]);\n\n useEffect(() => {\n // Focus the button upon closing for convenient tabbing\n if (hasOpened && isOpen === false) {\n setTimeout(() => {\n const current = triggerRef.current;\n if (!current) {\n return;\n }\n\n // If a dropdown menu item triggers a modal, we do not want to focus the trigger. Instead\n // we let the modal components control their own focus.\n // Note that this is not ideal since closing the modal will not cause the dropdown trigger\n // to regain focus.\n const hasModal = current.closest?.('.has-modal');\n\n !hasModal && current.focus?.();\n });\n }\n }, [isOpen, hasOpened]);\n\n useEffect(() => {\n setHasOpened(isOpen);\n onStateChange?.({ isOpen });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n const renderTrigger = () => {\n return cloneElement(parseChildren().target, {\n 'aria-haspopup': true,\n 'aria-expanded': isOpen ? true : false,\n ref: triggerRef,\n isopen: isOpen?.toString(),\n });\n };\n\n const renderContent = () => {\n return cloneElement(parseChildren().content, {\n onSelect: handleSelect,\n });\n };\n\n const handleSelect = (item: T) => {\n setIsOpen(false);\n onSelect?.(item, { isOpen: false });\n };\n\n const handlePopoverInteraction = (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen);\n };\n\n const parseChildren = () => {\n const [targetChild, contentChild] = Children.toArray(children);\n return {\n target: targetChild as React.ReactElement,\n content: contentChild as React.ReactElement,\n };\n };\n\n const popoverTargetClasses = cx('Dropdown-target', targetClassName);\n const popoverClasses = cx('Dropdown', popoverClassName);\n\n return (\n <Popover\n isOpen={isOpen}\n placement={placement}\n onInteraction={onInteraction || handlePopoverInteraction}\n restrictHeight={false}\n disabled={disabled}\n targetClassName={popoverTargetClasses}\n popoverClassName={popoverClasses}\n {...rest}\n >\n {renderTrigger()}\n {renderContent()}\n </Popover>\n );\n};\n\nexport { Dropdown };\nexport type { DropdownProps };\n", "import type { ButtonKind, ButtonSize } from '@launchpad-ui/button';\n\nimport { Button } from '@launchpad-ui/button';\nimport { ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport { forwardRef } from 'react';\n\ntype DropdownButtonProps = {\n hideCaret?: boolean;\n kind?: ButtonKind;\n size?: ButtonSize;\n className?: string;\n disabled?: boolean;\n children?: React.ReactNode;\n onClick?(v: React.MouseEvent): void;\n testId?: string;\n 'aria-label'?: string;\n};\n\nconst DropdownButton = forwardRef<React.ElementRef<typeof Button>, DropdownButtonProps>(\n (props, ref) => {\n const { children, hideCaret, ...rest } = props;\n\n return (\n <Button {...rest} ref={ref}>\n {children} {!hideCaret && <ExpandMore size={IconSize.SMALL} />}\n </Button>\n );\n }\n);\n\nDropdownButton.displayName = 'DropdownButton';\n\nexport { DropdownButton };\nexport type { DropdownButtonProps };\n"],
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;;;ACEvB,qBAAwB;AACxB,kBAAe;AACf,mBAAoE;AAiGhE;AAtFJ,IAAM,WAAW,CAAqC,UAA4B;AAChF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,OACG;AAAA,EACL,IAAI;AAEJ,QAAM,iBAAa,qBAAoB,IAAI;AAC3C,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAS,cAAc,KAAK;AACxD,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,MAAM;AAEjD,8BAAU,MAAM;AACd,QAAI,eAAe,QAAW;AAC5B,gBAAU,UAAU;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,8BAAU,MAAM;AAEd,QAAI,aAAa,WAAW,OAAO;AACjC,iBAAW,MAAM;AACf,cAAM,UAAU,WAAW;AAC3B,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AAMA,cAAM,WAAW,QAAQ,UAAU,YAAY;AAE/C,SAAC,YAAY,QAAQ,QAAQ;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,8BAAU,MAAM;AACd,iBAAa,MAAM;AACnB,oBAAgB,EAAE,OAAO,CAAC;AAAA,EAE5B,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,gBAAgB,MAAM;AAC1B,eAAO,2BAAa,cAAc,EAAE,QAAQ;AAAA,MAC1C,iBAAiB;AAAA,MACjB,iBAAiB,SAAS,OAAO;AAAA,MACjC,KAAK;AAAA,MACL,QAAQ,QAAQ,SAAS;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgB,MAAM;AAC1B,eAAO,2BAAa,cAAc,EAAE,SAAS;AAAA,MAC3C,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,QAAM,eAAe,CAAC,SAAY;AAChC,cAAU,KAAK;AACf,eAAW,MAAM,EAAE,QAAQ,MAAM,CAAC;AAAA,EACpC;AAEA,QAAM,2BAA2B,CAAC,eAAwB;AACxD,cAAU,UAAU;AAAA,EACtB;AAEA,QAAM,gBAAgB,MAAM;AAC1B,UAAM,CAAC,aAAa,YAAY,IAAI,sBAAS,QAAQ,QAAQ;AAC7D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,2BAAuB,YAAAA,SAAG,mBAAmB,eAAe;AAClE,QAAM,qBAAiB,YAAAA,SAAG,YAAY,gBAAgB;AAEtD,SACE,6CAAC;AAAA,IACC;AAAA,IACA;AAAA,IACA,eAAe,iBAAiB;AAAA,IAChC,gBAAgB;AAAA,IAChB;AAAA,IACA,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IACjB,GAAG;AAAA,IAEH;AAAA,oBAAc;AAAA,MACd,cAAc;AAAA;AAAA,GACjB;AAEJ;;;ACjHA,oBAAuB;AACvB,mBAAqC;AACrC,IAAAC,gBAA2B;AAmBrB;AALN,IAAM,qBAAiB;AAAA,EACrB,CAAC,OAAO,QAAQ;AACd,UAAM,EAAE,UAAU,cAAc,KAAK,IAAI;AAEzC,WACE,6CAAC;AAAA,MAAQ,GAAG;AAAA,MAAM;AAAA,MACf;AAAA;AAAA,QAAS;AAAA,QAAE,CAAC,aAAa,4CAAC;AAAA,UAAW,MAAM,sBAAS;AAAA,SAAO;AAAA;AAAA,KAC9D;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;",
|
6
|
-
"names": ["cx", "import_react"]
|
7
|
-
}
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/Dropdown.tsx","../src/DropdownButton.tsx"],"sourcesContent":["import type { PopoverProps } from '@launchpad-ui/popover';\nimport type { ReactElement } from 'react';\n\nimport { Popover } from '@launchpad-ui/popover';\nimport { cx } from 'classix';\nimport { Children, cloneElement, useEffect, useRef, useState } from 'react';\n\ntype DropdownState = {\n isOpen?: boolean;\n};\n\ntype DropdownProps<T extends string | object | number> = PopoverProps & {\n onSelect?: (item: T, stateChanges: DropdownState) => void;\n onStateChange?: (state: DropdownState) => void;\n};\n\nconst Dropdown = <T extends string | object | number>(props: DropdownProps<T>) => {\n const {\n placement,\n disabled,\n targetClassName,\n popoverClassName,\n isOpen: isOpenProp,\n onInteraction,\n onSelect,\n onStateChange,\n children,\n ...rest\n } = props;\n\n const triggerRef = useRef<HTMLElement>(null);\n const [isOpen, setIsOpen] = useState(isOpenProp ?? false);\n const [hasOpened, setHasOpened] = useState(isOpen);\n\n useEffect(() => {\n if (isOpenProp !== undefined) {\n setIsOpen(isOpenProp);\n }\n }, [isOpenProp]);\n\n useEffect(() => {\n // Focus the button upon closing for convenient tabbing\n if (hasOpened && isOpen === false) {\n setTimeout(() => {\n const current = triggerRef.current;\n if (!current) {\n return;\n }\n\n // If a dropdown menu item triggers a modal, we do not want to focus the trigger. Instead\n // we let the modal components control their own focus.\n // Note that this is not ideal since closing the modal will not cause the dropdown trigger\n // to regain focus.\n const hasModal = current.closest?.('.has-modal');\n\n !hasModal && current.focus?.();\n });\n }\n }, [isOpen, hasOpened]);\n\n useEffect(() => {\n setHasOpened(isOpen);\n onStateChange?.({ isOpen });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n const renderTrigger = () => {\n return cloneElement(parseChildren().target, {\n 'aria-haspopup': true,\n 'aria-expanded': isOpen ? true : false,\n ref: triggerRef,\n isopen: isOpen?.toString(),\n });\n };\n\n const renderContent = () => {\n return cloneElement(parseChildren().content, {\n onSelect: handleSelect,\n });\n };\n\n const handleSelect = (item: T) => {\n setIsOpen(false);\n onSelect?.(item, { isOpen: false });\n };\n\n const handlePopoverInteraction = (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen);\n };\n\n const parseChildren = () => {\n const [targetChild, contentChild] = Children.toArray(children);\n return {\n target: targetChild as ReactElement,\n content: contentChild as ReactElement,\n };\n };\n\n const popoverTargetClasses = cx('Dropdown-target', targetClassName);\n const popoverClasses = cx('Dropdown', popoverClassName);\n\n return (\n <Popover\n isOpen={isOpen}\n placement={placement}\n onInteraction={onInteraction || handlePopoverInteraction}\n restrictHeight={false}\n disabled={disabled}\n targetClassName={popoverTargetClasses}\n popoverClassName={popoverClasses}\n {...rest}\n >\n {renderTrigger()}\n {renderContent()}\n </Popover>\n );\n};\n\nexport { Dropdown };\nexport type { DropdownProps };\n","import type { ButtonKind, ButtonSize } from '@launchpad-ui/button';\nimport type { ElementRef, MouseEvent, ReactNode } from 'react';\n\nimport { Button } from '@launchpad-ui/button';\nimport { ExpandMore, IconSize } from '@launchpad-ui/icons';\nimport { forwardRef } from 'react';\n\ntype DropdownButtonProps = {\n hideCaret?: boolean;\n kind?: ButtonKind;\n size?: ButtonSize;\n className?: string;\n disabled?: boolean;\n children?: ReactNode;\n onClick?(v: MouseEvent): void;\n testId?: string;\n 'aria-label'?: string;\n};\n\nconst DropdownButton = forwardRef<ElementRef<typeof Button>, DropdownButtonProps>((props, ref) => {\n const { children, hideCaret, ...rest } = props;\n\n return (\n <Button {...rest} ref={ref}>\n {children} {!hideCaret && <ExpandMore size={IconSize.SMALL} />}\n </Button>\n );\n});\n\nDropdownButton.displayName = 'DropdownButton';\n\nexport { DropdownButton };\nexport type { DropdownButtonProps };\n"],"names":["Dropdown","props","placement","disabled","targetClassName","popoverClassName","isOpen","isOpenProp","onInteraction","onSelect","onStateChange","children","rest","triggerRef","useRef","setIsOpen","useState","hasOpened","setHasOpened","useEffect","undefined","setTimeout","current","hasModal","closest","focus","renderTrigger","cloneElement","parseChildren","target","ref","isopen","toString","renderContent","content","handleSelect","item","handlePopoverInteraction","nextIsOpen","targetChild","contentChild","Children","toArray","popoverTargetClasses","cx","popoverClasses","Popover","DropdownButton","forwardRef","hideCaret","Button","ExpandMore","IconSize","SMALL","displayName"],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@launchpad-ui/dropdown",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.4.0",
|
4
4
|
"status": "beta",
|
5
5
|
"publishConfig": {
|
6
6
|
"access": "public"
|
@@ -25,11 +25,11 @@
|
|
25
25
|
},
|
26
26
|
"source": "src/index.ts",
|
27
27
|
"dependencies": {
|
28
|
-
"@launchpad-ui/button": "~0.
|
29
|
-
"@launchpad-ui/icons": "~0.
|
30
|
-
"@launchpad-ui/popover": "~0.
|
28
|
+
"@launchpad-ui/button": "~0.6.0",
|
29
|
+
"@launchpad-ui/icons": "~0.4.0",
|
30
|
+
"@launchpad-ui/popover": "~0.7.0",
|
31
31
|
"@launchpad-ui/tokens": "~0.1.5",
|
32
|
-
"
|
32
|
+
"classix": "^2.1.13"
|
33
33
|
},
|
34
34
|
"peerDependencies": {
|
35
35
|
"react": "^18.0.0",
|
@@ -40,7 +40,7 @@
|
|
40
40
|
"react-dom": "^18.2.0"
|
41
41
|
},
|
42
42
|
"scripts": {
|
43
|
-
"build": "tsc --project tsconfig.build.json
|
43
|
+
"build": "vite build -c ../../vite.config.ts && tsc --project tsconfig.build.json",
|
44
44
|
"clean": "rm -rf dist",
|
45
45
|
"e2e": "playwright test --config=../../playwright.config.ct.ts",
|
46
46
|
"lint": "eslint '**/*.{ts,tsx,js}'",
|