@homebound/beam 2.143.1 → 2.145.1

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.
@@ -0,0 +1,8 @@
1
+ export interface AvatarProps {
2
+ src: string | undefined;
3
+ name: string;
4
+ size?: AvatarSize;
5
+ showName?: boolean;
6
+ }
7
+ export declare function Avatar({ src, name, size, showName, ...others }: AvatarProps): import("@emotion/react/jsx-runtime").JSX.Element;
8
+ export declare type AvatarSize = "sm" | "md" | "lg" | "xl";
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Avatar = void 0;
4
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const Css_1 = require("../Css");
7
+ const utils_1 = require("../utils");
8
+ function Avatar({ src, name, size = "md", showName = false, ...others }) {
9
+ const tid = (0, utils_1.useTestIds)(others, "avatar");
10
+ const px = sizeToPixel[size];
11
+ const [showFallback, setShowFallback] = (0, react_1.useState)(src === undefined);
12
+ const styles = Css_1.Css.br100.wPx(px).hPx(px).overflowHidden.$;
13
+ const img = showFallback ? ((0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...styles, ...Css_1.Css[sizeToFallbackTypeScale[size]].bgLightBlue700.white.df.aic.jcc.$ } }, tid, { children: nameToInitials(name) }), void 0)) : ((0, jsx_runtime_1.jsx)("img", Object.assign({ src: src, alt: name, css: { ...styles, ...Css_1.Css.objectCover.$ }, onError: () => setShowFallback(true), loading: "lazy" }, tid), void 0));
14
+ return showName ? ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.dif.aic.gap1.if(size === "lg" || size === "xl").fdc.$ }, { children: [img, (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css[sizeToTypeScale[size]].$ }, { children: name }), void 0)] }), void 0)) : (img);
15
+ }
16
+ exports.Avatar = Avatar;
17
+ const sizeToPixel = {
18
+ sm: 24,
19
+ md: 36,
20
+ lg: 48,
21
+ xl: 72,
22
+ };
23
+ const sizeToFallbackTypeScale = {
24
+ sm: "tiny",
25
+ md: "sm",
26
+ lg: "lg",
27
+ xl: "xl3",
28
+ };
29
+ const sizeToTypeScale = {
30
+ sm: "baseEm",
31
+ md: "baseEm",
32
+ lg: "lg",
33
+ xl: "xl3",
34
+ };
35
+ function nameToInitials(name) {
36
+ return (name
37
+ .split(" ")
38
+ .map((n) => n[0].toUpperCase())
39
+ .join("")
40
+ // Return at most 3 initials
41
+ .slice(0, 3));
42
+ }
@@ -0,0 +1,31 @@
1
+ import { AriaButtonProps } from "@react-types/button";
2
+ import { RefObject } from "react";
3
+ import { AvatarProps } from "./Avatar";
4
+ import { BeamButtonProps, BeamFocusableProps } from "../interfaces";
5
+ export interface AvatarButtonProps extends AvatarProps, BeamButtonProps, BeamFocusableProps {
6
+ menuTriggerProps?: AriaButtonProps;
7
+ buttonRef?: RefObject<HTMLButtonElement>;
8
+ }
9
+ export declare function AvatarButton(props: AvatarButtonProps): import("@emotion/react/jsx-runtime").JSX.Element;
10
+ export declare const hoverStyles: {
11
+ boxShadow: import("csstype").Property.BoxShadow | undefined;
12
+ };
13
+ export declare const pressedStyles: {
14
+ borderRadius: import("csstype").Property.BorderRadius<0 | (string & {})> | undefined;
15
+ } & {
16
+ backgroundColor: import("csstype").Property.BackgroundColor | undefined;
17
+ } & {
18
+ content: import("csstype").Property.Content | undefined;
19
+ } & {
20
+ width: import("csstype").Property.Width<0 | (string & {})> | undefined;
21
+ } & {
22
+ height: import("csstype").Property.Height<0 | (string & {})> | undefined;
23
+ } & {
24
+ position: import("csstype").Property.Position | undefined;
25
+ } & {
26
+ top: import("csstype").Property.Top<0 | (string & {})> | undefined;
27
+ } & {
28
+ left: import("csstype").Property.Left<0 | (string & {})> | undefined;
29
+ } & {
30
+ opacity: import("csstype").Property.Opacity | undefined;
31
+ };
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pressedStyles = exports.hoverStyles = exports.AvatarButton = void 0;
4
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_aria_1 = require("react-aria");
7
+ const components_1 = require("./");
8
+ const Avatar_1 = require("./Avatar");
9
+ const Css_1 = require("../Css");
10
+ const utils_1 = require("../utils");
11
+ const getInteractiveElement_1 = require("../utils/getInteractiveElement");
12
+ const useTestIds_1 = require("../utils/useTestIds");
13
+ function AvatarButton(props) {
14
+ const { onClick: onPress, disabled, autoFocus, buttonRef, tooltip, menuTriggerProps, openInNew, ...avatarProps } = props;
15
+ const isDisabled = !!disabled;
16
+ const ariaProps = { onPress, isDisabled, autoFocus, ...menuTriggerProps };
17
+ // eslint-disable-next-line react-hooks/rules-of-hooks
18
+ const ref = buttonRef || (0, react_1.useRef)(null);
19
+ const { buttonProps, isPressed } = (0, react_aria_1.useButton)({
20
+ ...ariaProps,
21
+ onPress: typeof onPress === "string" ? utils_1.noop : onPress,
22
+ elementType: typeof onPress === "string" ? "a" : "button",
23
+ }, ref);
24
+ const { focusProps, isFocusVisible } = (0, react_aria_1.useFocusRing)(ariaProps);
25
+ const { hoverProps, isHovered } = (0, react_aria_1.useHover)(ariaProps);
26
+ const tid = (0, useTestIds_1.useTestIds)(props, avatarProps.name);
27
+ const styles = (0, react_1.useMemo)(() => ({
28
+ ...resetStyles,
29
+ ...(isHovered && exports.hoverStyles),
30
+ ...(isPressed && exports.pressedStyles),
31
+ ...(isFocusVisible && focusStyles),
32
+ ...(isDisabled && disabledStyles),
33
+ }), [isHovered, isFocusVisible, isDisabled, isPressed]);
34
+ const buttonAttrs = {
35
+ ...tid.button,
36
+ ...buttonProps,
37
+ ...focusProps,
38
+ ...hoverProps,
39
+ className: typeof onPress === "string" ? components_1.navLink : undefined,
40
+ ref: ref,
41
+ css: styles,
42
+ };
43
+ // If we're disabled b/c of a non-boolean ReactNode, or the caller specified tooltip text, then show it in a tooltip
44
+ return (0, components_1.maybeTooltip)({
45
+ title: (0, components_1.resolveTooltip)(disabled, tooltip),
46
+ placement: "top",
47
+ children: (0, getInteractiveElement_1.getButtonOrLink)((0, jsx_runtime_1.jsx)(Avatar_1.Avatar, Object.assign({}, avatarProps, tid), void 0), onPress, buttonAttrs, openInNew),
48
+ });
49
+ }
50
+ exports.AvatarButton = AvatarButton;
51
+ const resetStyles = Css_1.Css.br100.cursorPointer.outline0.relative.$;
52
+ exports.hoverStyles = Css_1.Css.boxShadow(`0 0 4px ${Css_1.Palette.Gray900}`).$;
53
+ const focusStyles = Css_1.Css.bshFocus.$;
54
+ const disabledStyles = Css_1.Css.cursorNotAllowed.$;
55
+ exports.pressedStyles = Css_1.Css.addIn(":after", Css_1.Css.br100.bgGray900.contentEmpty.w100.h100.absolute.top0.left0.add("opacity", "0.2").$).$;
@@ -15,7 +15,7 @@ function ButtonDatePicker(props) {
15
15
  const state = (0, react_stately_1.useMenuTriggerState)({ isOpen: defaultOpen });
16
16
  const buttonRef = (0, react_1.useRef)(null);
17
17
  const { menuTriggerProps, menuProps } = (0, react_aria_1.useMenuTrigger)({ isDisabled: !!disabled }, state, buttonRef);
18
- const tid = (0, utils_1.useTestIds)(props, (0, OverlayTrigger_1.isTextButton)(trigger) ? (0, defaultTestId_1.defaultTestId)(trigger.label) : trigger.icon);
18
+ const tid = (0, utils_1.useTestIds)(props, (0, OverlayTrigger_1.isTextButton)(trigger) ? (0, defaultTestId_1.defaultTestId)(trigger.label) : (0, OverlayTrigger_1.isIconButton)(trigger) ? trigger.icon : trigger.name);
19
19
  return ((0, jsx_runtime_1.jsx)(OverlayTrigger_1.OverlayTrigger, Object.assign({}, props, { menuTriggerProps: menuTriggerProps, state: state, buttonRef: buttonRef }, tid, { children: (0, jsx_runtime_1.jsx)(DatePickerOverlay_1.DatePickerOverlay, Object.assign({ overlayProps: menuProps }, { children: (0, jsx_runtime_1.jsx)(DatePicker_1.DatePicker, Object.assign({}, datePickerProps, { onSelect: (d) => {
20
20
  onSelect(d);
21
21
  state.close();
@@ -8,13 +8,12 @@ const react_stately_1 = require("react-stately");
8
8
  const Menu_1 = require("./internal/Menu");
9
9
  const OverlayTrigger_1 = require("./internal/OverlayTrigger");
10
10
  const utils_1 = require("../utils");
11
- const defaultTestId_1 = require("../utils/defaultTestId");
12
11
  function ButtonMenu(props) {
13
12
  const { defaultOpen, disabled, items, persistentItems, trigger } = props;
14
13
  const state = (0, react_stately_1.useMenuTriggerState)({ isOpen: defaultOpen });
15
14
  const buttonRef = (0, react_1.useRef)(null);
16
15
  const { menuTriggerProps, menuProps } = (0, react_aria_1.useMenuTrigger)({ isDisabled: !!disabled }, state, buttonRef);
17
- const tid = (0, utils_1.useTestIds)(props, (0, OverlayTrigger_1.isTextButton)(trigger) ? (0, defaultTestId_1.defaultTestId)(trigger.label) : trigger.icon);
16
+ const tid = (0, utils_1.useTestIds)(props, (0, OverlayTrigger_1.isTextButton)(trigger) ? trigger.label : (0, OverlayTrigger_1.isIconButton)(trigger) ? trigger.icon : trigger.name);
18
17
  return ((0, jsx_runtime_1.jsx)(OverlayTrigger_1.OverlayTrigger, Object.assign({}, props, { menuTriggerProps: menuTriggerProps, state: state, buttonRef: buttonRef }, tid, { children: (0, jsx_runtime_1.jsx)(Menu_1.Menu, Object.assign({ ariaMenuProps: menuProps, onClose: () => state.close(), items: items, persistentItems: persistentItems }, tid), void 0) }), void 0));
19
18
  }
20
19
  exports.ButtonMenu = ButtonMenu;
@@ -16,6 +16,8 @@ export interface IconButtonProps extends BeamButtonProps, BeamFocusableProps {
16
16
  compact?: boolean;
17
17
  /** Whether to display the contrast variant */
18
18
  contrast?: boolean;
19
+ /** Denotes if this button is used to download a resource. Uses the anchor tag with the `download` attribute */
20
+ download?: boolean;
19
21
  }
20
22
  export declare function IconButton(props: IconButtonProps): import("@emotion/react/jsx-runtime").JSX.Element;
21
23
  export declare const iconButtonStylesHover: {
@@ -4,13 +4,13 @@ exports.iconButtonContrastStylesHover = exports.iconButtonStylesHover = exports.
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const react_aria_1 = require("react-aria");
7
- const react_router_dom_1 = require("react-router-dom");
8
7
  const components_1 = require("./");
9
8
  const Css_1 = require("../Css");
10
9
  const utils_1 = require("../utils");
10
+ const getInteractiveElement_1 = require("../utils/getInteractiveElement");
11
11
  const useTestIds_1 = require("../utils/useTestIds");
12
12
  function IconButton(props) {
13
- const { onClick: onPress, disabled, color, icon, autoFocus, inc, buttonRef, tooltip, menuTriggerProps, openInNew, compact = false, contrast = false, } = props;
13
+ const { onClick: onPress, disabled, color, icon, autoFocus, inc, buttonRef, tooltip, menuTriggerProps, openInNew, compact = false, contrast = false, download = false, } = props;
14
14
  const isDisabled = !!disabled;
15
15
  const ariaProps = { onPress, isDisabled, autoFocus, ...menuTriggerProps };
16
16
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -31,14 +31,21 @@ function IconButton(props) {
31
31
  ...(isDisabled && iconButtonStylesDisabled),
32
32
  }), [isHovered, isFocusVisible, isDisabled, compact]);
33
33
  const iconColor = contrast ? contrastIconColor : defaultIconColor;
34
- const buttonAttrs = { ...testIds, ...buttonProps, ...focusProps, ...hoverProps, ref: ref, css: styles };
34
+ const buttonAttrs = {
35
+ ...testIds,
36
+ ...buttonProps,
37
+ ...focusProps,
38
+ ...hoverProps,
39
+ className: typeof onPress === "string" ? components_1.navLink : undefined,
40
+ ref: ref,
41
+ css: styles,
42
+ };
35
43
  const buttonContent = ((0, jsx_runtime_1.jsx)(components_1.Icon, { icon: icon, color: color || (isDisabled ? Css_1.Palette.Gray400 : iconColor), inc: compact ? 2 : inc }, void 0));
36
- const button = typeof onPress === "string" ? ((0, utils_1.isAbsoluteUrl)(onPress) || openInNew ? ((0, jsx_runtime_1.jsx)("a", Object.assign({}, buttonAttrs, { href: onPress, className: components_1.navLink, target: "_blank", rel: "noreferrer noopener" }, { children: buttonContent }), void 0)) : ((0, jsx_runtime_1.jsx)(react_router_dom_1.Link, Object.assign({}, buttonAttrs, { to: onPress, className: components_1.navLink }, { children: buttonContent }), void 0))) : ((0, jsx_runtime_1.jsx)("button", Object.assign({}, buttonAttrs, { children: buttonContent }), void 0));
37
44
  // If we're disabled b/c of a non-boolean ReactNode, or the caller specified tooltip text, then show it in a tooltip
38
45
  return (0, components_1.maybeTooltip)({
39
46
  title: (0, components_1.resolveTooltip)(disabled, tooltip),
40
47
  placement: "top",
41
- children: button,
48
+ children: (0, getInteractiveElement_1.getButtonOrLink)(buttonContent, onPress, buttonAttrs, openInNew, download),
42
49
  });
43
50
  }
44
51
  exports.IconButton = IconButton;
@@ -12,10 +12,16 @@ function Stepper({ steps, currentStep, onChange }) {
12
12
  }
13
13
  // calc progress based on last completed step - return -1 when no steps completed
14
14
  const lastCompletedStep = steps.map((step) => step.state).lastIndexOf("complete");
15
- return ((0, jsx_runtime_1.jsxs)("nav", Object.assign({ "aria-label": "steps", css: Css_1.Css.df.fdc.$ }, { children: [(0, jsx_runtime_1.jsx)("ol", Object.assign({ css: Css_1.Css.listReset.df.$ }, { children: steps.map((step) => {
15
+ const maxStepWidth = 200;
16
+ const minStepWidth = 100;
17
+ const gap = 8;
18
+ return ((0, jsx_runtime_1.jsxs)("nav", Object.assign({ "aria-label": "steps", css: Css_1.Css.df.fdc.w100.$ }, { children: [(0, jsx_runtime_1.jsx)("ol", Object.assign({ css: Css_1.Css.listReset.df.gapPx(gap).$ }, { children: steps.map((step) => {
16
19
  const isCurrent = currentStep === step.value;
17
- return ((0, jsx_runtime_1.jsx)("li", Object.assign({ css: Css_1.Css.df.fdc.wPx(200).$, "aria-current": isCurrent }, { children: (0, jsx_runtime_1.jsx)(StepButton, Object.assign({}, step, { onClick: () => onChange(step.value), isCurrent: isCurrent }), void 0) }), step.label));
18
- }) }), void 0), (0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.mt1.bgGray300.hPx(4).w(`${steps.length * 200}px`).$ }, { children: (0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.bgLightBlue600
20
+ return ((0, jsx_runtime_1.jsx)("li", Object.assign({ css: Css_1.Css.df.fg1.fdc.maxwPx(maxStepWidth).mwPx(minStepWidth).$, "aria-current": isCurrent }, { children: (0, jsx_runtime_1.jsx)(StepButton, Object.assign({}, step, { onClick: () => onChange(step.value), isCurrent: isCurrent }), void 0) }), step.label));
21
+ }) }), void 0), (0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.mt1.bgGray300
22
+ .hPx(4)
23
+ .maxwPx(steps.length * maxStepWidth + (steps.length - 1) * gap)
24
+ .mwPx(steps.length * minStepWidth + (steps.length - 1) * gap).w100.$ }, { children: (0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.bgLightBlue600
19
25
  .add("transition", "width 200ms")
20
26
  .h100.w(`${((lastCompletedStep + 1) / steps.length) * 100}%`).$ }, void 0) }), void 0)] }), void 0));
21
27
  }
@@ -124,33 +124,6 @@ function GridTable(props) {
124
124
  return rows;
125
125
  }, [columns, rows, sortOn, sortState, caseSensitive]);
126
126
  const hasTotalsRow = rows.some((row) => row.id === "totals");
127
- // Filter rows - ensures parent rows remain in the list if any children match the filter.
128
- const filterRows = (0, react_1.useCallback)((acc, row) => {
129
- var _a, _b, _c;
130
- // Break up "foo bar" into `[foo, bar]` and a row must match both `foo` and `bar`
131
- const filters = (filter && filter.split(/ +/)) || [];
132
- const matches = row.kind === "header" ||
133
- row.kind === "totals" ||
134
- filters.length === 0 ||
135
- !!row.pin ||
136
- filters.every((f) => columns.map((c) => applyRowFn(c, row, api, 0)).some((maybeContent) => matchesFilter(maybeContent, f)));
137
- // If the row matches, add it in
138
- if (matches) {
139
- return acc.concat([[row, (_b = (_a = row.children) === null || _a === void 0 ? void 0 : _a.reduce(filterRows, [])) !== null && _b !== void 0 ? _b : []]]);
140
- }
141
- else {
142
- // Otherwise, maybe one of the children match.
143
- // Always filter children rows whether or not they are collapsed in order to determine proper "selected" state of the group row.
144
- if (!!((_c = row.children) === null || _c === void 0 ? void 0 : _c.length)) {
145
- const matchedChildren = row.children.reduce(filterRows, []);
146
- // If some children did match, then add the parent row with its matched children.
147
- if (matchedChildren.length > 0) {
148
- return acc.concat([[row, matchedChildren]]);
149
- }
150
- }
151
- }
152
- return acc;
153
- }, [filter, collapsedIds, columns]);
154
127
  // Flatten + component-ize the sorted rows.
155
128
  let [headerRows, visibleDataRows, totalsRows, filteredRowIds] = (0, react_1.useMemo)(() => {
156
129
  function makeRowComponent(row, level) {
@@ -213,14 +186,16 @@ function GridTable(props) {
213
186
  }
214
187
  // Call `visitRows` with our a pre-filtered set list
215
188
  // If nestedCards is set, we assume the top-level kind is a card, and so should add spacers between them
216
- visitRows(maybeSorted.reduce(filterRows, []), !!nestedCards, 0, true);
189
+ const filteredRows = filterRows(api, columns, maybeSorted, filter);
190
+ visitRows(filteredRows, !!nestedCards, 0, true);
217
191
  nestedCards && nestedCards.done();
218
192
  return [headerRows, visibleDataRows, totalsRows, filteredRowIds];
219
193
  }, [
220
194
  as,
195
+ api,
196
+ filter,
221
197
  maybeSorted,
222
198
  columns,
223
- filterRows,
224
199
  style,
225
200
  rowStyles,
226
201
  sortOn,
@@ -819,3 +794,33 @@ function resolveStyles(style) {
819
794
  }
820
795
  return style;
821
796
  }
797
+ /**
798
+ * Filters rows given a client-side text `filter.
799
+ *
800
+ * Ensures parent rows remain in the list if any children match the filter.
801
+ *
802
+ * We return a copy of `[Parent, [Child]]` tuples so that we don't modify the `GridDataRow.children`.
803
+ */
804
+ function filterRows(api, columns, rows, filter) {
805
+ // Make a function to do recursion
806
+ function filterFn(acc, row) {
807
+ var _a, _b;
808
+ // Break up "foo bar" into `[foo, bar]` and a row must match both `foo` and `bar`
809
+ const filters = (filter && filter.split(/ +/)) || [];
810
+ const matches = row.kind === "header" ||
811
+ row.kind === "totals" ||
812
+ filters.length === 0 ||
813
+ !!row.pin ||
814
+ filters.every((f) => columns.map((c) => applyRowFn(c, row, api, 0)).some((maybeContent) => matchesFilter(maybeContent, f)));
815
+ const matchedChildren = (_b = (_a = row.children) === null || _a === void 0 ? void 0 : _a.reduce(filterFn, [])) !== null && _b !== void 0 ? _b : [];
816
+ // If row or any children match, add the parent (and its matched children)
817
+ if (matches || matchedChildren.length > 0) {
818
+ return acc.concat([[row, matchedChildren]]);
819
+ }
820
+ else {
821
+ return acc;
822
+ }
823
+ }
824
+ ;
825
+ return rows.reduce(filterFn, []);
826
+ }
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const react_aria_1 = require("react-aria");
7
7
  const react_router_1 = require("react-router");
8
8
  const react_router_dom_1 = require("react-router-dom");
9
+ const Avatar_1 = require("../Avatar");
9
10
  const Icon_1 = require("../Icon");
10
11
  const Css_1 = require("../../Css");
11
12
  const utils_1 = require("../../utils");
@@ -47,13 +48,7 @@ function MenuItemImpl(props) {
47
48
  exports.MenuItemImpl = MenuItemImpl;
48
49
  function ImageMenuItem(item) {
49
50
  const { src, size = 24, label, isAvatar = false } = item;
50
- const styles = isAvatar
51
- ? Css_1.Css.br12
52
- .wPx(size)
53
- .hPx(size)
54
- .objectCover.if(size === 48).br24.$
55
- : Css_1.Css.br4.$;
56
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.fs0.mr2.$ }, { children: (0, jsx_runtime_1.jsx)("img", { width: size, src: src, css: styles, alt: label }, void 0) }), void 0), label] }, void 0));
51
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.fs0.mr2.$ }, { children: isAvatar ? ((0, jsx_runtime_1.jsx)(Avatar_1.Avatar, { src: src, name: label, size: size === 24 ? "sm" : "lg" }, void 0)) : ((0, jsx_runtime_1.jsx)("img", { width: size, src: src, css: Css_1.Css.br4.$, alt: label }, void 0)) }), void 0), label] }, void 0));
57
52
  }
58
53
  function IconMenuItem(item) {
59
54
  const { icon, label } = item;
@@ -1,14 +1,17 @@
1
1
  import { AriaButtonProps } from "@react-types/button";
2
2
  import { MutableRefObject, ReactElement, ReactNode } from "react";
3
3
  import { MenuTriggerState } from "react-stately";
4
+ import { AvatarButtonProps } from "../AvatarButton";
4
5
  import { ButtonProps } from "../Button";
5
6
  import { IconButtonProps } from "../IconButton";
6
7
  interface TextButtonTriggerProps extends Pick<ButtonProps, "label" | "variant" | "size" | "icon"> {
7
8
  }
8
9
  interface IconButtonTriggerProps extends Pick<IconButtonProps, "icon" | "color" | "compact" | "contrast"> {
9
10
  }
11
+ interface AvatarButtonTriggerProps extends Pick<AvatarButtonProps, "src" | "name" | "size"> {
12
+ }
10
13
  export interface OverlayTriggerProps {
11
- trigger: TextButtonTriggerProps | IconButtonTriggerProps;
14
+ trigger: TextButtonTriggerProps | IconButtonTriggerProps | AvatarButtonTriggerProps;
12
15
  /** Defaults to "left" */
13
16
  placement?: "left" | "right";
14
17
  /** Whether the Button is disabled. If a ReactNode, it's treated as a "disabled reason" that's shown in a tooltip. */
@@ -25,5 +28,6 @@ export interface OverlayTriggerProps {
25
28
  state: MenuTriggerState;
26
29
  }
27
30
  export declare function OverlayTrigger(props: OverlayTriggerProps): import("@emotion/react/jsx-runtime").JSX.Element;
28
- export declare function isTextButton(trigger: TextButtonTriggerProps | IconButtonTriggerProps): trigger is TextButtonTriggerProps;
31
+ export declare function isTextButton(trigger: TextButtonTriggerProps | IconButtonTriggerProps | AvatarButtonTriggerProps): trigger is TextButtonTriggerProps;
32
+ export declare function isIconButton(trigger: TextButtonTriggerProps | IconButtonTriggerProps | AvatarButtonTriggerProps): trigger is IconButtonTriggerProps;
29
33
  export {};
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isTextButton = exports.OverlayTrigger = void 0;
3
+ exports.isIconButton = exports.isTextButton = exports.OverlayTrigger = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const react_aria_1 = require("react-aria");
7
+ const AvatarButton_1 = require("../AvatarButton");
7
8
  const Button_1 = require("../Button");
8
9
  const Icon_1 = require("../Icon");
9
10
  const IconButton_1 = require("../IconButton");
@@ -22,11 +23,15 @@ function OverlayTrigger(props) {
22
23
  onClose: state.close,
23
24
  placement: (placement ? `bottom ${placement}` : "bottom left"),
24
25
  });
25
- const tid = (0, utils_1.useTestIds)(props, isTextButton(trigger) ? (0, defaultTestId_1.defaultTestId)(trigger.label) : trigger.icon);
26
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.relative.dib.$ }, { children: [isTextButton(trigger) ? ((0, jsx_runtime_1.jsx)(Button_1.Button, Object.assign({ variant: "secondary" }, trigger, { menuTriggerProps: menuTriggerProps, buttonRef: buttonRef, endAdornment: (0, jsx_runtime_1.jsx)(Icon_1.Icon, { icon: state.isOpen ? "chevronUp" : "chevronDown" }, void 0), disabled: disabled, tooltip: tooltip, onClick: utils_1.noop }, tid), void 0)) : ((0, jsx_runtime_1.jsx)(IconButton_1.IconButton, Object.assign({}, trigger, { menuTriggerProps: menuTriggerProps, buttonRef: buttonRef }, tid, { onClick: utils_1.noop }), void 0)), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, Object.assign({ triggerRef: buttonRef, popoverRef: popoverRef, positionProps: positionProps, onClose: () => state.close(), isOpen: state.isOpen }, { children: children }), void 0))] }), void 0));
26
+ const tid = (0, utils_1.useTestIds)(props, isTextButton(trigger) ? (0, defaultTestId_1.defaultTestId)(trigger.label) : isIconButton(trigger) ? trigger.icon : trigger.name);
27
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.relative.dib.$ }, { children: [isTextButton(trigger) ? ((0, jsx_runtime_1.jsx)(Button_1.Button, Object.assign({ variant: "secondary" }, trigger, { menuTriggerProps: menuTriggerProps, buttonRef: buttonRef, endAdornment: (0, jsx_runtime_1.jsx)(Icon_1.Icon, { icon: state.isOpen ? "chevronUp" : "chevronDown" }, void 0), disabled: disabled, tooltip: tooltip, onClick: utils_1.noop }, tid), void 0)) : isIconButton(trigger) ? ((0, jsx_runtime_1.jsx)(IconButton_1.IconButton, Object.assign({}, trigger, { menuTriggerProps: menuTriggerProps, buttonRef: buttonRef }, tid, { disabled: disabled, tooltip: tooltip, onClick: utils_1.noop }), void 0)) : ((0, jsx_runtime_1.jsx)(AvatarButton_1.AvatarButton, Object.assign({}, trigger, { menuTriggerProps: menuTriggerProps, buttonRef: buttonRef }, tid, { disabled: disabled, tooltip: tooltip, onClick: utils_1.noop }), void 0)), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, Object.assign({ triggerRef: buttonRef, popoverRef: popoverRef, positionProps: positionProps, onClose: () => state.close(), isOpen: state.isOpen }, { children: children }), void 0))] }), void 0));
27
28
  }
