@homebound/beam 2.362.0 → 2.362.2

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.
@@ -36,7 +36,8 @@ function ToggleChip(props) {
36
36
  title: tooltip,
37
37
  placement: "top",
38
38
  children: ((0, jsx_runtime_1.jsxs)("label", { css: {
39
- ...Css_1.Css.relative.dib.br16.sm.px1.cursorPointer.pyPx(4).bgGray200.if(isDisabled).cursorNotAllowed.gray600.pr1.$,
39
+ ...Css_1.Css.relative.dif.gap1.aic.br16.sm.px1.cursorPointer.pyPx(4).bgGray200.if(isDisabled).cursorNotAllowed
40
+ .gray600.pr1.$,
40
41
  ...(isSelected
41
42
  ? {
42
43
  ...Css_1.Css.color((_a = xss === null || xss === void 0 ? void 0 : xss.color) !== null && _a !== void 0 ? _a : Css_1.Palette.White).bgColor((_b = xss === null || xss === void 0 ? void 0 : xss.backgroundColor) !== null && _b !== void 0 ? _b : Css_1.Palette.Blue700).$,
@@ -44,6 +45,6 @@ function ToggleChip(props) {
44
45
  }
45
46
  : { ":hover:not([data-disabled='true'])": Css_1.Css.bgGray300.$ }),
46
47
  ...(isFocusVisible ? Css_1.Css.bshFocus.$ : {}),
47
- }, "data-selected": isSelected, "data-disabled": isDisabled, "aria-disabled": isDisabled, ...others, children: [(0, jsx_runtime_1.jsx)(react_aria_1.VisuallyHidden, { children: (0, jsx_runtime_1.jsx)("input", { ...inputProps, ...focusProps }) }), (0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.gap1.$, children: [startAdornment, label] })] })),
48
+ }, "data-selected": isSelected, "data-disabled": isDisabled, "aria-disabled": isDisabled, ...others, children: [(0, jsx_runtime_1.jsx)(react_aria_1.VisuallyHidden, { children: (0, jsx_runtime_1.jsx)("input", { ...inputProps, ...focusProps }) }), startAdornment, label] })),
48
49
  });
49
50
  }
@@ -42,7 +42,19 @@ function TreeSelectField(props) {
42
42
  const { getOptionValue = (opt) => opt.id, // if unset, assume O implements HasId
43
43
  getOptionLabel = (opt) => opt.name, // if unset, assume O implements HasName
44
44
  options, onSelect, values, defaultCollapsed = false, ...otherProps } = props;
45
- const [collapsedKeys, setCollapsedKeys] = (0, react_1.useState)(Array.isArray(options) && defaultCollapsed ? options.map((o) => getOptionValue(o)) : []);
45
+ const [collapsedKeys, setCollapsedKeys] = (0, react_1.useState)([]);
46
+ (0, react_1.useEffect)(() => {
47
+ setCollapsedKeys(!Array.isArray(options)
48
+ ? []
49
+ : defaultCollapsed
50
+ ? options.map((o) => getOptionValue(o))
51
+ : options
52
+ .flatMap(utils_1.flattenOptions)
53
+ .filter((o) => o.defaultCollapsed)
54
+ .map((o) => getOptionValue(o)));
55
+ // Explicitly ignoring `getOptionValue` as it typically isn't memo'd
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ }, [options, defaultCollapsed]);
46
58
  const contextValue = (0, react_1.useMemo)(() => ({ collapsedKeys, setCollapsedKeys, getOptionValue }),
47
59
  // TODO: validate this eslint-disable. It was automatically ignored as part of https://app.shortcut.com/homebound-team/story/40033/enable-react-hooks-exhaustive-deps-for-react-projects
48
60
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -84,14 +96,17 @@ function TreeSelectFieldBase(props) {
84
96
  // Find the options that matches the value. These could be parents or a children.
85
97
  const foundOptions = (0, utils_1.findOptions)(initialOptions, (0, Value_1.valueToKey)(v), getOptionValue);
86
98
  // Go through the `foundOptions` and get the keys of the options and its children if it has any.
87
- return foundOptions.flatMap(({ option }) => {
88
- var _a, _b;
89
- return [
90
- (0, Value_1.valueToKey)(getOptionValue(option)),
91
- ...((_b = (_a = option.children) === null || _a === void 0 ? void 0 : _a.flatMap((o) => (0, Value_1.valueToKey)(getOptionValue(o)))) !== null && _b !== void 0 ? _b : []),
92
- ];
93
- });
99
+ return foundOptions.flatMap(({ option }) => selectOptionAndAllChildren(option));
94
100
  }));
