@homebound/beam 3.31.2 → 3.33.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/index.d.cts CHANGED
@@ -6205,11 +6205,20 @@ type ImpersonatedUser = {
6205
6205
  type EnvironmentBannerProps = {
6206
6206
  env: AppEnvironment;
6207
6207
  impersonating?: ImpersonatedUser;
6208
+ /**
6209
+ * Shows the production warning banner; typically set to `true` only for developers in the consuming app.
6210
+ * Its styling takes precedence over impersonation (red fill + prod warning copy, with impersonation still
6211
+ * shown on the right).
6212
+ */
6213
+ showProdWarning?: boolean;
6208
6214
  };
6209
6215
  /** Environment banner; horizontal/vertical pinning is owned by {@link EnvironmentBannerLayout}. */
6210
6216
  declare function EnvironmentBanner(props: EnvironmentBannerProps): JSX.Element | null;
6211
- /** True when {@link EnvironmentBanner} should display: `dev`, `qa`, `local-prod`, or `prod` while impersonating. */
6212
- declare function shouldShowEnvironmentBanner(env: AppEnvironment, impersonating: ImpersonatedUser | undefined): boolean;
6217
+ /**
6218
+ * True when {@link EnvironmentBanner} should display: `dev`, `qa`, `local-prod`, or `prod` while impersonating
6219
+ * or when `showProdWarning` is set (typically only for developers in the consuming app).
6220
+ */
6221
+ declare function shouldShowEnvironmentBanner(env: AppEnvironment, impersonating: ImpersonatedUser | undefined, showProdWarning: boolean): boolean;
6213
6222
  /** Fixed banner height (px); {@link EnvironmentBannerLayout} reads this for spacer/CSS var offsets. */
6214
6223
  declare const environmentBannerSizePx = 34;
6215
6224
 
@@ -7212,7 +7221,14 @@ type TreeSelectFieldProps<O, V extends Value> = {
7212
7221
  /** Which selected options to display as chips in the input field when not focused.
7213
7222
  * @default root */
7214
7223
  chipDisplay?: "all" | "leaf" | "root";
7215
- disabledOptions?: V[];
7224
+ /**
7225
+ * Options to disable. Can be a list of `V` values, or `{ value, reason }` tuples where the
7226
+ * `reason` is shown as a tooltip when the user hovers the disabled option.
7227
+ */
7228
+ disabledOptions?: (V | {
7229
+ value: V;
7230
+ reason: string;
7231
+ })[];
7216
7232
  groupOptions?: V[];
7217
7233
  } & BeamFocusableProps & PresentationFieldProps;
7218
7234
  declare function TreeSelectField<O, V extends Value>(props: TreeSelectFieldProps<O, V>): JSX.Element;
package/dist/index.d.ts CHANGED
@@ -6205,11 +6205,20 @@ type ImpersonatedUser = {
6205
6205
  type EnvironmentBannerProps = {
6206
6206
  env: AppEnvironment;
6207
6207
  impersonating?: ImpersonatedUser;
6208
+ /**
6209
+ * Shows the production warning banner; typically set to `true` only for developers in the consuming app.
6210
+ * Its styling takes precedence over impersonation (red fill + prod warning copy, with impersonation still
6211
+ * shown on the right).
6212
+ */
6213
+ showProdWarning?: boolean;
6208
6214
  };
6209
6215
  /** Environment banner; horizontal/vertical pinning is owned by {@link EnvironmentBannerLayout}. */
6210
6216
  declare function EnvironmentBanner(props: EnvironmentBannerProps): JSX.Element | null;
6211
- /** True when {@link EnvironmentBanner} should display: `dev`, `qa`, `local-prod`, or `prod` while impersonating. */
6212
- declare function shouldShowEnvironmentBanner(env: AppEnvironment, impersonating: ImpersonatedUser | undefined): boolean;
6217
+ /**
6218
+ * True when {@link EnvironmentBanner} should display: `dev`, `qa`, `local-prod`, or `prod` while impersonating
6219
+ * or when `showProdWarning` is set (typically only for developers in the consuming app).
6220
+ */
6221
+ declare function shouldShowEnvironmentBanner(env: AppEnvironment, impersonating: ImpersonatedUser | undefined, showProdWarning: boolean): boolean;
6213
6222
  /** Fixed banner height (px); {@link EnvironmentBannerLayout} reads this for spacer/CSS var offsets. */
6214
6223
  declare const environmentBannerSizePx = 34;
6215
6224
 
@@ -7212,7 +7221,14 @@ type TreeSelectFieldProps<O, V extends Value> = {
7212
7221
  /** Which selected options to display as chips in the input field when not focused.
7213
7222
  * @default root */
7214
7223
  chipDisplay?: "all" | "leaf" | "root";
7215
- disabledOptions?: V[];
7224
+ /**
7225
+ * Options to disable. Can be a list of `V` values, or `{ value, reason }` tuples where the
7226
+ * `reason` is shown as a tooltip when the user hovers the disabled option.
7227
+ */
7228
+ disabledOptions?: (V | {
7229
+ value: V;
7230
+ reason: string;
7231
+ })[];
7216
7232
  groupOptions?: V[];
7217
7233
  } & BeamFocusableProps & PresentationFieldProps;
7218
7234
  declare function TreeSelectField<O, V extends Value>(props: TreeSelectFieldProps<O, V>): JSX.Element;
package/dist/index.js CHANGED
@@ -11642,7 +11642,8 @@ function TreeOption(props) {
11642
11642
  const {
11643
11643
  item,
11644
11644
  state,
11645
- allowCollapsing = true
11645
+ allowCollapsing = true,
11646
+ disabledReason
11646
11647
  } = props;
11647
11648
  const leveledOption = item.value;
11648
11649
  if (!leveledOption) return null;
@@ -11699,43 +11700,47 @@ function TreeOption(props) {
11699
11700
  }]
11700
11701
  }
11701
11702
  };