28
29
  exports.OverlayTrigger = OverlayTrigger;
29
30
  function isTextButton(trigger) {
30
31
  return trigger && typeof trigger === "object" && "label" in trigger;
31
32
  }
32
33
  exports.isTextButton = isTextButton;
34
+ function isIconButton(trigger) {
35
+ return trigger && typeof trigger === "object" && "icon" in trigger;
36
+ }
37
+ exports.isIconButton = isIconButton;
@@ -1,8 +1,8 @@
1
1
  import { FieldState } from "@homebound/form-state";
2
2
  import { SelectFieldProps, Value } from "../inputs";
3
3
  import { HasIdAndName, Optional } from "../types";
4
- export declare type BoundSelectFieldProps<T, V extends Value> = Omit<SelectFieldProps<T, V>, "value" | "onSelect" | "label"> & {
5
- onSelect?: (option: V | undefined) => void;
4
+ export declare type BoundSelectFieldProps<O, V extends Value> = Omit<SelectFieldProps<O, V>, "value" | "onSelect" | "label"> & {
5
+ onSelect?: (value: V | undefined, opt: O | undefined) => void;
6
6
  field: FieldState<any, V | null | undefined>;
7
7
  label?: string;
8
8
  };
@@ -14,8 +14,8 @@ function BoundSelectField(props) {
14
14
  const testId = (0, useTestIds_1.useTestIds)(props, field.key);
15
15
  return ((0, jsx_runtime_1.jsx)(mobx_react_1.Observer, { children: () => {
16
16
  var _a;
17
- return ((0, jsx_runtime_1.jsx)(inputs_1.SelectField, Object.assign({ label: label, value: (_a = field.value) !== null && _a !== void 0 ? _a : undefined, onSelect: (value) => {
18
- onSelect(value);
17
+ return ((0, jsx_runtime_1.jsx)(inputs_1.SelectField, Object.assign({ label: label, value: (_a = field.value) !== null && _a !== void 0 ? _a : undefined, onSelect: (value, opt) => {
18
+ onSelect(value, opt);
19
19
  field.maybeAutoSave();
20
20
  }, options: options, readOnly: readOnly !== null && readOnly !== void 0 ? readOnly : field.readOnly, errorMsg: field.touched ? field.errors.join(" ") : undefined, required: field.required, getOptionLabel: getOptionLabel, getOptionValue: getOptionValue, onBlur: () => {
21
21
  field.blur();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.143.1",
3
+ "version": "2.145.1",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",