101
+ function selectOptionAndAllChildren(maybeParent) {
102
+ var _a, _b;
103
+ // Check if the maybeParent has children, if so, return those as selected keys
104
+ // Do in a recursive way so that children may have children
105
+ return [
106
+ (0, Value_1.valueToKey)(getOptionValue(maybeParent)),
107
+ ...((_b = (_a = maybeParent.children) === null || _a === void 0 ? void 0 : _a.flatMap(selectOptionAndAllChildren)) !== null && _b !== void 0 ? _b : []),
108
+ ];
109
+ }
95
110
  // It is possible that all the children of a parent were considered selected `values`, but the parent wasn't included in the `values` array.
96
111
  // In this case, the parent also should be considered a selected option.
97
112
  function areAllChildrenSelected(maybeParent) {
@@ -146,17 +161,27 @@ function TreeSelectFieldBase(props) {
146
161
  getOptionLabel,
147
162
  isReadOnly,
148
163
  nothingSelectedText,
149
- collapsedKeys,
150
164
  getOptionValue,
165
+ collapsedKeys,
151
166
  ]);
152
167
  // Initialize the TreeFieldState
153
168
  const [fieldState, setFieldState] = (0, react_1.useState)(() => initTreeFieldState());
169
+ (0, react_1.useEffect)(() => {
170
+ // We don't want to do this if initialOptions is not an array, because we would be lazy loading `allOptions`
171
+ if (Array.isArray(options)) {
172
+ setFieldState((prevState) => ({ ...prevState, allOptions: options }));
173
+ }
174
+ }, [options]);
154
175
  // Reset the TreeFieldState if the values array changes and doesn't match the selectedOptions