11702
- return /* @__PURE__ */ jsxs33("li", { ...hoverProps, onClick: (e) => {
11703
- if (!isGroup) return;
11704
- e.preventDefault();
11705
- e.stopPropagation();
11706
- toggleCollapsed();
11707
- }, ...trussProps34({
11708
- ...{
11709
- display: "df",
11710
- alignItems: "aic",
11711
- justifyContent: "jcsb",
11712
- gap: "gap1",
11713
- paddingLeft: ["pl_var", {
11714
- "--paddingLeft": `${16 + level * 8}px`
11715
- }],
11716
- minHeight: "mh_42px",
11717
- outline: "outline0",
11718
- cursor: "cursorPointer",
11719
- fontWeight: "fw4",
11720
- fontSize: "fz_14px",
11721
- lineHeight: "lh_20px"
11722
- },
11723
- ...listItemStyles.item,
11724
- ...isHovered && (!isDisabled || isGroup) ? listItemStyles.hover : {},
11725
- ...isFocused && !isGroup ? listItemStyles.focus : {},
11726
- ...isDisabled && !isGroup ? listItemStyles.disabled : {}
11727
- }), children: [
11728
- allowCollapsing && /* @__PURE__ */ jsx52("span", { className: "w_18px fs0 df aic", children: canCollapse && /* @__PURE__ */ jsx52("button", { onClick: (e) => {
11703
+ return maybeTooltip({
11704
+ title: !isGroup ? disabledReason : void 0,
11705
+ placement: "right",
11706
+ children: /* @__PURE__ */ jsxs33("li", { ...hoverProps, onClick: (e) => {
11707
+ if (!isGroup) return;
11729
11708
  e.preventDefault();
11730
11709
  e.stopPropagation();
11731
11710
  toggleCollapsed();
11732
- return false;
11733
- }, className: "br4 h_16px w_16px bgTransparent h_bgGray300", ...tid[`collapseToggle_${item.key}`], children: /* @__PURE__ */ jsx52(Icon, { icon: collapsedKeys.includes(item.key) ? "triangleRight" : "triangleDown", inc: 2 }) }) }),
11734
- /* @__PURE__ */ jsxs33("span", { className: "df aic gap1 h100 fg1 pt1 pb1 pr2", ref, ...optionProps, "data-label": item.textValue, children: [
11735
- !isGroup && /* @__PURE__ */ jsx52(StyledCheckbox, { isDisabled, isSelected, isIndeterminate, ...tid[item.key.toString()] }),
11736
- /* @__PURE__ */ jsx52("div", { className: "pl1", children: item.rendered })
11711
+ }, ...trussProps34({
11712
+ ...{
11713
+ display: "df",
11714
+ alignItems: "aic",
11715
+ justifyContent: "jcsb",
11716
+ gap: "gap1",
11717
+ paddingLeft: ["pl_var", {
11718
+ "--paddingLeft": `${16 + level * 8}px`
11719
+ }],
11720
+ minHeight: "mh_42px",
11721
+ outline: "outline0",
11722
+ cursor: "cursorPointer",
11723
+ fontWeight: "fw4",
11724
+ fontSize: "fz_14px",
11725
+ lineHeight: "lh_20px"
11726
+ },
11727
+ ...listItemStyles.item,
11728
+ ...isHovered && (!isDisabled || isGroup) ? listItemStyles.hover : {},
11729
+ ...isFocused && !isGroup ? listItemStyles.focus : {},
11730
+ ...isDisabled && !isGroup ? listItemStyles.disabled : {}
11731
+ }), children: [
11732
+ allowCollapsing && /* @__PURE__ */ jsx52("span", { className: "w_18px fs0 df aic", children: canCollapse && /* @__PURE__ */ jsx52("button", { onClick: (e) => {
11733
+ e.preventDefault();
11734
+ e.stopPropagation();
11735
+ toggleCollapsed();
11736
+ return false;
11737
+ }, className: "br4 h_16px w_16px bgTransparent h_bgGray300", ...tid[`collapseToggle_${item.key}`], children: /* @__PURE__ */ jsx52(Icon, { icon: collapsedKeys.includes(item.key) ? "triangleRight" : "triangleDown", inc: 2 }) }) }),
11738
+ /* @__PURE__ */ jsxs33("span", { className: "df aic gap1 h100 fg1 pt1 pb1 pr2", ref, ...optionProps, "data-label": item.textValue, children: [
11739
+ !isGroup && /* @__PURE__ */ jsx52(StyledCheckbox, { isDisabled, isSelected, isIndeterminate, ...tid[item.key.toString()] }),
11740
+ /* @__PURE__ */ jsx52("div", { className: "pl1", children: item.rendered })
11741
+ ] })
11737
11742
  ] })
11738
- ] });
11743
+ });
11739
11744
  }
11740
11745
  function hasSelectedChildren(childOption, state, getOptionValue) {
11741
11746
  if (childOption.children && childOption.children.length > 0) {
@@ -11833,7 +11838,8 @@ function VirtualizedOptions(props) {
11833
11838
  {
11834
11839
  item,
11835
11840
  state,
11836
- allowCollapsing
11841
+ allowCollapsing,
11842
+ disabledReason: disabledOptionsWithReasons[item.key]
11837
11843
  },
11838
11844
  item.key
11839
11845
  );
@@ -12414,7 +12420,7 @@ function TreeSelectFieldBase(props) {
12414
12420
  onClose: () => state.toggle(),
12415
12421
  isOpen: state.isOpen,
12416
12422
  minWidth: 320,
12417
- children: /* @__PURE__ */ jsx57(ListBox, { ...listBoxProps, positionProps, state, listBoxRef, selectedOptions: fieldState.selectedChipOptions, getOptionLabel, getOptionValue: (o) => valueToKey(getOptionValue(o)), horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, allowCollapsing: fieldState.allowCollapsing, isTree: true })
12423
+ children: /* @__PURE__ */ jsx57(ListBox, { ...listBoxProps, positionProps, state, listBoxRef, selectedOptions: fieldState.selectedChipOptions, getOptionLabel, getOptionValue: (o) => valueToKey(getOptionValue(o)), horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, allowCollapsing: fieldState.allowCollapsing, disabledOptionsWithReasons, isTree: true })
12418
12424
  }
12419
12425
  )
12420
12426
  ] });
