@homebound/beam 2.153.2 → 2.156.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.
|
@@ -20,4 +20,4 @@ export interface ButtonProps extends BeamButtonProps, BeamFocusableProps {
|
|
|
20
20
|
}
|
|
21
21
|
export declare function Button(props: ButtonProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
22
22
|
export declare type ButtonSize = "sm" | "md" | "lg";
|
|
23
|
-
export declare type ButtonVariant = "primary" | "secondary" | "tertiary" | "danger" | "text";
|
|
23
|
+
export declare type ButtonVariant = "primary" | "secondary" | "tertiary" | "tertiaryDanger" | "danger" | "text";
|
|
@@ -11,9 +11,11 @@ const getInteractiveElement_1 = require("../utils/getInteractiveElement");
|
|
|
11
11
|
const useTestIds_1 = require("../utils/useTestIds");
|
|
12
12
|
function Button(props) {
|
|
13
13
|
const { onClick: onPress, disabled, endAdornment, menuTriggerProps, tooltip, openInNew, download, contrast = false, ...otherProps } = props;
|
|
14
|
-
const
|
|
14
|
+
const asLink = typeof onPress === "string";
|
|
15
|
+
const showExternalLinkIcon = (asLink && (0, utils_1.isAbsoluteUrl)(onPress)) || openInNew;
|
|
16
|
+
const [asyncInProgress, setAsyncInProgress] = (0, react_1.useState)(false);
|
|
15
17
|
const isDisabled = !!disabled;
|
|
16
|
-
const ariaProps = { onPress, isDisabled, ...otherProps, ...menuTriggerProps };
|
|
18
|
+
const ariaProps = { onPress, isDisabled: isDisabled || asyncInProgress, ...otherProps, ...menuTriggerProps };
|
|
17
19
|
const { label,
|
|
18
20
|
// Default the icon based on other properties.
|
|
19
21
|
icon = download ? "download" : showExternalLinkIcon ? "linkExternal" : undefined, variant = "primary", size = "sm", buttonRef, } = ariaProps;
|
|
@@ -21,30 +23,34 @@ function Button(props) {
|
|
|
21
23
|
const tid = (0, useTestIds_1.useTestIds)(props, label);
|
|
22
24
|
const { buttonProps, isPressed } = (0, react_aria_1.useButton)({
|
|
23
25
|
...ariaProps,
|
|
24
|
-
onPress:
|
|
25
|
-
|
|
26
|
+
onPress: asLink
|
|
27
|
+
? utils_1.noop
|
|
28
|
+
: (e) => {
|
|
29
|
+
const result = onPress(e);
|
|
30
|
+
if (isPromise(result)) {
|
|
31
|
+
setAsyncInProgress(true);
|
|
32
|
+
result.finally(() => setAsyncInProgress(false));
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
},
|
|
36
|
+
elementType: asLink ? "a" : "button",
|
|
26
37
|
}, ref);
|
|
27
38
|
const { isFocusVisible, focusProps } = (0, react_aria_1.useFocusRing)(ariaProps);
|
|
28
39
|
const { hoverProps, isHovered } = (0, react_aria_1.useHover)(ariaProps);
|
|
29
|
-
const { baseStyles, hoverStyles, disabledStyles, pressedStyles } = (0, react_1.useMemo)(() => getButtonStyles(variant, size, contrast), [variant, size, contrast]);
|
|
30
|
-
const focusStyles = (0, react_1.useMemo)(() => !contrast
|
|
31
|
-
? variant === "danger"
|
|
32
|
-
? Css_1.Css.bshDanger.$
|
|
33
|
-
: Css_1.Css.bshFocus.$
|
|
34
|
-
: Css_1.Css.boxShadow(`0 0 0 2px ${variant === "tertiary" ? Css_1.Palette.LightBlue700 : Css_1.Palette.White}`).if(variant === "tertiary").bgGray700.white.$, [variant, contrast]);
|
|
40
|
+
const { baseStyles, hoverStyles, disabledStyles, pressedStyles, focusStyles } = (0, react_1.useMemo)(() => getButtonStyles(variant, size, contrast), [variant, size, contrast]);
|
|
35
41
|
const buttonContent = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon && (0, jsx_runtime_1.jsx)(components_1.Icon, { xss: iconStyles[size], icon: icon }, void 0), label, endAdornment && (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.ml1.$ }, { children: endAdornment }), void 0)] }, void 0));
|
|
36
42
|
const buttonAttrs = {
|
|
37
43
|
ref: ref,
|
|
38
44
|
...buttonProps,
|
|
39
45
|
...focusProps,
|
|
40
46
|
...hoverProps,
|
|
41
|
-
className:
|
|
47
|
+
className: asLink ? components_1.navLink : undefined,
|
|
42
48
|
css: {
|
|
43
49
|
...Css_1.Css.buttonBase.tt("inherit").$,
|
|
44
50
|
...baseStyles,
|
|
45
51
|
...(isHovered && !isPressed ? hoverStyles : {}),
|
|
46
52
|
...(isPressed ? pressedStyles : {}),
|
|
47
|
-
...(isDisabled ? { ...disabledStyles, ...Css_1.Css.cursorNotAllowed.$ } : {}),
|
|
53
|
+
...(isDisabled || asyncInProgress ? { ...disabledStyles, ...Css_1.Css.cursorNotAllowed.$ } : {}),
|
|
48
54
|
...(isFocusVisible ? focusStyles : {}),
|
|
49
55
|
},
|
|
50
56
|
...tid,
|
|
@@ -74,30 +80,44 @@ const variantStyles = (contrast) => ({
|
|
|
74
80
|
hoverStyles: Css_1.Css.bgLightBlue900.if(contrast).bgLightBlue500.$,
|
|
75
81
|
pressedStyles: Css_1.Css.bgLightBlue500.if(contrast).bgLightBlue900.$,
|
|
76
82
|
disabledStyles: Css_1.Css.bgLightBlue200.if(contrast).gray600.bgLightBlue900.$,
|
|
83
|
+
focusStyles: Css_1.Css.bshFocus.if(contrast).boxShadow(`0 0 0 2px ${Css_1.Palette.White}`).$,
|
|
77
84
|
},
|
|
78
85
|
secondary: {
|
|
79
86
|
baseStyles: Css_1.Css.bgWhite.bGray300.bw1.ba.gray800.$,
|
|
80
87
|
hoverStyles: Css_1.Css.bgGray100.if(contrast).bgGray300.$,
|
|
81
88
|
pressedStyles: Css_1.Css.bgGray200.if(contrast).bgGray100.$,
|
|
82
89
|
disabledStyles: Css_1.Css.bgWhite.gray400.$,
|
|
90
|
+
focusStyles: Css_1.Css.bshFocus.if(contrast).boxShadow(`0 0 0 2px ${Css_1.Palette.White}`).$,
|
|
83
91
|
},
|
|
84
92
|
tertiary: {
|
|
85
93
|
baseStyles: Css_1.Css.bgTransparent.lightBlue700.if(contrast).lightBlue400.$,
|
|
86
94
|
hoverStyles: Css_1.Css.bgGray100.if(contrast).bgGray700.white.$,
|
|
87
95
|
pressedStyles: Css_1.Css.lightBlue900.if(contrast).bgWhite.gray900.$,
|
|
88
96
|
disabledStyles: Css_1.Css.gray400.if(contrast).gray700.$,
|
|
97
|
+
focusStyles: Css_1.Css.bshFocus.if(contrast).boxShadow(`0 0 0 2px ${Css_1.Palette.LightBlue700}`).bgGray700.white.$,
|
|
98
|
+
},
|
|
99
|
+
tertiaryDanger: {
|
|
100
|
+
baseStyles: Css_1.Css.bgTransparent.red500.if(contrast).red500.$,
|
|
101
|
+
hoverStyles: Css_1.Css.bgGray100.if(contrast).bgGray700.white.$,
|
|
102
|
+
pressedStyles: Css_1.Css.red900.if(contrast).bgWhite.gray900.$,
|
|
103
|
+
disabledStyles: Css_1.Css.gray400.if(contrast).gray700.$,
|
|
104
|
+
focusStyles: Css_1.Css.boxShadow(`0px 0px 0px 2px ${Css_1.Palette.White}, 0px 0px 0px 4px ${Css_1.Palette.Red500}`)
|
|
105
|
+
.if(contrast)
|
|
106
|
+
.boxShadow(`0px 0px 0px 2px ${Css_1.Palette.Red500}`).$,
|
|
89
107
|
},
|
|
90
108
|
danger: {
|
|
91
109
|
baseStyles: Css_1.Css.bgRed900.white.if(contrast).bgRed800.$,
|
|
92
110
|
hoverStyles: Css_1.Css.bgRed500.if(contrast).bgRed600.$,
|
|
93
111
|
pressedStyles: Css_1.Css.bgRed900.if(contrast).bgRed800.$,
|
|
94
112
|
disabledStyles: Css_1.Css.bgRed200.if(contrast).bgRed900.gray600.$,
|
|
113
|
+
focusStyles: Css_1.Css.bshDanger.if(contrast).boxShadow(`0 0 0 2px ${Css_1.Palette.White}`).$,
|
|
95
114
|
},
|
|
96
115
|
text: {
|
|
97
116
|
baseStyles: Css_1.Css.lightBlue700.add("fontSize", "inherit").if(contrast).lightBlue400.$,
|
|
98
117
|
hoverStyles: Css_1.Css.lightBlue600.if(contrast).lightBlue300.$,
|
|
99
118
|
pressedStyles: Css_1.Css.lightBlue700.if(contrast).lightBlue200.$,
|
|
100
119
|
disabledStyles: Css_1.Css.lightBlue300.if(contrast).lightBlue700.$,
|
|
120
|
+
focusStyles: Css_1.Css.bshFocus.if(contrast).boxShadow(`0 0 0 2px ${Css_1.Palette.White}`).$,
|
|
101
121
|
},
|
|
102
122
|
});
|
|
103
123
|
const sizeStyles = {
|
|
@@ -110,3 +130,6 @@ const iconStyles = {
|
|
|
110
130
|
md: Css_1.Css.mr1.$,
|
|
111
131
|
lg: Css_1.Css.mrPx(10).$,
|
|
112
132
|
};
|
|
133
|
+
function isPromise(obj) {
|
|
134
|
+
return typeof obj === "object" && "then" in obj && typeof obj.then === "function";
|
|
135
|
+
}
|
|
@@ -56,7 +56,7 @@ function SuperDrawer() {
|
|
|
56
56
|
const { content } = currentContent;
|
|
57
57
|
// Also get the first / non-detail element on the stack
|
|
58
58
|
const firstContent = contentStack.current[0].opts;
|
|
59
|
-
const { onPrevClick, onNextClick, titleRightContent, titleLeftContent } = firstContent;
|
|
59
|
+
const { onPrevClick, onNextClick, titleRightContent, titleLeftContent, hideControls } = firstContent;
|
|
60
60
|
const isDetail = currentContent !== firstContent;
|
|
61
61
|
const title = currentContent.title || firstContent.title;
|
|
62
62
|
return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: content && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.Global, { styles: { body: Css_1.Css.overflowHidden.$ } }, void 0), (0, react_1.createElement)(framer_motion_1.motion.div, { ...testId,
|
|
@@ -80,7 +80,7 @@ function SuperDrawer() {
|
|
|
80
80
|
// Preventing clicks from triggering parent onClick
|
|
81
81
|
onClick: (e) => e.stopPropagation() }, { children: (0, jsx_runtime_1.jsxs)(form_state_1.AutoSaveStatusProvider, { children: [(0, jsx_runtime_1.jsxs)("header", Object.assign({ css: Css_1.Css.df.p3.bb.bGray200.df.aic.jcsb.gap2.$ }, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.aic.$ }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.xl2Em.gray900.mr2.$ }, testId.title, { ref: drawerHeaderRef }, { children: !modalState.current && (title || null) }), void 0), !modalState.current && (titleLeftContent || null)] }), void 0), !modalState.current && (
|
|
82
82
|
// Forcing height to 32px to match title height
|
|
83
|
-
(0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.childGap3.aic.hPx(32).fs0.$ }, { children: [titleRightContent || null, (0, jsx_runtime_1.jsx)(components_1.ButtonGroup, Object.assign({ buttons: [
|
|
83
|
+
(0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.childGap3.aic.hPx(32).fs0.$ }, { children: [titleRightContent || null, !hideControls && ((0, jsx_runtime_1.jsx)(components_1.ButtonGroup, Object.assign({ buttons: [
|
|
84
84
|
{
|
|
85
85
|
icon: "chevronLeft",
|
|
86
86
|
onClick: () => onPrevClick && onPrevClick(),
|
|
@@ -91,7 +91,7 @@ function SuperDrawer() {
|
|
|
91
91
|
onClick: () => onNextClick && onNextClick(),
|
|
92
92
|
disabled: !onNextClick || isDetail,
|
|
93
93
|
},
|
|
94
|
-
] }, testId.headerActions), void 0), (0, jsx_runtime_1.jsx)(components_1.IconButton, Object.assign({ icon: "x", onClick: closeDrawer }, testId.close), void 0)] }), void 0))] }), void 0), content, modalState.current && (
|
|
94
|
+
] }, testId.headerActions), void 0)), (0, jsx_runtime_1.jsx)(components_1.IconButton, Object.assign({ icon: "x", onClick: closeDrawer }, testId.close), void 0)] }), void 0))] }), void 0), content, modalState.current && (
|
|
95
95
|
// Forcing some design constraints on the modal component
|
|
96
96
|
(0, jsx_runtime_1.jsxs)("div", Object.assign({ css:
|
|
97
97
|
// topPX(81) is the offset from the header
|
|
@@ -11,6 +11,8 @@ export interface OpenInDrawerOpts {
|
|
|
11
11
|
onPrevClick?: () => void;
|
|
12
12
|
/** Invokes right, disabled if undefined. */
|
|
13
13
|
onNextClick?: () => void;
|
|
14
|
+
/** Hides the pagination controls for `onNextClick` and `onPrevClick` */
|
|
15
|
+
hideControls?: true;
|
|
14
16
|
/** Adds a callback that is called _after_ close has definitely happened. */
|
|
15
17
|
onClose?: () => void;
|
|
16
18
|
content: ReactNode;
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface BeamButtonProps {
|
|
|
15
15
|
*/
|
|
16
16
|
disabled?: boolean | ReactNode;
|
|
17
17
|
/** If function, then it is the handler that is called when the press is released over the target. Otherwise if string, it is the URL path for the link */
|
|
18
|
-
onClick: ((e: PressEvent) => void) | string;
|
|
18
|
+
onClick: ((e: PressEvent) => void) | ((e: PressEvent) => Promise<void>) | string;
|
|
19
19
|
/** Text to be shown via a tooltip when the user hovers over the button */
|
|
20
20
|
tooltip?: ReactNode;
|
|
21
21
|
/** Whether to open link in a new tab. This only effects the element if the `onClick` is a `string`/URL. */
|