@launchpad-ui/dropdown 0.2.7 → 0.3.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 +6 -36
- package/dist/Dropdown.d.ts.map +1 -1
- package/dist/index.es.js +83 -97
- package/dist/index.es.js.map +3 -3
- package/dist/index.js +86 -97
- package/dist/index.js.map +3 -3
- package/package.json +6 -6
package/dist/Dropdown.d.ts
CHANGED
@@ -1,43 +1,13 @@
|
|
1
|
-
|
2
|
-
import type {
|
3
|
-
import { Component } from 'react';
|
1
|
+
/// <reference types="react" />
|
2
|
+
import type { PopoverProps } from '@launchpad-ui/popover';
|
4
3
|
declare type DropdownState = {
|
5
4
|
isOpen?: boolean;
|
6
|
-
}
|
7
|
-
declare type DropdownProps<T extends string | object | number> = {
|
8
|
-
isOpen?: boolean;
|
9
|
-
placement?: PopoverPlacement;
|
5
|
+
};
|
6
|
+
declare type DropdownProps<T extends string | object | number> = PopoverProps & {
|
10
7
|
onSelect?: (item: T, stateChanges: DropdownState) => void;
|
11
|
-
onStateChange?: (state:
|
12
|
-
disabled?: boolean;
|
13
|
-
targetClassName?: string;
|
14
|
-
children: React.ReactNode;
|
15
|
-
onInteraction?: (nextIsOpen: boolean) => void;
|
16
|
-
popoverClassName?: string;
|
17
|
-
enforceFocus?: boolean;
|
18
|
-
[key: string]: unknown;
|
8
|
+
onStateChange?: (state: DropdownState) => void;
|
19
9
|
};
|
20
|
-
declare
|
21
|
-
triggerElement: HTMLElement | null | typeof Button;
|
22
|
-
refHandlers: {
|
23
|
-
trigger: (node: HTMLElement | null | typeof Button) => void;
|
24
|
-
};
|
25
|
-
state: {
|
26
|
-
isOpen: boolean;
|
27
|
-
};
|
28
|
-
componentDidUpdate(prevProps: DropdownProps<T>, prevState: DropdownState): void;
|
29
|
-
render(): JSX.Element;
|
30
|
-
renderTrigger(): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
31
|
-
renderContent(): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
32
|
-
handleSelect: (item: T) => void;
|
33
|
-
handlePopoverInteraction: (nextIsOpen: boolean) => void;
|
34
|
-
parseChildren(): {
|
35
|
-
target: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
36
|
-
content: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
37
|
-
};
|
38
|
-
updateState(state: DropdownState, selectedItem?: T): void;
|
39
|
-
isControlledProp(key: string): boolean;
|
40
|
-
}
|
10
|
+
declare const Dropdown: <T extends string | number | object>(props: DropdownProps<T>) => JSX.Element;
|
41
11
|
export { Dropdown };
|
42
12
|
export type { DropdownProps };
|
43
13
|
//# sourceMappingURL=Dropdown.d.ts.map
|
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":";AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAM1D,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/index.es.js
CHANGED
@@ -4,33 +4,33 @@ import * as React from "react";
|
|
4
4
|
// src/Dropdown.tsx
|
5
5
|
import { Popover } from "@launchpad-ui/popover";
|
6
6
|
import cx from "clsx";
|
7
|
-
import { Children, cloneElement,
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
if (this.props.isOpen !== prevProps.isOpen) {
|
29
|
-
this.setState({ isOpen: this.props.isOpen });
|
7
|
+
import { Children, cloneElement, useEffect, useRef, useState } from "react";
|
8
|
+
import { jsxs } from "react/jsx-runtime";
|
9
|
+
var Dropdown = (props) => {
|
10
|
+
const {
|
11
|
+
placement,
|
12
|
+
disabled,
|
13
|
+
targetClassName,
|
14
|
+
popoverClassName,
|
15
|
+
isOpen: isOpenProp,
|
16
|
+
onInteraction,
|
17
|
+
onSelect,
|
18
|
+
onStateChange,
|
19
|
+
children,
|
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);
|
30
28
|
}
|
31
|
-
|
29
|
+
}, [isOpenProp]);
|
30
|
+
useEffect(() => {
|
31
|
+
if (hasOpened && isOpen === false) {
|
32
32
|
setTimeout(() => {
|
33
|
-
const current =
|
33
|
+
const current = triggerRef.current;
|
34
34
|
if (!current) {
|
35
35
|
return;
|
36
36
|
}
|
@@ -38,91 +38,77 @@ var Dropdown = class extends Component {
|
|
38
38
|
!hasModal && current.focus?.();
|
39
39
|
});
|
40
40
|
}
|
41
|
-
}
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
isOpen: isOpenProp,
|
49
|
-
onInteraction,
|
50
|
-
...rest
|
51
|
-
} = this.props;
|
52
|
-
const { isOpen } = this.state;
|
53
|
-
const popoverTargetClasses = cx("Dropdown-target", targetClassName);
|
54
|
-
const popoverClasses = cx("Dropdown", popoverClassName);
|
55
|
-
return /* @__PURE__ */ React.createElement(Popover, {
|
56
|
-
isOpen,
|
57
|
-
placement,
|
58
|
-
onInteraction: onInteraction || this.handlePopoverInteraction,
|
59
|
-
restrictHeight: false,
|
60
|
-
disabled,
|
61
|
-
targetClassName: popoverTargetClasses,
|
62
|
-
popoverClassName: popoverClasses,
|
63
|
-
...rest
|
64
|
-
}, this.renderTrigger(), this.renderContent());
|
65
|
-
}
|
66
|
-
renderTrigger() {
|
67
|
-
return cloneElement(this.parseChildren().target, {
|
41
|
+
}, [isOpen, hasOpened]);
|
42
|
+
useEffect(() => {
|
43
|
+
setHasOpened(isOpen);
|
44
|
+
onStateChange?.({ isOpen });
|
45
|
+
}, [isOpen]);
|
46
|
+
const renderTrigger = () => {
|
47
|
+
return cloneElement(parseChildren().target, {
|
68
48
|
"aria-haspopup": true,
|
69
|
-
"aria-expanded":
|
70
|
-
ref:
|
71
|
-
isopen:
|
49
|
+
"aria-expanded": isOpen ? true : false,
|
50
|
+
ref: triggerRef,
|
51
|
+
isopen: isOpen?.toString()
|
72
52
|
});
|
73
|
-
}
|
74
|
-
renderContent() {
|
75
|
-
return cloneElement(
|
76
|
-
onSelect:
|
53
|
+
};
|
54
|
+
const renderContent = () => {
|
55
|
+
return cloneElement(parseChildren().content, {
|
56
|
+
onSelect: handleSelect
|
77
57
|
});
|
78
|
-
}
|
79
|
-
|
80
|
-
|
58
|
+
};
|
59
|
+
const handleSelect = (item) => {
|
60
|
+
setIsOpen(false);
|
61
|
+
onSelect?.(item, { isOpen: false });
|
62
|
+
};
|
63
|
+
const handlePopoverInteraction = (nextIsOpen) => {
|
64
|
+
setIsOpen(nextIsOpen);
|
65
|
+
};
|
66
|
+
const parseChildren = () => {
|
67
|
+
const [targetChild, contentChild] = Children.toArray(children);
|
81
68
|
return {
|
82
69
|
target: targetChild,
|
83
70
|
content: contentChild
|
84
71
|
};
|
85
|
-
}
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
}
|
103
|
-
if (Object.keys(stateChanges).length) {
|
104
|
-
this.props.onStateChange?.(stateChanges);
|
105
|
-
}
|
106
|
-
});
|
107
|
-
}
|
108
|
-
isControlledProp(key) {
|
109
|
-
return this.props[key] !== void 0;
|
110
|
-
}
|
72
|
+
};
|
73
|
+
const popoverTargetClasses = cx("Dropdown-target", targetClassName);
|
74
|
+
const popoverClasses = cx("Dropdown", popoverClassName);
|
75
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
76
|
+
isOpen,
|
77
|
+
placement,
|
78
|
+
onInteraction: onInteraction || handlePopoverInteraction,
|
79
|
+
restrictHeight: false,
|
80
|
+
disabled,
|
81
|
+
targetClassName: popoverTargetClasses,
|
82
|
+
popoverClassName: popoverClasses,
|
83
|
+
...rest,
|
84
|
+
children: [
|
85
|
+
renderTrigger(),
|
86
|
+
renderContent()
|
87
|
+
]
|
88
|
+
});
|
111
89
|
};
|
112
90
|
|
113
91
|
// src/DropdownButton.tsx
|
114
92
|
import { Button } from "@launchpad-ui/button";
|
115
93
|
import { ExpandMore, IconSize } from "@launchpad-ui/icons";
|
116
94
|
import { forwardRef } from "react";
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
...rest
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
95
|
+
import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
|
96
|
+
var DropdownButton = forwardRef(
|
97
|
+
(props, ref) => {
|
98
|
+
const { children, hideCaret, ...rest } = props;
|
99
|
+
return /* @__PURE__ */ jsxs2(Button, {
|
100
|
+
...rest,
|
101
|
+
ref,
|
102
|
+
children: [
|
103
|
+
children,
|
104
|
+
" ",
|
105
|
+
!hideCaret && /* @__PURE__ */ jsx(ExpandMore, {
|
106
|
+
size: IconSize.SMALL
|
107
|
+
})
|
108
|
+
]
|
109
|
+
});
|
110
|
+
}
|
111
|
+
);
|
126
112
|
DropdownButton.displayName = "DropdownButton";
|
127
113
|
export {
|
128
114
|
Dropdown,
|
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/Dropdown.tsx", "../src/DropdownButton.tsx"],
|
4
|
-
"sourcesContent": ["import * as React from 'react';\nexport { React };\n", "
|
5
|
-
"mappings": ";AAAA;;;
|
6
|
-
"names": []
|
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};\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;AAkBrB,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
7
|
}
|
package/dist/index.js
CHANGED
@@ -17,7 +17,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
17
17
|
}
|
18
18
|
return to;
|
19
19
|
};
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
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
|
+
));
|
21
24
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
22
25
|
|
23
26
|
// src/index.ts
|
@@ -35,32 +38,32 @@ var React = __toESM(require("react"));
|
|
35
38
|
var import_popover = require("@launchpad-ui/popover");
|
36
39
|
var import_clsx = __toESM(require("clsx"));
|
37
40
|
var import_react = require("react");
|
38
|
-
var
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if (this.props.isOpen !== prevProps.isOpen) {
|
59
|
-
this.setState({ isOpen: this.props.isOpen });
|
41
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
42
|
+
var Dropdown = (props) => {
|
43
|
+
const {
|
44
|
+
placement,
|
45
|
+
disabled,
|
46
|
+
targetClassName,
|
47
|
+
popoverClassName,
|
48
|
+
isOpen: isOpenProp,
|
49
|
+
onInteraction,
|
50
|
+
onSelect,
|
51
|
+
onStateChange,
|
52
|
+
children,
|
53
|
+
...rest
|
54
|
+
} = props;
|
55
|
+
const triggerRef = (0, import_react.useRef)(null);
|
56
|
+
const [isOpen, setIsOpen] = (0, import_react.useState)(isOpenProp ?? false);
|
57
|
+
const [hasOpened, setHasOpened] = (0, import_react.useState)(isOpen);
|
58
|
+
(0, import_react.useEffect)(() => {
|
59
|
+
if (isOpenProp !== void 0) {
|
60
|
+
setIsOpen(isOpenProp);
|
60
61
|
}
|
61
|
-
|
62
|
+
}, [isOpenProp]);
|
63
|
+
(0, import_react.useEffect)(() => {
|
64
|
+
if (hasOpened && isOpen === false) {
|
62
65
|
setTimeout(() => {
|
63
|
-
const current =
|
66
|
+
const current = triggerRef.current;
|
64
67
|
if (!current) {
|
65
68
|
return;
|
66
69
|
}
|
@@ -68,91 +71,77 @@ var Dropdown = class extends import_react.Component {
|
|
68
71
|
!hasModal && current.focus?.();
|
69
72
|
});
|
70
73
|
}
|
71
|
-
}
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
isOpen: isOpenProp,
|
79
|
-
onInteraction,
|
80
|
-
...rest
|
81
|
-
} = this.props;
|
82
|
-
const { isOpen } = this.state;
|
83
|
-
const popoverTargetClasses = (0, import_clsx.default)("Dropdown-target", targetClassName);
|
84
|
-
const popoverClasses = (0, import_clsx.default)("Dropdown", popoverClassName);
|
85
|
-
return /* @__PURE__ */ React.createElement(import_popover.Popover, {
|
86
|
-
isOpen,
|
87
|
-
placement,
|
88
|
-
onInteraction: onInteraction || this.handlePopoverInteraction,
|
89
|
-
restrictHeight: false,
|
90
|
-
disabled,
|
91
|
-
targetClassName: popoverTargetClasses,
|
92
|
-
popoverClassName: popoverClasses,
|
93
|
-
...rest
|
94
|
-
}, this.renderTrigger(), this.renderContent());
|
95
|
-
}
|
96
|
-
renderTrigger() {
|
97
|
-
return (0, import_react.cloneElement)(this.parseChildren().target, {
|
74
|
+
}, [isOpen, hasOpened]);
|
75
|
+
(0, import_react.useEffect)(() => {
|
76
|
+
setHasOpened(isOpen);
|
77
|
+
onStateChange?.({ isOpen });
|
78
|
+
}, [isOpen]);
|
79
|
+
const renderTrigger = () => {
|
80
|
+
return (0, import_react.cloneElement)(parseChildren().target, {
|
98
81
|
"aria-haspopup": true,
|
99
|
-
"aria-expanded":
|
100
|
-
ref:
|
101
|
-
isopen:
|
82
|
+
"aria-expanded": isOpen ? true : false,
|
83
|
+
ref: triggerRef,
|
84
|
+
isopen: isOpen?.toString()
|
102
85
|
});
|
103
|
-
}
|
104
|
-
renderContent() {
|
105
|
-
return (0, import_react.cloneElement)(
|
106
|
-
onSelect:
|
86
|
+
};
|
87
|
+
const renderContent = () => {
|
88
|
+
return (0, import_react.cloneElement)(parseChildren().content, {
|
89
|
+
onSelect: handleSelect
|
107
90
|
});
|
108
|
-
}
|
109
|
-
|
110
|
-
|
91
|
+
};
|
92
|
+
const handleSelect = (item) => {
|
93
|
+
setIsOpen(false);
|
94
|
+
onSelect?.(item, { isOpen: false });
|
95
|
+
};
|
96
|
+
const handlePopoverInteraction = (nextIsOpen) => {
|
97
|
+
setIsOpen(nextIsOpen);
|
98
|
+
};
|
99
|
+
const parseChildren = () => {
|
100
|
+
const [targetChild, contentChild] = import_react.Children.toArray(children);
|
111
101
|
return {
|
112
102
|
target: targetChild,
|
113
103
|
content: contentChild
|
114
104
|
};
|
115
|
-
}
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
}
|
133
|
-
if (Object.keys(stateChanges).length) {
|
134
|
-
this.props.onStateChange?.(stateChanges);
|
135
|
-
}
|
136
|
-
});
|
137
|
-
}
|
138
|
-
isControlledProp(key) {
|
139
|
-
return this.props[key] !== void 0;
|
140
|
-
}
|
105
|
+
};
|
106
|
+
const popoverTargetClasses = (0, import_clsx.default)("Dropdown-target", targetClassName);
|
107
|
+
const popoverClasses = (0, import_clsx.default)("Dropdown", popoverClassName);
|
108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_popover.Popover, {
|
109
|
+
isOpen,
|
110
|
+
placement,
|
111
|
+
onInteraction: onInteraction || handlePopoverInteraction,
|
112
|
+
restrictHeight: false,
|
113
|
+
disabled,
|
114
|
+
targetClassName: popoverTargetClasses,
|
115
|
+
popoverClassName: popoverClasses,
|
116
|
+
...rest,
|
117
|
+
children: [
|
118
|
+
renderTrigger(),
|
119
|
+
renderContent()
|
120
|
+
]
|
121
|
+
});
|
141
122
|
};
|
142
123
|
|
143
124
|
// src/DropdownButton.tsx
|
144
125
|
var import_button = require("@launchpad-ui/button");
|
145
126
|
var import_icons = require("@launchpad-ui/icons");
|
146
127
|
var import_react2 = require("react");
|
147
|
-
var
|
148
|
-
|
149
|
-
|
150
|
-
...rest
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
128
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
129
|
+
var DropdownButton = (0, import_react2.forwardRef)(
|
130
|
+
(props, ref) => {
|
131
|
+
const { children, hideCaret, ...rest } = props;
|
132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_button.Button, {
|
133
|
+
...rest,
|
134
|
+
ref,
|
135
|
+
children: [
|
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
|
+
);
|
156
145
|
DropdownButton.displayName = "DropdownButton";
|
157
146
|
// Annotate the CommonJS export names for ESM import in node:
|
158
147
|
0 && (module.exports = {
|
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/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", "
|
5
|
-
"mappings": "
|
6
|
-
"names": []
|
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};\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;AAkBrB;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
7
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@launchpad-ui/dropdown",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.3.0",
|
4
4
|
"status": "beta",
|
5
5
|
"publishConfig": {
|
6
6
|
"access": "public"
|
@@ -25,15 +25,15 @@
|
|
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.4.0",
|
29
|
+
"@launchpad-ui/icons": "~0.3.0",
|
30
|
+
"@launchpad-ui/popover": "~0.6.0",
|
31
31
|
"@launchpad-ui/tokens": "~0.1.5",
|
32
32
|
"clsx": "^1.2.0"
|
33
33
|
},
|
34
34
|
"peerDependencies": {
|
35
|
-
"react": "^
|
36
|
-
"react-dom": "^
|
35
|
+
"react": "^18.0.0",
|
36
|
+
"react-dom": "^18.0.0"
|
37
37
|
},
|
38
38
|
"devDependencies": {
|
39
39
|
"react": "^18.2.0",
|