@launchpad-ui/dropdown 0.10.17 → 0.10.18
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.map +1 -1
- package/dist/index.es.js +101 -80
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +102 -83
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/Dropdown.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../src/Dropdown.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Dropdown.d.ts","sourceRoot":"","sources":["../src/Dropdown.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,KAAK,aAAa,GAAG;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,YAAY,GAAG;IACvE,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;CAC/C,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,QAAQ,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,OAAO,aAAa,CAAC,CAAC,CAAC,4CAyG5E,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -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":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD,KAAK,mBAAmB,GAAG,WAAW,GAAG;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,QAAA,MAAM,cAAc;;;;;;;;;;;;gBAHP,OAAO;qDAWlB,CAAC;AAIH,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
package/dist/index.es.js
CHANGED
|
@@ -1,87 +1,108 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState, useEffect, cloneElement, Children, forwardRef } from "react";
|
|
2
3
|
import { mergeRefs } from "@react-aria/utils";
|
|
3
4
|
import { cx } from "classix";
|
|
4
|
-
import {
|
|
5
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Popover } from "@launchpad-ui/popover";
|
|
6
6
|
import { Button } from "@launchpad-ui/button";
|
|
7
7
|
import { Icon } from "@launchpad-ui/icons";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
8
|
+
const Dropdown = (props) => {
|
|
9
|
+
const {
|
|
10
|
+
placement,
|
|
11
|
+
disabled,
|
|
12
|
+
targetClassName,
|
|
13
|
+
popoverClassName,
|
|
14
|
+
isOpen: isOpenProp,
|
|
15
|
+
onInteraction,
|
|
16
|
+
onSelect,
|
|
17
|
+
onStateChange,
|
|
18
|
+
children,
|
|
19
|
+
"data-test-id": testId = "dropdown",
|
|
20
|
+
...rest
|
|
21
|
+
} = props;
|
|
22
|
+
const triggerRef = useRef(null);
|
|
23
|
+
const [isOpen, setIsOpen] = useState(isOpenProp ?? false);
|
|
24
|
+
const [hasOpened, setHasOpened] = useState(isOpen);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (isOpenProp !== void 0) {
|
|
27
|
+
setIsOpen(isOpenProp);
|
|
28
|
+
}
|
|
29
|
+
}, [isOpenProp]);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (hasOpened && isOpen === false) {
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
const current = triggerRef.current;
|
|
34
|
+
if (!current) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const hasModal = current.closest?.(".has-overlay");
|
|
38
|
+
!hasModal && current.focus?.();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}, [isOpen, hasOpened]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
setHasOpened(isOpen);
|
|
44
|
+
onStateChange?.({ isOpen });
|
|
45
|
+
}, [isOpen]);
|
|
46
|
+
const renderTrigger = () => {
|
|
47
|
+
const { target } = parseChildren();
|
|
48
|
+
return /* @__PURE__ */ cloneElement(target, {
|
|
49
|
+
"aria-haspopup": true,
|
|
50
|
+
"aria-expanded": !!isOpen,
|
|
51
|
+
ref: target.ref ? mergeRefs(target.ref, triggerRef) : triggerRef,
|
|
52
|
+
isopen: isOpen?.toString()
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
const renderContent = () => {
|
|
56
|
+
return /* @__PURE__ */ cloneElement(parseChildren().content, {
|
|
57
|
+
onSelect: handleSelect
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const handleSelect = (item) => {
|
|
61
|
+
setIsOpen(false);
|
|
62
|
+
onSelect?.(item, { isOpen: false });
|
|
63
|
+
};
|
|
64
|
+
const handlePopoverInteraction = (nextIsOpen) => {
|
|
65
|
+
setIsOpen(nextIsOpen);
|
|
66
|
+
};
|
|
67
|
+
const parseChildren = () => {
|
|
68
|
+
const [targetChild, contentChild] = Children.toArray(children);
|
|
69
|
+
return {
|
|
70
|
+
target: targetChild,
|
|
71
|
+
content: contentChild
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
const popoverTargetClasses = cx("Dropdown-target", targetClassName);
|
|
75
|
+
const popoverClasses = cx("Dropdown", popoverClassName);
|
|
76
|
+
return /* @__PURE__ */ jsxs(
|
|
77
|
+
Popover,
|
|
78
|
+
{
|
|
79
|
+
isOpen,
|
|
80
|
+
placement,
|
|
81
|
+
onInteraction: onInteraction || handlePopoverInteraction,
|
|
82
|
+
restrictHeight: false,
|
|
83
|
+
disabled,
|
|
84
|
+
targetClassName: popoverTargetClasses,
|
|
85
|
+
popoverClassName: popoverClasses,
|
|
86
|
+
"data-test-id": testId,
|
|
87
|
+
...rest,
|
|
88
|
+
children: [
|
|
89
|
+
renderTrigger(),
|
|
90
|
+
renderContent()
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
);
|
|
67
94
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
children,
|
|
76
|
-
" ",
|
|
77
|
-
!hideCaret && /* @__PURE__ */ jsx(Icon, {
|
|
78
|
-
name: "chevron-down",
|
|
79
|
-
size: "small"
|
|
80
|
-
})
|
|
81
|
-
]
|
|
82
|
-
});
|
|
95
|
+
const DropdownButton = /* @__PURE__ */ forwardRef((props, ref) => {
|
|
96
|
+
const { children, hideCaret, "data-test-id": testId = "dropdown-button", ...rest } = props;
|
|
97
|
+
return /* @__PURE__ */ jsxs(Button, { ...rest, "data-test-id": testId, ref, children: [
|
|
98
|
+
children,
|
|
99
|
+
" ",
|
|
100
|
+
!hideCaret && /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "small" })
|
|
101
|
+
] });
|
|
83
102
|
});
|
|
84
103
|
DropdownButton.displayName = "DropdownButton";
|
|
85
|
-
export {
|
|
86
|
-
|
|
87
|
-
|
|
104
|
+
export {
|
|
105
|
+
Dropdown,
|
|
106
|
+
DropdownButton
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=index.es.js.map
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","
|
|
1
|
+
{"version":3,"file":"index.es.js","sources":["../src/Dropdown.tsx","../src/DropdownButton.tsx"],"sourcesContent":["import type { AriaAttributes, ForwardedRef, FunctionComponentElement, ReactElement } from 'react';\nimport { Children, cloneElement, useEffect, useRef, useState } from 'react';\nimport { mergeRefs } from '@react-aria/utils';\nimport { cx } from 'classix';\n\nimport type { PopoverProps } from '@launchpad-ui/popover';\nimport { Popover } from '@launchpad-ui/popover';\n\ntype DropdownState = {\n\tisOpen?: boolean;\n};\n\ntype DropdownProps<T extends string | object | number> = PopoverProps & {\n\tonSelect?: (item: T, stateChanges: DropdownState) => void;\n\tonStateChange?: (state: DropdownState) => void;\n};\n\n/**\n * @deprecated use `Menu` from `@launchpad-ui/components` instead\n *\n * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs\n */\nconst Dropdown = <T extends string | object | number>(props: DropdownProps<T>) => {\n\tconst {\n\t\tplacement,\n\t\tdisabled,\n\t\ttargetClassName,\n\t\tpopoverClassName,\n\t\tisOpen: isOpenProp,\n\t\tonInteraction,\n\t\tonSelect,\n\t\tonStateChange,\n\t\tchildren,\n\t\t'data-test-id': testId = 'dropdown',\n\t\t...rest\n\t} = props;\n\n\tconst triggerRef = useRef<HTMLElement | null>(null);\n\tconst [isOpen, setIsOpen] = useState(isOpenProp ?? false);\n\tconst [hasOpened, setHasOpened] = useState(isOpen);\n\n\tuseEffect(() => {\n\t\tif (isOpenProp !== undefined) {\n\t\t\tsetIsOpen(isOpenProp);\n\t\t}\n\t}, [isOpenProp]);\n\n\tuseEffect(() => {\n\t\t// Focus the button upon closing for convenient tabbing\n\t\tif (hasOpened && isOpen === false) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tconst current = triggerRef.current;\n\t\t\t\tif (!current) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If a dropdown menu item triggers a modal, we do not want to focus the trigger. Instead\n\t\t\t\t// we let the modal components control their own focus.\n\t\t\t\t// Note that this is not ideal since closing the modal will not cause the dropdown trigger\n\t\t\t\t// to regain focus.\n\t\t\t\tconst hasModal = current.closest?.('.has-overlay');\n\n\t\t\t\t!hasModal && current.focus?.();\n\t\t\t});\n\t\t}\n\t}, [isOpen, hasOpened]);\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: ignore\n\tuseEffect(() => {\n\t\tsetHasOpened(isOpen);\n\t\tonStateChange?.({ isOpen });\n\t}, [isOpen]);\n\n\tconst renderTrigger = () => {\n\t\tconst { target } = parseChildren();\n\t\treturn cloneElement(target, {\n\t\t\t'aria-haspopup': true,\n\t\t\t'aria-expanded': !!isOpen,\n\t\t\tref: target.ref ? mergeRefs(target.ref, triggerRef) : triggerRef,\n\t\t\tisopen: isOpen?.toString(),\n\t\t});\n\t};\n\n\tconst renderContent = () => {\n\t\treturn cloneElement(parseChildren().content, {\n\t\t\tonSelect: handleSelect,\n\t\t});\n\t};\n\n\tconst handleSelect = (item: T) => {\n\t\tsetIsOpen(false);\n\t\tonSelect?.(item, { isOpen: false });\n\t};\n\n\tconst handlePopoverInteraction = (nextIsOpen: boolean) => {\n\t\tsetIsOpen(nextIsOpen);\n\t};\n\n\tconst parseChildren = () => {\n\t\tconst [targetChild, contentChild] = Children.toArray(children);\n\t\treturn {\n\t\t\ttarget: targetChild as FunctionComponentElement<\n\t\t\t\tAriaAttributes & { ref: ForwardedRef<HTMLElement | undefined>; isopen: string }\n\t\t\t>,\n\t\t\tcontent: contentChild as ReactElement<{ onSelect?: (item: T) => void }>,\n\t\t};\n\t};\n\n\tconst popoverTargetClasses = cx('Dropdown-target', targetClassName);\n\tconst popoverClasses = cx('Dropdown', popoverClassName);\n\n\treturn (\n\t\t<Popover\n\t\t\tisOpen={isOpen}\n\t\t\tplacement={placement}\n\t\t\tonInteraction={onInteraction || handlePopoverInteraction}\n\t\t\trestrictHeight={false}\n\t\t\tdisabled={disabled}\n\t\t\ttargetClassName={popoverTargetClasses}\n\t\t\tpopoverClassName={popoverClasses}\n\t\t\tdata-test-id={testId}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{renderTrigger()}\n\t\t\t{renderContent()}\n\t\t</Popover>\n\t);\n};\n\nexport { Dropdown };\nexport type { DropdownProps };\n","import { forwardRef } from 'react';\n\nimport type { ButtonProps } from '@launchpad-ui/button';\nimport { Button } from '@launchpad-ui/button';\nimport { Icon } from '@launchpad-ui/icons';\n\ntype DropdownButtonProps = ButtonProps & {\n\thideCaret?: boolean;\n};\n\nconst DropdownButton = forwardRef<HTMLButtonElement, DropdownButtonProps>((props, ref) => {\n\tconst { children, hideCaret, 'data-test-id': testId = 'dropdown-button', ...rest } = props;\n\n\treturn (\n\t\t<Button {...rest} data-test-id={testId} ref={ref}>\n\t\t\t{children} {!hideCaret && <Icon name=\"chevron-down\" size=\"small\" />}\n\t\t</Button>\n\t);\n});\n\nDropdownButton.displayName = 'DropdownButton';\n\nexport { DropdownButton };\nexport type { DropdownButtonProps };\n"],"names":[],"mappings":";;;;;;;AAsBA,MAAM,WAAW,CAAqC,UAA4B;AACjF,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB,SAAS;AAAA,IACzB,GAAG;AAAA,EAAA,IACA;AAEJ,QAAM,aAAa,OAA2B,IAAI;AAClD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,cAAc,KAAK;AACxD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,MAAM;AAEjD,YAAU,MAAM;AACf,QAAI,eAAe,QAAW;AAC7B,gBAAU,UAAU;AAAA,IACrB;AAAA,EACD,GAAG,CAAC,UAAU,CAAC;AAEf,YAAU,MAAM;AAEf,QAAI,aAAa,WAAW,OAAO;AAClC,iBAAW,MAAM;AAChB,cAAM,UAAU,WAAW;AAC3B,YAAI,CAAC,SAAS;AACb;AAAA,QACD;AAMA,cAAM,WAAW,QAAQ,UAAU,cAAc;AAEjD,SAAC,YAAY,QAAQ,QAAA;AAAA,MACtB,CAAC;AAAA,IACF;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,CAAC;AAGtB,YAAU,MAAM;AACf,iBAAa,MAAM;AACnB,oBAAgB,EAAE,QAAQ;AAAA,EAC3B,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,gBAAgB,MAAM;AAC3B,UAAM,EAAE,OAAA,IAAW,cAAA;AACnB,WAAO,6BAAa,QAAQ;AAAA,MAC3B,iBAAiB;AAAA,MACjB,iBAAiB,CAAC,CAAC;AAAA,MACnB,KAAK,OAAO,MAAM,UAAU,OAAO,KAAK,UAAU,IAAI;AAAA,MACtD,QAAQ,QAAQ,SAAA;AAAA,IAAS,CACzB;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAM;AAC3B,WAAO,6BAAa,cAAA,EAAgB,SAAS;AAAA,MAC5C,UAAU;AAAA,IAAA,CACV;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,SAAY;AACjC,cAAU,KAAK;AACf,eAAW,MAAM,EAAE,QAAQ,MAAA,CAAO;AAAA,EACnC;AAEA,QAAM,2BAA2B,CAAC,eAAwB;AACzD,cAAU,UAAU;AAAA,EACrB;AAEA,QAAM,gBAAgB,MAAM;AAC3B,UAAM,CAAC,aAAa,YAAY,IAAI,SAAS,QAAQ,QAAQ;AAC7D,WAAO;AAAA,MACN,QAAQ;AAAA,MAGR,SAAS;AAAA,IAAA;AAAA,EAEX;AAEA,QAAM,uBAAuB,GAAG,mBAAmB,eAAe;AAClE,QAAM,iBAAiB,GAAG,YAAY,gBAAgB;AAEtD,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,iBAAiB;AAAA,MAChC,gBAAgB;AAAA,MAChB;AAAA,MACA,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,MAClB,gBAAc;AAAA,MACb,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,cAAA;AAAA,QACA,cAAA;AAAA,MAAc;AAAA,IAAA;AAAA,EAAA;AAGlB;ACrHA,MAAM,iBAAiB,2BAAmD,CAAC,OAAO,QAAQ;AACzF,QAAM,EAAE,UAAU,WAAW,gBAAgB,SAAS,mBAAmB,GAAG,SAAS;AAErF,8BACE,QAAA,EAAQ,GAAG,MAAM,gBAAc,QAAQ,KACtC,UAAA;AAAA,IAAA;AAAA,IAAS;AAAA,IAAE,CAAC,aAAa,oBAAC,QAAK,MAAK,gBAAe,MAAK,QAAA,CAAQ;AAAA,EAAA,GAClE;AAEF,CAAC;AAED,eAAe,cAAc;"}
|
package/dist/index.js
CHANGED
|
@@ -1,89 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const react = require("react");
|
|
5
|
+
const utils = require("@react-aria/utils");
|
|
6
|
+
const classix = require("classix");
|
|
7
|
+
const popover = require("@launchpad-ui/popover");
|
|
8
|
+
const button = require("@launchpad-ui/button");
|
|
9
|
+
const icons = require("@launchpad-ui/icons");
|
|
10
|
+
const Dropdown = (props) => {
|
|
11
|
+
const {
|
|
12
|
+
placement,
|
|
13
|
+
disabled,
|
|
14
|
+
targetClassName,
|
|
15
|
+
popoverClassName,
|
|
16
|
+
isOpen: isOpenProp,
|
|
17
|
+
onInteraction,
|
|
18
|
+
onSelect,
|
|
19
|
+
onStateChange,
|
|
20
|
+
children,
|
|
21
|
+
"data-test-id": testId = "dropdown",
|
|
22
|
+
...rest
|
|
23
|
+
} = props;
|
|
24
|
+
const triggerRef = react.useRef(null);
|
|
25
|
+
const [isOpen, setIsOpen] = react.useState(isOpenProp ?? false);
|
|
26
|
+
const [hasOpened, setHasOpened] = react.useState(isOpen);
|
|
27
|
+
react.useEffect(() => {
|
|
28
|
+
if (isOpenProp !== void 0) {
|
|
29
|
+
setIsOpen(isOpenProp);
|
|
30
|
+
}
|
|
31
|
+
}, [isOpenProp]);
|
|
32
|
+
react.useEffect(() => {
|
|
33
|
+
if (hasOpened && isOpen === false) {
|
|
34
|
+
setTimeout(() => {
|
|
35
|
+
const current = triggerRef.current;
|
|
36
|
+
if (!current) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const hasModal = current.closest?.(".has-overlay");
|
|
40
|
+
!hasModal && current.focus?.();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}, [isOpen, hasOpened]);
|
|
44
|
+
react.useEffect(() => {
|
|
45
|
+
setHasOpened(isOpen);
|
|
46
|
+
onStateChange?.({ isOpen });
|
|
47
|
+
}, [isOpen]);
|
|
48
|
+
const renderTrigger = () => {
|
|
49
|
+
const { target } = parseChildren();
|
|
50
|
+
return /* @__PURE__ */ react.cloneElement(target, {
|
|
51
|
+
"aria-haspopup": true,
|
|
52
|
+
"aria-expanded": !!isOpen,
|
|
53
|
+
ref: target.ref ? utils.mergeRefs(target.ref, triggerRef) : triggerRef,
|
|
54
|
+
isopen: isOpen?.toString()
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
const renderContent = () => {
|
|
58
|
+
return /* @__PURE__ */ react.cloneElement(parseChildren().content, {
|
|
59
|
+
onSelect: handleSelect
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
const handleSelect = (item) => {
|
|
63
|
+
setIsOpen(false);
|
|
64
|
+
onSelect?.(item, { isOpen: false });
|
|
65
|
+
};
|
|
66
|
+
const handlePopoverInteraction = (nextIsOpen) => {
|
|
67
|
+
setIsOpen(nextIsOpen);
|
|
68
|
+
};
|
|
69
|
+
const parseChildren = () => {
|
|
70
|
+
const [targetChild, contentChild] = react.Children.toArray(children);
|
|
71
|
+
return {
|
|
72
|
+
target: targetChild,
|
|
73
|
+
content: contentChild
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
const popoverTargetClasses = classix.cx("Dropdown-target", targetClassName);
|
|
77
|
+
const popoverClasses = classix.cx("Dropdown", popoverClassName);
|
|
78
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
79
|
+
popover.Popover,
|
|
80
|
+
{
|
|
81
|
+
isOpen,
|
|
82
|
+
placement,
|
|
83
|
+
onInteraction: onInteraction || handlePopoverInteraction,
|
|
84
|
+
restrictHeight: false,
|
|
85
|
+
disabled,
|
|
86
|
+
targetClassName: popoverTargetClasses,
|
|
87
|
+
popoverClassName: popoverClasses,
|
|
88
|
+
"data-test-id": testId,
|
|
89
|
+
...rest,
|
|
90
|
+
children: [
|
|
91
|
+
renderTrigger(),
|
|
92
|
+
renderContent()
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
);
|
|
68
96
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
children,
|
|
77
|
-
" ",
|
|
78
|
-
!hideCaret && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__launchpad_ui_icons.Icon, {
|
|
79
|
-
name: "chevron-down",
|
|
80
|
-
size: "small"
|
|
81
|
-
})
|
|
82
|
-
]
|
|
83
|
-
});
|
|
97
|
+
const DropdownButton = /* @__PURE__ */ react.forwardRef((props, ref) => {
|
|
98
|
+
const { children, hideCaret, "data-test-id": testId = "dropdown-button", ...rest } = props;
|
|
99
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(button.Button, { ...rest, "data-test-id": testId, ref, children: [
|
|
100
|
+
children,
|
|
101
|
+
" ",
|
|
102
|
+
!hideCaret && /* @__PURE__ */ jsxRuntime.jsx(icons.Icon, { name: "chevron-down", size: "small" })
|
|
103
|
+
] });
|
|
84
104
|
});
|
|
85
105
|
DropdownButton.displayName = "DropdownButton";
|
|
86
106
|
exports.Dropdown = Dropdown;
|
|
87
107
|
exports.DropdownButton = DropdownButton;
|
|
88
|
-
|
|
89
|
-
//# sourceMappingURL=index.js.map
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/Dropdown.tsx","../src/DropdownButton.tsx"],"sourcesContent":["import type { AriaAttributes, ForwardedRef, FunctionComponentElement, ReactElement } from 'react';\nimport { Children, cloneElement, useEffect, useRef, useState } from 'react';\nimport { mergeRefs } from '@react-aria/utils';\nimport { cx } from 'classix';\n\nimport type { PopoverProps } from '@launchpad-ui/popover';\nimport { Popover } from '@launchpad-ui/popover';\n\ntype DropdownState = {\n\tisOpen?: boolean;\n};\n\ntype DropdownProps<T extends string | object | number> = PopoverProps & {\n\tonSelect?: (item: T, stateChanges: DropdownState) => void;\n\tonStateChange?: (state: DropdownState) => void;\n};\n\n/**\n * @deprecated use `Menu` from `@launchpad-ui/components` instead\n *\n * https://launchpad.launchdarkly.com/?path=/docs/components-collections-menu--docs\n */\nconst Dropdown = <T extends string | object | number>(props: DropdownProps<T>) => {\n\tconst {\n\t\tplacement,\n\t\tdisabled,\n\t\ttargetClassName,\n\t\tpopoverClassName,\n\t\tisOpen: isOpenProp,\n\t\tonInteraction,\n\t\tonSelect,\n\t\tonStateChange,\n\t\tchildren,\n\t\t'data-test-id': testId = 'dropdown',\n\t\t...rest\n\t} = props;\n\n\tconst triggerRef = useRef<HTMLElement | null>(null);\n\tconst [isOpen, setIsOpen] = useState(isOpenProp ?? false);\n\tconst [hasOpened, setHasOpened] = useState(isOpen);\n\n\tuseEffect(() => {\n\t\tif (isOpenProp !== undefined) {\n\t\t\tsetIsOpen(isOpenProp);\n\t\t}\n\t}, [isOpenProp]);\n\n\tuseEffect(() => {\n\t\t// Focus the button upon closing for convenient tabbing\n\t\tif (hasOpened && isOpen === false) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tconst current = triggerRef.current;\n\t\t\t\tif (!current) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If a dropdown menu item triggers a modal, we do not want to focus the trigger. Instead\n\t\t\t\t// we let the modal components control their own focus.\n\t\t\t\t// Note that this is not ideal since closing the modal will not cause the dropdown trigger\n\t\t\t\t// to regain focus.\n\t\t\t\tconst hasModal = current.closest?.('.has-overlay');\n\n\t\t\t\t!hasModal && current.focus?.();\n\t\t\t});\n\t\t}\n\t}, [isOpen, hasOpened]);\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: ignore\n\tuseEffect(() => {\n\t\tsetHasOpened(isOpen);\n\t\tonStateChange?.({ isOpen });\n\t}, [isOpen]);\n\n\tconst renderTrigger = () => {\n\t\tconst { target } = parseChildren();\n\t\treturn cloneElement(target, {\n\t\t\t'aria-haspopup': true,\n\t\t\t'aria-expanded': !!isOpen,\n\t\t\tref: target.ref ? mergeRefs(target.ref, triggerRef) : triggerRef,\n\t\t\tisopen: isOpen?.toString(),\n\t\t});\n\t};\n\n\tconst renderContent = () => {\n\t\treturn cloneElement(parseChildren().content, {\n\t\t\tonSelect: handleSelect,\n\t\t});\n\t};\n\n\tconst handleSelect = (item: T) => {\n\t\tsetIsOpen(false);\n\t\tonSelect?.(item, { isOpen: false });\n\t};\n\n\tconst handlePopoverInteraction = (nextIsOpen: boolean) => {\n\t\tsetIsOpen(nextIsOpen);\n\t};\n\n\tconst parseChildren = () => {\n\t\tconst [targetChild, contentChild] = Children.toArray(children);\n\t\treturn {\n\t\t\ttarget: targetChild as FunctionComponentElement<\n\t\t\t\tAriaAttributes & { ref: ForwardedRef<HTMLElement | undefined>; isopen: string }\n\t\t\t>,\n\t\t\tcontent: contentChild as ReactElement<{ onSelect?: (item: T) => void }>,\n\t\t};\n\t};\n\n\tconst popoverTargetClasses = cx('Dropdown-target', targetClassName);\n\tconst popoverClasses = cx('Dropdown', popoverClassName);\n\n\treturn (\n\t\t<Popover\n\t\t\tisOpen={isOpen}\n\t\t\tplacement={placement}\n\t\t\tonInteraction={onInteraction || handlePopoverInteraction}\n\t\t\trestrictHeight={false}\n\t\t\tdisabled={disabled}\n\t\t\ttargetClassName={popoverTargetClasses}\n\t\t\tpopoverClassName={popoverClasses}\n\t\t\tdata-test-id={testId}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{renderTrigger()}\n\t\t\t{renderContent()}\n\t\t</Popover>\n\t);\n};\n\nexport { Dropdown };\nexport type { DropdownProps };\n","import { forwardRef } from 'react';\n\nimport type { ButtonProps } from '@launchpad-ui/button';\nimport { Button } from '@launchpad-ui/button';\nimport { Icon } from '@launchpad-ui/icons';\n\ntype DropdownButtonProps = ButtonProps & {\n\thideCaret?: boolean;\n};\n\nconst DropdownButton = forwardRef<HTMLButtonElement, DropdownButtonProps>((props, ref) => {\n\tconst { children, hideCaret, 'data-test-id': testId = 'dropdown-button', ...rest } = props;\n\n\treturn (\n\t\t<Button {...rest} data-test-id={testId} ref={ref}>\n\t\t\t{children} {!hideCaret && <Icon name=\"chevron-down\" size=\"small\" />}\n\t\t</Button>\n\t);\n});\n\nDropdownButton.displayName = 'DropdownButton';\n\nexport { DropdownButton };\nexport type { DropdownButtonProps };\n"],"names":["useRef","useState","useEffect","cloneElement","mergeRefs","Children","cx","jsxs","Popover","forwardRef","Button","jsx","Icon"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@launchpad-ui/dropdown",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.18",
|
|
4
4
|
"description": "An element that displays a list of actions or options to a user.",
|
|
5
5
|
"repository": "launchdarkly/launchpad-ui",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -20,21 +20,21 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"classix": "2.2.0",
|
|
23
|
-
"@launchpad-ui/button": "~0.15.
|
|
24
|
-
"@launchpad-ui/icons": "~0.26.
|
|
25
|
-
"@launchpad-ui/popover": "~0.14.
|
|
26
|
-
"@launchpad-ui/tokens": "~0.17.
|
|
23
|
+
"@launchpad-ui/button": "~0.15.18",
|
|
24
|
+
"@launchpad-ui/icons": "~0.26.3",
|
|
25
|
+
"@launchpad-ui/popover": "~0.14.6",
|
|
26
|
+
"@launchpad-ui/tokens": "~0.17.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@react-aria/utils": "3.34.1",
|
|
30
30
|
"@react-types/shared": "3.36.0",
|
|
31
|
-
"react": "19.2.
|
|
32
|
-
"react-dom": "19.2.
|
|
31
|
+
"react": "19.2.8",
|
|
32
|
+
"react-dom": "19.2.8"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@react-aria/utils": "3.34.1",
|
|
36
|
-
"react": "19
|
|
37
|
-
"react-dom": "19
|
|
35
|
+
"@react-aria/utils": "^3.34.1",
|
|
36
|
+
"react": "^19",
|
|
37
|
+
"react-dom": "^19"
|
|
38
38
|
},
|
|
39
39
|
"exports": {
|
|
40
40
|
".": {
|