155
176
  (0, react_1.useEffect)(() => {
156
177
  // if the values does not match the values in the fieldState, then update the fieldState
157
178
  const selectedKeys = fieldState.selectedOptions.map((o) => (0, Value_1.valueToKey)(getOptionValue(o)));
158
- if (values &&
159
- (values.length !== selectedKeys.length || !values.every((v) => selectedKeys.includes((0, Value_1.valueToKey)(v))))) {
179
+ if (
180
+ // If the values were cleared
181
+ (values === undefined && selectedKeys.length !== 0) ||
182
+ // Or values were set, but they don't match the selected keys
183
+ (values && (values.length !== selectedKeys.length || !values.every((v) => selectedKeys.includes((0, Value_1.valueToKey)(v)))))) {
184
+ // Then reinitialize
160
185
  setFieldState(initTreeFieldState());
161
186
  }
162
187
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -218,7 +243,7 @@ function TreeSelectFieldBase(props) {
218
243
  setFieldState((prevState) => ({
219
244
  ...prevState,
220
245
  inputValue: "",
221
- filteredOptions: initialOptions.flatMap((o) => levelOptions(o, 0, false, collapsedKeys, getOptionValue)),
246
+ filteredOptions: prevState.allOptions.flatMap((o) => levelOptions(o, 0, false, collapsedKeys, getOptionValue)),
222
247
  }));
223
248
  }
224
249
  }
@@ -417,10 +442,10 @@ function TreeSelectFieldBase(props) {
417
442
  ...positionProps.style,
418
443
  width: (_c = comboBoxRef === null || comboBoxRef === void 0 ? void 0 : comboBoxRef.current) === null || _c === void 0 ? void 0 : _c.clientWidth,
419
444
  // Ensures the menu never gets too small.
420
- minWidth: 200,
445
+ minWidth: 320,
421
446
  };
422
447
  const fieldMaxWidth = (0, utils_2.getFieldWidth)(fullWidth);
423
- return ((0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.fdc.w100.maxw(fieldMaxWidth).if(labelStyle === "left").maxw100.$, ref: comboBoxRef, children: [(0, jsx_runtime_1.jsx)(ComboBoxInput_1.ComboBoxInput, { ...otherProps, fullWidth: fullWidth, labelStyle: labelStyle, buttonProps: buttonProps, buttonRef: triggerRef, inputProps: inputProps, inputRef: inputRef, inputWrapRef: inputWrapRef, listBoxRef: listBoxRef, state: state, labelProps: labelProps, selectedOptions: fieldState.selectedOptions, selectedOptionsLabels: fieldState.selectedOptionsLabels, getOptionValue: getOptionValue, getOptionLabel: getOptionLabel, contrast: contrast, borderless: borderless, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), resetField: resetField, nothingSelectedText: nothingSelectedText, isTree: true }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: triggerRef, popoverRef: popoverRef, positionProps: positionProps, onClose: () => state.close(), isOpen: state.isOpen, minWidth: 200, children: (0, jsx_runtime_1.jsx)(ListBox_1.ListBox, { ...listBoxProps, positionProps: positionProps, state: state, listBoxRef: listBoxRef, selectedOptions: fieldState.selectedOptions, getOptionLabel: getOptionLabel, getOptionValue: (o) => (0, Value_1.valueToKey)(getOptionValue(o)), contrast: contrast, horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, allowCollapsing: fieldState.allowCollapsing, isTree: true }) }))] }));
448
+ return ((0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.df.fdc.w100.maxw(fieldMaxWidth).if(labelStyle === "left").maxw100.$, ref: comboBoxRef, children: [(0, jsx_runtime_1.jsx)(ComboBoxInput_1.ComboBoxInput, { ...otherProps, fullWidth: fullWidth, labelStyle: labelStyle, buttonProps: buttonProps, buttonRef: triggerRef, inputProps: inputProps, inputRef: inputRef, inputWrapRef: inputWrapRef, listBoxRef: listBoxRef, state: state, labelProps: labelProps, selectedOptions: fieldState.selectedOptions, selectedOptionsLabels: fieldState.selectedOptionsLabels, getOptionValue: getOptionValue, getOptionLabel: getOptionLabel, contrast: contrast, borderless: borderless, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), resetField: resetField, nothingSelectedText: nothingSelectedText, isTree: true }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: triggerRef, popoverRef: popoverRef, positionProps: positionProps, onClose: () => state.close(), isOpen: state.isOpen, minWidth: 320, children: (0, jsx_runtime_1.jsx)(ListBox_1.ListBox, { ...listBoxProps, positionProps: positionProps, state: state, listBoxRef: listBoxRef, selectedOptions: fieldState.selectedOptions, getOptionLabel: getOptionLabel, getOptionValue: (o) => (0, Value_1.valueToKey)(getOptionValue(o)), contrast: contrast, horizontalLayout: labelStyle === "left", loading: fieldState.optionsLoading, allowCollapsing: fieldState.allowCollapsing, isTree: true }) }))] }));
424
449
  }
425
450
  function levelOptions(o, level, filtering, collapsedKeys, getOptionValue) {
426
451
  var _a;
@@ -7,6 +7,7 @@ type FoundOption<O> = {
7
7
  };
8
8
  export type NestedOption<O> = O & {
9
9
  children?: NestedOption<O>[];
10
+ defaultCollapsed?: boolean;
10
11
  };
11
12
  export type NestedOptionsOrLoad<O> = NestedOption<O>[] | {
12
13
  current: NestedOption<O>[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.362.0",
3
+ "version": "2.362.2",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",