@homebound/beam 3.62.0 → 3.63.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.
package/dist/index.cjs CHANGED
@@ -11258,6 +11258,10 @@ function MenuItemImpl(props) {
11258
11258
  isHovered
11259
11259
  } = (0, import_react_aria17.useHover)({});
11260
11260
  const tid = useTestIds(props);
11261
+ const openInNewTabRef = (0, import_react41.useRef)(false);
11262
+ function captureModifiers(e) {
11263
+ openInNewTabRef.current = wantsNewTab(e);
11264
+ }
11261
11265
  const {
11262
11266
  menuItemProps
11263
11267
  } = (0, import_react_aria17.useMenuItem)({
@@ -11271,7 +11275,7 @@ function MenuItemImpl(props) {
11271
11275
  onClick
11272
11276
  } = menuItem;
11273
11277
  if (typeof onClick === "string") {
11274
- if (isAbsoluteUrl(onClick)) {
11278
+ if (isAbsoluteUrl(onClick) || openInNewTabRef.current) {
11275
11279
  window.open(onClick, "_blank").opener = null;
11276
11280
  return;
11277
11281
  }
@@ -11293,55 +11297,68 @@ function MenuItemImpl(props) {
11293
11297
  const isDisabled = Boolean(disabled);
11294
11298
  const isSelected = state.selectionManager.selectedKeys.has(label);
11295
11299
  const isFocused = state.selectionManager.focusedKey === item.key;
11296
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { ...menuItemProps, ...hoverProps, ref, ...(0, import_runtime30.trussProps)({
11297
- ...{
11298
- display: "df",
11299
- alignItems: "aic",
11300
- paddingTop: "pt1",
11301
- paddingBottom: "pb1",
11302
- paddingLeft: "pl2",
11303
- paddingRight: "pr2",
11304
- cursor: "cursorPointer",
11305
- outline: "outline0",
11306
- minHeight: "mh_42px",
11307
- fontWeight: "fw4",
11308
- fontSize: "fz_14px",
11309
- lineHeight: "lh_20px"
11310
- },
11311
- ...menuItem.hasDivider ? {
11312
- borderBottomStyle: "bbs_solid",
11313
- borderBottomWidth: "bbw_1px",
11314
- borderColor: "bcGray700"
11315
- } : {},
11316
- ...!isDisabled && isHovered ? {
11317
- backgroundColor: ["bgColor_var", {
11318
- "--backgroundColor": "var(--b-menu-item-bg-hover)"
11319
- }]
11320
- } : {},
11321
- ...isFocused ? {
11322
- boxShadow: ["boxShadow_var", {
11323
- "--boxShadow": (0, import_runtime30.maybeCssVar)(`inset 0 0 0 1px var(${"--b-focus-ring-inset" /* FocusRingInset */})`)
11324
- }]
11325
- } : {},
11326
- ...isDisabled ? {
11327
- color: ["color_var", {
11328
- "--color": "var(--b-text-disabled)"
11329
- }],
11330
- cursor: "cursorNotAllowed"
11331
- } : {},
11332
- ...destructive ? {
11333
- color: ["color_var", {
11334
- "--color": "var(--b-danger)"
11335
- }]
11336
- } : {},
11337
- ...isSelected ? {
11338
- fontWeight: "fw5"
11339
- } : {}
11340
- }), ...tid[defaultTestId(menuItem.label)], children: maybeTooltip({
11341
- title: resolveTooltip(disabled),
11342
- placement: "right",
11343
- children: renderMenuItem(menuItem, isSelected, isDisabled)
11344
- }) });
11300
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
11301
+ "li",
11302
+ {
11303
+ ...menuItemProps,
11304
+ ...hoverProps,
11305
+ onPointerDownCapture: captureModifiers,
11306
+ onKeyDownCapture: captureModifiers,
11307
+ onClickCapture: captureModifiers,
11308
+ ref,
11309
+ ...(0, import_runtime30.trussProps)({
11310
+ ...{
11311
+ display: "df",
11312
+ alignItems: "aic",
11313
+ paddingTop: "pt1",
11314
+ paddingBottom: "pb1",
11315
+ paddingLeft: "pl2",
11316
+ paddingRight: "pr2",
11317
+ cursor: "cursorPointer",
11318
+ outline: "outline0",
11319
+ minHeight: "mh_42px",
11320
+ fontWeight: "fw4",
11321
+ fontSize: "fz_14px",
11322
+ lineHeight: "lh_20px"
11323
+ },
11324
+ ...menuItem.hasDivider ? {
11325
+ borderBottomStyle: "bbs_solid",
11326
+ borderBottomWidth: "bbw_1px",
11327
+ borderColor: "bcGray700"
11328
+ } : {},
11329
+ ...!isDisabled && isHovered ? {
11330
+ backgroundColor: ["bgColor_var", {
11331
+ "--backgroundColor": "var(--b-menu-item-bg-hover)"
11332
+ }]
11333
+ } : {},
11334
+ ...isFocused ? {
11335
+ boxShadow: ["boxShadow_var", {
11336
+ "--boxShadow": (0, import_runtime30.maybeCssVar)(`inset 0 0 0 1px var(${"--b-focus-ring-inset" /* FocusRingInset */})`)
11337
+ }]
11338
+ } : {},
11339
+ ...isDisabled ? {
11340
+ color: ["color_var", {
11341
+ "--color": "var(--b-text-disabled)"
11342
+ }],
11343
+ cursor: "cursorNotAllowed"
11344
+ } : {},
11345
+ ...destructive ? {
11346
+ color: ["color_var", {
11347
+ "--color": "var(--b-danger)"
11348
+ }]
11349
+ } : {},
11350
+ ...isSelected ? {
11351
+ fontWeight: "fw5"
11352
+ } : {}
11353
+ }),
11354
+ ...tid[defaultTestId(menuItem.label)],
11355
+ children: maybeTooltip({
11356
+ title: resolveTooltip(disabled),
11357
+ placement: "right",
11358
+ children: renderMenuItem(menuItem, isSelected, isDisabled)
11359
+ })
11360
+ }
11361
+ );
11345
11362
  }
11346
11363
  function renderMenuItem(menuItem, isSelected, isDisabled) {
11347
11364
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "df w100 aic jcsb gap2", children: [
@@ -11385,6 +11402,9 @@ function maybeWrapInLink(onClick, content, disabled) {
11385
11402
  /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "fs0 ml2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Icon, { icon: "linkExternal" }) })
11386
11403
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react_router_dom3.Link, { className: "navLink", to: onClick, children: content });
11387
11404
  }
11405
+ function wantsNewTab(e) {
11406
+ return e.metaKey || e.ctrlKey || e.shiftKey;
11407
+ }
11388
11408
  function isIconMenuItem(item) {
11389
11409
  return item && typeof item === "object" && "icon" in item;
11390
11410
  }
@@ -12236,7 +12256,6 @@ function TreeOption(props) {
12236
12256
  const {
12237
12257
  item,
12238
12258
  state,
12239
- allowCollapsing = true,
12240
12259
  disabledReason
12241
12260
  } = props;
12242
12261
  const leveledOption = item.value;
@@ -12265,7 +12284,7 @@ function TreeOption(props) {
12265
12284
  shouldFocusOnHover: false
12266
12285
  }, state, ref);
12267
12286
  const isGroup = groupKeys.includes(item.key);
12268
- const canCollapse = allowCollapsing && !!option.children?.length;
12287
+ const canCollapse = !!option.children?.length;
12269
12288
  function toggleCollapsed() {
12270
12289
  if (!canCollapse) return;
12271
12290
  setCollapsedKeys((prevKeys) => collapsedKeys.includes(item.key) ? prevKeys.filter((k) => k !== item.key) : [...prevKeys, item.key]);
@@ -12323,7 +12342,7 @@ function TreeOption(props) {
12323
12342
  ...isFocused && !isGroup ? listItemStyles.focus : {},
12324
12343
  ...isDisabled && !isGroup ? listItemStyles.disabled : {}
12325
12344
  }), children: [
12326
- allowCollapsing && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "w_18px fs0 df aic", children: canCollapse && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { onClick: (e) => {
12345
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "w_18px fs0 df aic", children: canCollapse && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { onClick: (e) => {
12327
12346
  e.preventDefault();
12328
12347
  e.stopPropagation();
12329
12348
  toggleCollapsed();
@@ -12382,16 +12401,7 @@ function isLeveledNode(node) {
12382
12401
  // src/inputs/internal/VirtualizedOptions.tsx
12383
12402
  var import_jsx_runtime53 = require("react/jsx-runtime");
12384
12403
  function VirtualizedOptions(props) {
12385
- const {
12386
- state,
12387
- items,
12388
- onListHeightChange,
12389
- scrollOnFocus,
12390
- loading,
12391
- disabledOptionsWithReasons,
12392
- isTree,
12393
- allowCollapsing
12394
- } = props;
12404
+ const { state, items, onListHeightChange, scrollOnFocus, loading, disabledOptionsWithReasons, isTree } = props;
12395
12405
  const virtuosoRef = (0, import_react49.useRef)(null);
12396
12406
  const focusedKey = state.selectionManager.focusedKey;
12397
12407
  const focusedItem = focusedKey != null ? state.collection.getItem(focusedKey) : null;
@@ -12432,7 +12442,6 @@ function VirtualizedOptions(props) {
12432
12442
  {
12433
12443
  item,
12434
12444
  state,
12435
- allowCollapsing,
12436
12445
  disabledReason: disabledOptionsWithReasons[item.key]
12437
12446
  },
12438
12447
  item.key
@@ -12531,8 +12540,7 @@ function ListBox(props) {
12531
12540
  horizontalLayout = false,
12532
12541
  loading,
12533
12542
  disabledOptionsWithReasons = {},
12534
- isTree,
12535
- allowCollapsing
12543
+ isTree
12536
12544
  } = props;
12537
12545
  const {
12538
12546
  listBoxProps
@@ -12610,8 +12618,7 @@ function ListBox(props) {
12610
12618
  scrollOnFocus: props.shouldUseVirtualFocus,
12611
12619
  loading,
12612
12620
  disabledOptionsWithReasons,
12613
- isTree,
12614
- allowCollapsing
12621
+ isTree
12615
12622
  }
12616
12623
  ) })
12617
12624
  ] });
@@ -12704,7 +12711,8 @@ function TreeSelectFieldBase(props) {
12704
12711
  sensitivity: "base"
12705
12712
  });
12706
12713
  const {
12707
- collapsedKeys
12714
+ collapsedKeys,
12715
+ setCollapsedKeys
12708
12716
  } = useTreeSelectFieldProvider();
12709
12717
  const groupKeys = (0, import_react51.useMemo)(() => _groupOptions?.map((option) => valueToKey(option)) ?? [], [_groupOptions]);
12710
12718
  const groupKeySet = (0, import_react51.useMemo)(() => new Set(groupKeys), [groupKeys]);
@@ -12746,8 +12754,7 @@ function TreeSelectFieldBase(props) {
12746
12754
  selectedChipOptions: selectedChipState.options,
12747
12755
  allOptions: initialOptions,
12748
12756
  selectedOptionsLabels: selectedChipState.labels,
12749
- optionsLoading: false,
12750
- allowCollapsing: true
12757
+ optionsLoading: false
12751
12758
  };
12752
12759
  }, [initialOptions, values, chipDisplay, getOptionLabel, isReadOnly, nothingSelectedText, getOptionValue, groupKeySet]);
12753
12760
  const [fieldState, setFieldState] = (0, import_react51.useState)(() => initTreeFieldState());
@@ -12769,14 +12776,26 @@ function TreeSelectFieldBase(props) {
12769
12776
  setFieldState(initTreeFieldState());
12770
12777
  }
12771
12778
  }, [getOptionValue, initTreeFieldState, values]);
12779
+ const preSearchCollapsedKeys = (0, import_react51.useRef)(void 0);
12780
+ (0, import_react51.useEffect)(() => {
12781
+ if (fieldState.searchValue) {
12782
+ if (preSearchCollapsedKeys.current === void 0) {
12783
+ preSearchCollapsedKeys.current = collapsedKeys;
12784
+ if (collapsedKeys.length > 0) setCollapsedKeys([]);
12785
+ }
12786
+ } else if (preSearchCollapsedKeys.current !== void 0) {
12787
+ const keys = preSearchCollapsedKeys.current;
12788
+ preSearchCollapsedKeys.current = void 0;
12789
+ setCollapsedKeys(keys);
12790
+ }
12791
+ }, [fieldState.searchValue, collapsedKeys, setCollapsedKeys]);
12772
12792
  const filteredOptions = (0, import_react51.useMemo)(() => getFilteredOptions(fieldState.allOptions, fieldState.searchValue, collapsedKeys, contains, getOptionLabel, getOptionValue), [fieldState.allOptions, fieldState.searchValue, collapsedKeys, contains, getOptionLabel, getOptionValue]);
12773
12793
  const onInputChange = (0, import_react51.useCallback)((inputValue) => {
12774
12794
  setFieldState((prevState) => {
12775
12795
  return {
12776
12796
  ...prevState,
12777
12797
  inputValue,
12778
- searchValue: inputValue.length === 0 ? void 0 : inputValue,
12779
- allowCollapsing: inputValue.length === 0
12798
+ searchValue: inputValue.length === 0 ? void 0 : inputValue
12780
12799
  };
12781
12800
  });
12782
12801
  }, []);
@@ -12804,8 +12823,7 @@ function TreeSelectFieldBase(props) {
12804
12823
  setFieldState((prevState) => ({
12805
12824
  ...prevState,
12806
12825
  inputValue: "",
12807
- searchValue: void 0,
12808
- allowCollapsing: true
12826
+ searchValue: void 0
12809
12827
  }));
12810
12828
  }
12811
12829
  }