@@ -21845,10 +21851,11 @@ function EnvironmentBanner(props) {
21845
21851
  const {
21846
21852
  env,
21847
21853
  impersonating,
21854
+ showProdWarning = false,
21848
21855
  ...others
21849
21856
  } = props;
21850
21857
  const tid = useTestIds(others, "environmentBanner");
21851
- if (!shouldShowEnvironmentBanner(env, impersonating)) {
21858
+ if (!shouldShowEnvironmentBanner(env, impersonating, showProdWarning)) {
21852
21859
  return null;
21853
21860
  }
21854
21861
  const {
@@ -21856,7 +21863,7 @@ function EnvironmentBanner(props) {
21856
21863
  badgeLabel,
21857
21864
  message,
21858
21865
  tooltip
21859
- } = getEnvironmentBannerConfig(env, impersonating);
21866
+ } = getEnvironmentBannerConfig(env, impersonating, showProdWarning);
21860
21867
  const bgColorVar = maybeCssVar(bgColor);
21861
21868
  return /* @__PURE__ */ jsxs84("div", { ...trussProps83({
21862
21869
  flexShrink: "fs0",
@@ -21899,7 +21906,7 @@ function EnvironmentBanner(props) {
21899
21906
  ] })
21900
21907
  ] }),
21901
21908
  impersonating != null && /* @__PURE__ */ jsxs84("span", { className: "df aic gap2 fw6 fz_12px lh_16px white fs0", ...tid.impersonating, children: [
21902
- env !== "prod" && /* @__PURE__ */ jsxs84("span", { children: [
21909
+ (env !== "prod" || showProdWarning) && /* @__PURE__ */ jsxs84("span", { children: [
21903
21910
  /* @__PURE__ */ jsx166("span", { className: "dn mdandup_dib", children: "Impersonating \xA0" }),
21904
21911
  impersonating.name
21905
21912
  ] }),
@@ -21908,10 +21915,10 @@ function EnvironmentBanner(props) {
21908
21915
  ] })
21909
21916
  ] });
21910
21917
  }
21911
- function shouldShowEnvironmentBanner(env, impersonating) {
21912
- return env === "dev" || env === "qa" || env === "local-prod" || env === "prod" && isDefined(impersonating);
21918
+ function shouldShowEnvironmentBanner(env, impersonating, showProdWarning) {
21919
+ return env === "dev" || env === "qa" || env === "local-prod" || env === "prod" && (isDefined(impersonating) || showProdWarning);
21913
21920
  }
21914
- function getEnvironmentBannerConfig(env, impersonating) {
21921
+ function getEnvironmentBannerConfig(env, impersonating, showProdWarning) {
21915
21922
  switch (env) {
21916
21923
  case "dev":
21917
21924
  return {
@@ -21927,9 +21934,16 @@ function getEnvironmentBannerConfig(env, impersonating) {
21927
21934
  message: "You are in the QA Environment",
21928
21935
  tooltip: "You are in the QA Environment. Any changes here will not be reflected in live production data."
21929
21936
  };
21930
- // Prod env banner should only be displayed when impersonating
21937
+ // Prod banner shows when impersonating or when `showProdWarning` is set. The prod warning takes precedence:
21938
+ // it reuses the red local-prod fill for "live prod data" urgency, while impersonation (if any) still shows
21939
+ // on the right. Impersonation alone keeps its own prod fill and copy.
21931
21940
  case "prod":
21932
- return {
21941
+ return showProdWarning ? {
21942
+ bgColor: "--b-env-brand-local-prod" /* EnvBrandLocalProd */,
21943
+ badgeLabel: "PROD",
21944
+ message: "You are in the Production Environment",
21945
+ tooltip: "You are in the Production Environment. Any changes here WILL be reflected in live production data."
21946
+ } : {
21933
21947
  bgColor: "--b-env-brand-prod" /* EnvBrandProd */,
21934
21948
  badgeLabel: "PROD",
21935
21949
  message: `You are impersonating ${impersonating?.name}`,
@@ -24160,7 +24174,7 @@ function EnvironmentBannerLayout(props) {
24160
24174
  children
24161
24175
  } = props;
24162
24176
  const tid = useTestIds(props, "environmentBannerLayout");
24163
- const showBanner = environmentBanner != null && shouldShowEnvironmentBanner(environmentBanner.env, environmentBanner.impersonating);
24177
+ const showBanner = environmentBanner != null && shouldShowEnvironmentBanner(environmentBanner.env, environmentBanner.impersonating, environmentBanner.showProdWarning ?? false);
24164
24178
  const bannerHeightPx = showBanner ? environmentBannerSizePx : 0;
24165
24179
  const style = {
24166
24180
  [beamEnvironmentBannerLayoutHeightVar]: `${bannerHeightPx}px`