@@ -12840,9 +12858,8 @@ function TreeSelectFieldBase(props) {
12840
12858
  if (newKeys.size === 0) {
12841
12859
  setFieldState((prevState) => ({
12842
12860
  ...prevState,
12843
- inputValue: nothingSelectedText,
12844
- searchValue: void 0,
12845
- allowCollapsing: true,
12861
+ // Unselecting the last option shouldn't drop the search either
12862
+ inputValue: prevState.searchValue ?? nothingSelectedText,
12846
12863
  selectedKeys: [],
12847
12864
  selectedOptions: [],
12848
12865
  selectedChipOptions: [],
@@ -12916,9 +12933,9 @@ function TreeSelectFieldBase(props) {
12916
12933
  const selectedChipState = getSelectedChipState(fieldState.allOptions, selectedOptions, selectedKeys, chipDisplay, getOptionLabel, getOptionValue);
12917
12934
  setFieldState((prevState) => ({
12918
12935
  ...prevState,
12919
- // Since we reset the list of options upon selection changes, then set the `inputValue` to empty string to reflect that.
12920
- inputValue: "",
12921
- searchValue: void 0,
12936
+ // Keep any search in place, so picking several options out of the same filtered list doesn't
12937
+ // make the user retype it; when they're not searching the input stays empty as before.
12938
+ inputValue: prevState.searchValue ?? "",
12922
12939
  selectedKeys: [...selectedKeys],
12923
12940
  selectedOptions,
12924
12941
  selectedChipOptions: selectedChipState.options,
@@ -12950,8 +12967,7 @@ function TreeSelectFieldBase(props) {
12950
12967
  setFieldState((prevState) => ({
12951
12968
  ...prevState,
12952
12969
  inputValue: selectedOptions.length === 1 ? getOptionLabel(selectedOptions[0]) : selectedOptions.length === 0 ? nothingSelectedText : "",
12953
- searchValue: void 0,
12954
- allowCollapsing: true
12970
+ searchValue: void 0
12955
12971
  }));
12956
12972
  }
12957
12973
  }
@@ -13021,17 +13037,16 @@ function TreeSelectFieldBase(props) {
13021
13037
  onClose: () => state.toggle(),
13022
13038
  isOpen: state.isOpen,
13023
13039
  minWidth: 320,
13024
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(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 })
13040
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ListBox, { ...listBoxProps, positionProps, state, listBoxRef, selectedOptions: fieldState.selectedChipOptions, getOptionLabel, getOptionValue: (o) => valueToKey(getOptionValue(o)), horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, disabledOptionsWithReasons, isTree: true })
13025
13041
  }
13026
13042
  )
13027
13043
  ] });
13028
13044
  }
13029
- function levelOptions(o, level, filtering, collapsedKeys, getOptionValue) {
13030
- const actualLevel = filtering ? 0 : level;
13045
+ function levelOptions(o, level, collapsedKeys, getOptionValue) {
13031
13046
  return [
13032
- [o, actualLevel],
13033
- // Flat map the children if the parent is not collapsed or if we are filtering (for the search results)
13034
- ...o.children?.length && (!collapsedKeys.includes(valueToKey(getOptionValue(o))) || filtering) ? o.children.flatMap((oc) => levelOptions(oc, actualLevel + 1, filtering, collapsedKeys, getOptionValue)) : []
13047
+ [o, level],
13048
+ // Flat map the children if the parent is not collapsed
13049
+ ...o.children?.length && !collapsedKeys.includes(valueToKey(getOptionValue(o))) ? o.children.flatMap((oc) => levelOptions(oc, level + 1, collapsedKeys, getOptionValue)) : []
13035
13050
  ];
13036
13051
  }
13037
13052
  function getTopLevelSelections(o, selectedKeys, getOptionValue) {
@@ -13040,7 +13055,16 @@ function getTopLevelSelections(o, selectedKeys, getOptionValue) {
13040
13055
  return [];
13041
13056
  }
13042
13057
  function getFilteredOptions(allOptions, searchValue, collapsedKeys, contains, getOptionLabel, getOptionValue) {
13043
- return allOptions.flatMap((option) => levelOptions(option, 0, !!searchValue, collapsedKeys, getOptionValue).filter(([nestedOption]) => searchValue ? contains(getOptionLabel(nestedOption), searchValue) : true));
13058
+ if (!searchValue) return allOptions.flatMap((option) => levelOptions(option, 0, collapsedKeys, getOptionValue));
13059
+ const search = searchValue;
13060
+ return allOptions.flatMap((option) => matchedOptions(option, 0, false));
13061
+ function matchedOptions(o, level, hasMatchedParent) {
13062
+ const isDirectlyMatched = contains(getOptionLabel(o), search);
13063
+ const children = o.children?.flatMap((oc) => matchedOptions(oc, level + 1, hasMatchedParent || isDirectlyMatched));
13064
+ if (!isDirectlyMatched && !hasMatchedParent && !children?.length) return [];
13065
+ const isCollapsed = collapsedKeys.includes(valueToKey(getOptionValue(o)));
13066
+ return isCollapsed ? [[o, level]] : [[o, level], ...children ?? []];
13067
+ }
13044
13068
  }
13045
13069
  function isOptionFullySelected(option, selectedKeys, disabledKeys, groupKeys, getOptionValue) {
13046
13070
  const key = valueToKey(getOptionValue(option));
@@ -25781,6 +25805,7 @@ function FormSectionLayout(props) {
25781
25805
  title,
25782
25806
  description,
25783
25807
  actions,
25808
+ initialFields,
25784
25809
  sections
25785
25810
  } = props;
25786
25811
  const tid = useTestIds(props, "formSectionLayout");
@@ -25799,6 +25824,7 @@ function FormSectionLayout(props) {
25799
25824
  ] }),
25800
25825
  actions && /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("div", { className: "df gap1 fs0", ...tid.actions, children: actions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime207.jsx)(Button, { ...action }, `${action.label}`)) })
25801
25826
  ] }),
25827
+ initialFields,
25802
25828
  /* @__PURE__ */ (0, import_jsx_runtime207.jsx)("div", { className: "df fdc gap6", children: sections.map((section, i) => /* @__PURE__ */ (0, import_jsx_runtime207.jsx)(FormSection, { ...section }, defaultTestId(section.title) || i)) })
25803
25829
  ] });
25804
25830
  }