@homebound/beam 2.317.2 → 2.318.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.
Files changed (34) hide show
  1. package/dist/components/AutoSaveIndicator.js +4 -1
  2. package/dist/components/BeamContext.js +4 -1
  3. package/dist/components/CssReset.js +25 -4
  4. package/dist/components/DnDGrid/useDnDGridItem.js +4 -1
  5. package/dist/components/IconButton.js +4 -1
  6. package/dist/components/Label.d.ts +2 -1
  7. package/dist/components/Label.js +2 -2
  8. package/dist/components/Modal/Modal.js +8 -2
  9. package/dist/components/ScrollShadows.js +6 -1
  10. package/dist/components/Snackbar/useSnackbar.js +4 -1
  11. package/dist/components/SuperDrawer/SuperDrawer.js +4 -1
  12. package/dist/components/SuperDrawer/useSuperDrawer.js +8 -2
  13. package/dist/components/Table/GridTable.js +4 -1
  14. package/dist/components/Table/hooks/useSetupColumnSizes.js +8 -2
  15. package/dist/components/internal/Menu.js +2 -0
  16. package/dist/components/internal/MenuItem.js +10 -0
  17. package/dist/hooks/usePersistedFilter.js +4 -1
  18. package/dist/inputs/ChipSelectField.js +4 -1
  19. package/dist/inputs/ChipTextField.js +4 -1
  20. package/dist/inputs/DateFields/DateFieldBase.js +4 -1
  21. package/dist/inputs/RichTextField.js +4 -1
  22. package/dist/inputs/TextAreaField.js +4 -28
  23. package/dist/inputs/TextFieldBase.js +5 -5
  24. package/dist/inputs/TreeSelectField/TreeOption.js +10 -0
  25. package/dist/inputs/TreeSelectField/TreeSelectField.js +16 -4
  26. package/dist/inputs/hooks/useGrowingTextField.d.ts +9 -0
  27. package/dist/inputs/hooks/useGrowingTextField.js +37 -0
  28. package/dist/inputs/internal/ComboBoxBase.d.ts +1 -0
  29. package/dist/inputs/internal/ComboBoxBase.js +20 -5
  30. package/dist/inputs/internal/ComboBoxInput.d.ts +1 -0
  31. package/dist/inputs/internal/ComboBoxInput.js +16 -2
  32. package/dist/inputs/internal/ListBox.js +4 -1
  33. package/dist/inputs/internal/VirtualizedOptions.js +4 -1
  34. package/package.json +15 -15
@@ -17,7 +17,10 @@ function AutoSaveIndicator({ hideOnIdle, doNotReset }) {
17
17
  * state should clear before the next Indicator mounts
18
18
  */
19
19
  return () => resetStatus();
20
- }, []);
20
+ },
21
+ // 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
22
+ // eslint-disable-next-line react-hooks/exhaustive-deps
23
+ []);
21
24
  switch (status) {
22
25
  case _1.AutoSaveStatus.IDLE:
23
26
  return hideOnIdle ? null : (0, jsx_runtime_1.jsx)(Indicator, { icon: "cloudSave" });
@@ -60,7 +60,10 @@ function BeamProvider({ children, ...presentationProps }) {
60
60
  drawerCanCloseDetailsChecks,
61
61
  sdHeaderDiv,
62
62
  };
63
- }, [modalBodyDiv, modalFooterDiv]);
63
+ },
64
+ // 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
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ [modalBodyDiv, modalFooterDiv]);
64
67
  return ((0, jsx_runtime_1.jsx)(exports.BeamContext.Provider, { value: { ...context }, children: (0, jsx_runtime_1.jsx)(PresentationContext_1.PresentationProvider, { ...presentationProps, children: (0, jsx_runtime_1.jsx)(Layout_1.RightPaneProvider, { children: (0, jsx_runtime_1.jsx)(index_1.AutoSaveStatusProvider, { children: (0, jsx_runtime_1.jsx)(SnackbarContext_1.SnackbarProvider, { children: (0, jsx_runtime_1.jsxs)(ToastContext_1.ToastProvider, { children: [(0, jsx_runtime_1.jsxs)(react_aria_1.OverlayProvider, { children: [children, modalRef.current && (0, jsx_runtime_1.jsx)(Modal_1.Modal, { ...modalRef.current })] }), (0, jsx_runtime_1.jsx)(SuperDrawer_1.SuperDrawer, {})] }) }) }) }) }) }));
65
68
  }
66
69
  exports.BeamProvider = BeamProvider;
@@ -118,8 +118,16 @@ Improve consistency of default fonts in all browsers. (https://github.com/sindre
118
118
  */
119
119
 
120
120
  body {
121
- font-family: system-ui, -apple-system, /* Firefox supports this but not yet system-ui */ "Segoe UI", Roboto,
122
- Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
121
+ font-family:
122
+ system-ui,
123
+ -apple-system,
124
+ /* Firefox supports this but not yet system-ui */ "Segoe UI",
125
+ Roboto,
126
+ Helvetica,
127
+ Arial,
128
+ sans-serif,
129
+ "Apple Color Emoji",
130
+ "Segoe UI Emoji";
123
131
  }
124
132
 
125
133
  /*
@@ -376,8 +384,21 @@ const tailwindPreflightReset = (0, react_1.css) `
376
384
  * to override it to ensure consistency even when using the default theme.
377
385
  */
378
386
  html {
379
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
380
- "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
387
+ font-family:
388
+ Inter,
389
+ ui-sans-serif,
390
+ system-ui,
391
+ -apple-system,
392
+ BlinkMacSystemFont,
393
+ "Segoe UI",
394
+ Roboto,
395
+ "Helvetica Neue",
396
+ Arial,
397
+ "Noto Sans",
398
+ sans-serif,
399
+ "Apple Color Emoji",
400
+ "Segoe UI Emoji",
401
+ "Segoe UI Symbol",
381
402
  "Noto Color Emoji"; /* 1 */
382
403
  line-height: 1.5; /* 2 */
383
404
  }
@@ -25,7 +25,10 @@ function useDnDGridItem(props) {
25
25
  },
26
26
  },
27
27
  };
28
- }, [dragEl, id, itemRef]);
28
+ },
29
+ // 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
30
+ // eslint-disable-next-line react-hooks/exhaustive-deps
31
+ [dragEl, id, itemRef]);
29
32
  return { dragHandleProps, dragItemProps };
30
33
  }
31
34
  exports.useDnDGridItem = useDnDGridItem;
@@ -29,7 +29,10 @@ function IconButton(props) {
29
29
  ...(isHovered && (contrast ? exports.iconButtonContrastStylesHover : exports.iconButtonStylesHover)),
30
30
  ...(isFocusVisible || forceFocusStyles ? iconButtonStylesFocus : {}),
31
31
  ...(isDisabled && iconButtonStylesDisabled),
32
- }), [isHovered, isFocusVisible, isDisabled, compact]);
32
+ }),
33
+ // 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
34
+ // eslint-disable-next-line react-hooks/exhaustive-deps
35
+ [isHovered, isFocusVisible, isDisabled, compact]);
33
36
  const iconColor = contrast ? contrastIconColor : defaultIconColor;
34
37
  const buttonAttrs = {
35
38
  ...testIds,
@@ -5,9 +5,10 @@ interface LabelProps {
5
5
  suffix?: string;
6
6
  hidden?: boolean;
7
7
  contrast?: boolean;
8
+ multiline?: boolean;
8
9
  }
9
10
  /** An internal helper component for rendering form labels. */
10
11
  export declare const Label: React.MemoExoticComponent<(props: LabelProps) => import("@emotion/react/jsx-runtime").JSX.Element>;
11
12
  /** Used for showing labels within text fields. */
12
- export declare function InlineLabel({ labelProps, label, contrast, ...others }: LabelProps): import("@emotion/react/jsx-runtime").JSX.Element;
13
+ export declare function InlineLabel({ labelProps, label, contrast, multiline, ...others }: LabelProps): import("@emotion/react/jsx-runtime").JSX.Element;
13
14
  export {};
@@ -15,7 +15,7 @@ exports.Label = react_1.default.memo((props) => {
15
15
  return hidden ? (0, jsx_runtime_1.jsx)(react_aria_1.VisuallyHidden, { children: labelEl }) : labelEl;
16
16
  });
17
17
  /** Used for showing labels within text fields. */
18
- function InlineLabel({ labelProps, label, contrast, ...others }) {
19
- return ((0, jsx_runtime_1.jsxs)("label", { ...labelProps, ...others, css: Css_1.Css.smMd.nowrap.gray900.prPx(4).add("color", "currentColor").$, children: [label, ":"] }));
18
+ function InlineLabel({ labelProps, label, contrast, multiline = false, ...others }) {
19
+ return ((0, jsx_runtime_1.jsxs)("label", { ...labelProps, ...others, css: Css_1.Css.smMd.nowrap.gray900.prPx(4).add("color", "currentColor").asc.if(multiline).asfs.pt1.$, children: [label, ":"] }));
20
20
  }
21
21
  exports.InlineLabel = InlineLabel;
@@ -52,7 +52,10 @@ function Modal(props) {
52
52
  if (forceScrolling === undefined && !isFixedHeight) {
53
53
  setHasScroll(target.scrollHeight > target.clientHeight);
54
54
  }
55
- }, []),
55
+ },
56
+ // 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
57
+ // eslint-disable-next-line react-hooks/exhaustive-deps
58
+ []),
56
59
  });
57
60
  // Even though we use raw-divs for the createPortal calls, we do actually need to
58
61
  // use refs + useEffect to stitch those raw divs back into the React component tree.
@@ -60,7 +63,10 @@ function Modal(props) {
60
63
  modalHeaderRef.current.appendChild(modalHeaderDiv);
61
64
  modalBodyRef.current.appendChild(modalBodyDiv);
62
65
  modalFooterRef.current.appendChild(modalFooterDiv);
63
- }, [modalBodyRef, modalFooterRef, modalHeaderRef]);
66
+ },
67
+ // 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
68
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
+ [modalBodyRef, modalFooterRef, modalHeaderRef]);
64
70
  return ((0, jsx_runtime_1.jsx)(react_aria_1.OverlayContainer, { children: (0, jsx_runtime_1.jsx)(components_1.AutoSaveStatusProvider, { children: (0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.underlay.z4.$, ...underlayProps, ...testId.underlay, children: (0, jsx_runtime_1.jsx)(react_aria_1.FocusScope, { contain: true, restoreFocus: true, autoFocus: true, children: (0, jsx_runtime_1.jsxs)("div", { css: Css_1.Css.br24.bgWhite.bshModal.overflowHidden
65
71
  .maxh("90vh")
66
72
  .df.fdc.wPx(width)
@@ -37,9 +37,14 @@ function ScrollShadows(props) {
37
37
  const boxSize = horizontal ? clientWidth : clientHeight;
38
38
  setShowStartShadow(start > 0);
39
39
  setShowEndShadow(start + boxSize < end);
40
- }, []);
40
+ },
41
+ // 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
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ []);
41
44
  // Use a ResizeObserver to update the scroll props to determine if the shadows should be shown.
42
45
  // This executes on render and subsequent resizes which could be due to content/`children` changes (such as responses from APIs).
46
+ // 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
47
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
48
  const onResize = (0, react_1.useCallback)(() => scrollRef.current && updateScrollProps(scrollRef.current), []);
44
49
  (0, utils_1.useResizeObserver)({ ref: scrollRef, onResize });
45
50
  return ((0, jsx_runtime_1.jsxs)("div", { css: src_1.Css.relative.overflowHidden
@@ -19,7 +19,10 @@ function useSnackbar() {
19
19
  }
20
20
  return returnValue;
21
21
  });
22
- }, []);
22
+ },
23
+ // 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
24
+ // eslint-disable-next-line react-hooks/exhaustive-deps
25
+ []);
23
26
  const triggerNotice = (0, react_1.useCallback)((props) => {
24
27
  var _a;
25
28
  // Sets `noticeId` to the current value of `snackbarId` and then increments.
@@ -51,7 +51,10 @@ function SuperDrawer() {
51
51
  if (((_a = headerRef.current) === null || _a === void 0 ? void 0 : _a.childNodes.length) === 0 && content) {
52
52
  headerRef.current.appendChild(sdHeaderDiv);
53
53
  }
54
- }, [headerRef, content]);
54
+ },
55
+ // 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
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ [headerRef, content]);
55
58
  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.$ } }), (0, react_1.createElement)(framer_motion_1.motion.div, { ...testId,
56
59
  // Key is required for framer-motion animations
57
60
  key: "superDrawer",
@@ -85,7 +85,10 @@ function useSuperDrawer() {
85
85
  onClose();
86
86
  },
87
87
  };
88
- }, [canCloseChecks, canCloseDetailsChecks, contentStack, modalState, openModal]);
88
+ },
89
+ // 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
90
+ // eslint-disable-next-line react-hooks/exhaustive-deps
91
+ [canCloseChecks, canCloseDetailsChecks, contentStack, modalState, openModal]);
89
92
  // useMemo the actions separately from the dynamic isDrawerOpen value
90
93
  const actions = (0, react_1.useMemo)(() => {
91
94
  return {
@@ -131,7 +134,10 @@ function useSuperDrawer() {
131
134
  ];
132
135
  },
133
136
  };
134
- }, [canCloseChecks, canCloseDetailsChecks, closeActions, contentStack]);
137
+ },
138
+ // 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
139
+ // eslint-disable-next-line react-hooks/exhaustive-deps
140
+ [canCloseChecks, canCloseDetailsChecks, closeActions, contentStack]);
135
141
  return {
136
142
  ...actions,
137
143
  ...closeActions,
@@ -105,7 +105,10 @@ function GridTable(props) {
105
105
  // to avoid "Cannot update component during render" errors.
106
106
  api.tableState.setColumns(columnsWithIds, visibleColumnsStorageKey);
107
107
  return api;
108
- }, [props.api]);
108
+ },
109
+ // 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
110
+ // eslint-disable-next-line react-hooks/exhaustive-deps
111
+ [props.api]);
109
112
  const style = (0, TableStyles_1.resolveStyles)(maybeStyle);
110
113
  const { tableState } = api;
111
114
  tableState.onRowSelect = onRowSelect;
@@ -43,7 +43,10 @@ function useSetupColumnSizes(style, columns, resizeRef, expandedColumnIds) {
43
43
  const width = (_a = resizeRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth;
44
44
  width && setTableAndColumnWidths(width);
45
45
  }
46
- }, [columns, setTableAndColumnWidths]);
46
+ },
47
+ // 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
+ // eslint-disable-next-line react-hooks/exhaustive-deps
49
+ [columns, setTableAndColumnWidths]);
47
50
  const setTableAndColumnWidthsDebounced = (0, use_debounce_1.useDebouncedCallback)(setTableAndColumnWidths, 100);
48
51
  const onResize = (0, react_1.useCallback)(() => {
49
52
  const target = resizeRef.current;
@@ -56,7 +59,10 @@ function useSetupColumnSizes(style, columns, resizeRef, expandedColumnIds) {
56
59
  setTableAndColumnWidthsDebounced(target.clientWidth);
57
60
  }
58
61
  }
59
- }, [tableWidth, setTableAndColumnWidths, setTableAndColumnWidthsDebounced]);
62
+ },
63
+ // 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
64
+ // eslint-disable-next-line react-hooks/exhaustive-deps
65
+ [tableWidth, setTableAndColumnWidths, setTableAndColumnWidthsDebounced]);
60
66
  (0, utils_1.useResizeObserver)({ ref: resizeRef, onResize });
61
67
  return columnSizes;
62
68
  }
@@ -59,6 +59,8 @@ function Menu(props) {
59
59
  const tid = (0, utils_1.useTestIds)(props);
60
60
  // Bulk updates of MenuItems below. If we find this to be of sluggish performance, then we can change to be more surgical in our updating.
61
61
  // If our list of items change, update the "items" menu section. (key is based on label in `getKey` above)
62
+ // 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
63
+ // eslint-disable-next-line react-hooks/exhaustive-deps
62
64
  (0, react_1.useEffect)(() => filteredTree.update("items", { label: "items", items }), [items]);
63
65
  return ((0, jsx_runtime_1.jsx)(react_aria_1.FocusScope, { children: (0, jsx_runtime_1.jsxs)("div", {
64
66
  // Using `max-height: inherit` allows us to take advantage of the height set on the overlay container, which updates based on the available space for the overlay within the viewport
@@ -22,10 +22,20 @@ function MenuItemImpl(props) {
22
22
  const isDisabled = Boolean(disabled);
23
23
  const isSelected = state.selectionManager.selectedKeys.has(label);
24
24
  const isFocused = state.selectionManager.focusedKey === item.key;
25
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
26
+ // eslint-disable-next-line react-hooks/rules-of-hooks
25
27
  const ref = (0, react_1.useRef)(null);
28
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
29
+ // eslint-disable-next-line react-hooks/rules-of-hooks
26
30
  const history = (0, react_router_1.useHistory)();
31
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
32
+ // eslint-disable-next-line react-hooks/rules-of-hooks
27
33
  const { hoverProps, isHovered } = (0, react_aria_1.useHover)({});
34
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
35
+ // eslint-disable-next-line react-hooks/rules-of-hooks
28
36
  const tid = (0, utils_1.useTestIds)(props);
37
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
38
+ // eslint-disable-next-line react-hooks/rules-of-hooks
29
39
  const { menuItemProps } = (0, react_aria_1.useMenuItem)({
30
40
  key: item.key,
31
41
  isDisabled,
@@ -36,7 +36,10 @@ function usePersistedFilter({ storageKey, filterDefs }) {
36
36
  // current storedFilter, use query params filter
37
37
  setStoredFilter(queryParamsFilter);
38
38
  }
39
- }, [storedFilter, setStoredFilter, setQueryParams, queryParamsFilter]);
39
+ },
40
+ // 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
41
+ // eslint-disable-next-line react-hooks/exhaustive-deps
42
+ [storedFilter, setStoredFilter, setQueryParams, queryParamsFilter]);
40
43
  return { setFilter, filter };
41
44
  }
42
45
  exports.usePersistedFilter = usePersistedFilter;
@@ -80,7 +80,10 @@ function ChipSelectField(props) {
80
80
  }
81
81
  }
82
82
  firstRender.current = false;
83
- }, [options]);
83
+ },
84
+ // 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
85
+ // eslint-disable-next-line react-hooks/exhaustive-deps
86
+ [options]);
84
87
  const selectChildren = (0, react_1.useMemo)(() => listData.items.map((s) => {
85
88
  if (isListBoxSection(s)) {
86
89
  return ((0, jsx_runtime_1.jsx)(react_stately_1.Section, { title: s.title, items: s.options, children: (item) => {
@@ -38,7 +38,10 @@ function ChipTextField(props) {
38
38
  (0, react_1.useEffect)(() => {
39
39
  var _a;
40
40
  autoFocus && ((_a = fieldRef.current) === null || _a === void 0 ? void 0 : _a.focus());
41
- }, []);
41
+ },
42
+ // 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
43
+ // eslint-disable-next-line react-hooks/exhaustive-deps
44
+ []);
42
45
  // React doesn't like contentEditable because it takes the children of the node out of React's scope. This is fine in this case as it is just a text value and we are managing it.
43
46
  return ((0, jsx_runtime_1.jsx)("span", { ref: fieldRef, contentEditable: true, suppressContentEditableWarning: true, "aria-required": required, "aria-label": label, onKeyDown: (e) => {
44
47
  if (e.key === "Enter") {
@@ -133,7 +133,10 @@ function DateFieldBase(props) {
133
133
  props.onChange(undefined);
134
134
  return;
135
135
  }
136
- }, [isRangeMode, props.onChange]);
136
+ },
137
+ // 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
138
+ // eslint-disable-next-line react-hooks/exhaustive-deps
139
+ [isRangeMode, props.onChange]);
137
140
  // If showing the short date format, "01/01/20", so set size to 8. If medium (Wed, Nov 23) use 10 characters (leaving out the `,` character in the count because it is so small)
138
141
  // Otherwise the long format can be `undefined`.
139
142
  // Setting the size attribute only impacts the fields when displayed in a container that doesn't allow the field to grow to its max width, such as in an inline container.
@@ -86,7 +86,10 @@ function RichTextField(props) {
86
86
  // The <trix-editor /> web component's `trix-initialize` event may fire before a `useEffect` hook in the component is executed, making it difficult ot attach the event listener locally.
87
87
  window.addEventListener("trix-initialize", onEditorInit);
88
88
  return id;
89
- }, []);
89
+ },
90
+ // 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
91
+ // eslint-disable-next-line react-hooks/exhaustive-deps
92
+ []);
90
93
  (0, react_2.useEffect)(() => {
91
94
  // If our value prop changes (without the change coming from us), reload it
92
95
  if (!readOnly && editor && value !== currentHtml.current) {
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TextAreaField = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
- const utils_1 = require("@react-aria/utils");
6
5
  const react_1 = require("react");
7
6
  const react_aria_1 = require("react-aria");
8
7
  const components_1 = require("../components");
8
+ const useGrowingTextField_1 = require("./hooks/useGrowingTextField");
9
9
  const TextFieldBase_1 = require("./TextFieldBase");
10
- const utils_2 = require("../utils");
10
+ const utils_1 = require("../utils");
11
11
  /** Returns a <textarea /> element that auto-adjusts height based on the field's value */
12
12
  function TextAreaField(props) {
13
13
  const { value = "", disabled = false, readOnly = false, onBlur, onFocus, preventNewLines, onEnter, ...otherProps } = props;
@@ -16,31 +16,7 @@ function TextAreaField(props) {
16
16
  const textFieldProps = { ...otherProps, value, isDisabled, isReadOnly };
17
17
  const inputRef = (0, react_1.useRef)(null);
18
18
  const inputWrapRef = (0, react_1.useRef)(null);
19
- // not in stately because this is so we know when to re-measure, which is a spectrum design
20
- const onHeightChange = (0, react_1.useCallback)(() => {
21
- const input = inputRef.current;
22
- const inputWrap = inputWrapRef.current;
23
- if (input && inputWrap) {
24
- const prevAlignment = input.style.alignSelf;
25
- input.style.alignSelf = "start";
26
- input.style.height = "auto";
27
- // Adding 2px to height avoids showing the scrollbar. This is to compensate for the border due to `box-sizing: border-box;`
28
- inputWrap.style.height = `${input.scrollHeight + 2}px`;
29
- // Set the textarea's height back to 100% so it takes up the full `inputWrap`
30
- input.style.height = "100%";
31
- input.style.alignSelf = prevAlignment;
32
- }
33
- }, [inputRef]);
34
- (0, utils_1.useLayoutEffect)(() => {
35
- if (inputRef.current) {
36
- // Temp hack until we can figure out a better way to ensure proper measurements when rendered through a portal (i.e. Modals)
37
- if (inputRef.current.scrollHeight === 0) {
38
- setTimeout(() => onHeightChange(), 0);
39
- return;
40
- }
41
- onHeightChange();
42
- }
43
- }, [onHeightChange, value, inputRef]);
19
+ (0, useGrowingTextField_1.useGrowingTextField)({ inputRef, inputWrapRef, value });
44
20
  const { labelProps, inputProps } = (0, react_aria_1.useTextField)({
45
21
  ...textFieldProps,
46
22
  inputElementType: "textarea",
@@ -51,7 +27,7 @@ function TextAreaField(props) {
51
27
  // Prevent user from typing the new line character
52
28
  if (e.key === "Enter") {
53
29
  e.preventDefault();
54
- (0, utils_2.maybeCall)(onEnter);
30
+ (0, utils_1.maybeCall)(onEnter);
55
31
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur();
56
32
  }
57
33
  },
@@ -101,7 +101,7 @@ function TextFieldBase(props) {
101
101
  ...fieldStyles.inputWrapperReadOnly,
102
102
  ...(multiline ? Css_1.Css.fdc.aifs.gap2.$ : Css_1.Css.if(wrap === false).truncate.$),
103
103
  ...xss,
104
- }, "data-readonly": "true", ...tid, children: [!multiline && labelStyle === "inline" && label && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, { labelProps: labelProps, label: label, ...tid.label })), multiline
104
+ }, "data-readonly": "true", ...tid, children: [labelStyle === "inline" && label && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, { multiline: multiline, labelProps: labelProps, label: label, ...tid.label })), multiline
105
105
  ? (_g = inputProps.value) === null || _g === void 0 ? void 0 : _g.split("\n\n").map((p, i) => ((0, jsx_runtime_1.jsx)("p", { css: Css_1.Css.my1.$, children: p.split("\n").map((sentence, j) => ((0, jsx_runtime_1.jsxs)("span", { children: [sentence, (0, jsx_runtime_1.jsx)("br", {})] }, j))) }, i)))
106
106
  : inputProps.value] })) : ((0, jsx_runtime_1.jsxs)("div", { css: {
107
107
  ...fieldStyles.inputWrapper,
@@ -110,19 +110,19 @@ function TextFieldBase(props) {
110
110
  ...(showHover ? fieldStyles.hover : {}),
111
111
  // Only show error styles if the field is not disabled, following the pattern that the error message is also hidden
112
112
  ...(errorMsg && !inputProps.disabled ? fieldStyles.error : {}),
113
- ...Css_1.Css.if(multiline).aifs.px0.mhPx(textAreaMinHeight).$,
114
- }, ...hoverProps, ref: inputWrapRef, children: [!multiline && labelStyle === "inline" && label && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, { labelProps: labelProps, label: label, ...tid.label })), !multiline && startAdornment && (0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.fs0.br4.pr1.$, children: startAdornment }), (0, jsx_runtime_1.jsx)(ElementType, { ...(0, react_aria_1.mergeProps)(inputProps, { onBlur, onFocus: onFocusChained, onChange: onDomChange }, { "aria-invalid": Boolean(errorMsg), ...(labelStyle === "hidden" ? { "aria-label": label } : {}) }), ...(errorMsg ? { "aria-errormessage": errorMessageId } : {}), ref: fieldRef, rows: multiline ? 1 : undefined, css: {
113
+ ...Css_1.Css.if(multiline).aifs.mhPx(textAreaMinHeight).$,
114
+ }, ...hoverProps, ref: inputWrapRef, children: [labelStyle === "inline" && label && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, { multiline: multiline, labelProps: labelProps, label: label, ...tid.label })), startAdornment && (0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.asc.fs0.br4.pr1.$, children: startAdornment }), (0, jsx_runtime_1.jsx)(ElementType, { ...(0, react_aria_1.mergeProps)(inputProps, { onBlur, onFocus: onFocusChained, onChange: onDomChange }, { "aria-invalid": Boolean(errorMsg), ...(labelStyle === "hidden" ? { "aria-label": label } : {}) }), ...(errorMsg ? { "aria-errormessage": errorMessageId } : {}), ref: fieldRef, rows: multiline ? 1 : undefined, css: {
115
115
  ...fieldStyles.input,
116
116
  ...(inputProps.disabled ? fieldStyles.disabled : {}),
117
117
  ...(showHover ? fieldStyles.hover : {}),
118
- ...(multiline ? Css_1.Css.h100.p1.add("resize", "none").$ : Css_1.Css.truncate.$),
118
+ ...(multiline ? Css_1.Css.h100.py1.add("resize", "none").$ : Css_1.Css.truncate.$),
119
119
  ...xss,
120
120
  }, ...tid }), isFocused && clearable && onChange && inputProps.value && ((0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "xCircle", color: Css_1.Palette.Gray700, onClick: () => {
121
121
  var _a;
122
122
  onChange(undefined);
123
123
  // Reset focus to input element
124
124
  (_a = fieldRef.current) === null || _a === void 0 ? void 0 : _a.focus();
125
- } })), errorInTooltip && errorMsg && !hideErrorMessage && ((0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.pl1.fs0.$, children: (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: "error", color: Css_1.Palette.Red600, tooltip: errorMsg }) })), !multiline && endAdornment && (0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.pl1.fs0.$, children: endAdornment })] })),
125
+ } })), errorInTooltip && errorMsg && !hideErrorMessage && ((0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.asc.pl1.fs0.$, children: (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: "error", color: Css_1.Palette.Red600, tooltip: errorMsg }) })), endAdornment && (0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.asc.pl1.fs0.$, children: endAdornment })] })),
126
126
  }), labelStyle !== "left" &&
127
127
  (alwaysShowHelperText || (!compound && !inputProps.disabled && !inputProps.readOnly)) && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [errorMsg && !errorInTooltip && ((0, jsx_runtime_1.jsx)(ErrorMessage_1.ErrorMessage, { id: errorMessageId, errorMsg: errorMsg, hidden: hideErrorMessage, ...tid.errorMsg })), helperText && (0, jsx_runtime_1.jsx)(HelperText_1.HelperText, { helperText: helperText, ...tid.helperText })] }))] }), labelStyle === "left" &&
128
128
  (alwaysShowHelperText ||
@@ -18,10 +18,20 @@ function TreeOption(props) {
18
18
  if (!leveledOption)
19
19
  return null;
20
20
  const [option, level] = leveledOption;
21
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
22
+ // eslint-disable-next-line react-hooks/rules-of-hooks
21
23
  const ref = (0, react_1.useRef)(null);
24
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
25
+ // eslint-disable-next-line react-hooks/rules-of-hooks
22
26
  const { hoverProps, isHovered } = (0, react_aria_1.useHover)({});
27
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
28
+ // eslint-disable-next-line react-hooks/rules-of-hooks
23
29
  const tid = (0, utils_1.useTestIds)(props, "treeOption");
30
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
31
+ // eslint-disable-next-line react-hooks/rules-of-hooks
24
32
  const { collapsedKeys, setCollapsedKeys, getOptionValue } = (0, TreeSelectField_1.useTreeSelectFieldProvider)();
33
+ // TODO: validate this eslint-disable with https://app.shortcut.com/homebound-team/story/40045
34
+ // eslint-disable-next-line react-hooks/rules-of-hooks
25
35
  const { optionProps, isDisabled, isFocused, isSelected } = (0, react_aria_1.useOption)({ key: item.key, shouldSelectOnPressUp: true, shouldFocusOnHover: false }, state, ref);
26
36
  // If this item is not selected, then determine if some of its children are selected to show the indeterminate state.
27
37
  // Note: If `isSelected` will be true if all of the children were selected. That auto-parent-selection happens in the `onSelect` callback in TreeSelectField.
@@ -40,7 +40,10 @@ function TreeSelectField(props) {
40
40
  getOptionLabel = (opt) => opt.name, // if unset, assume O implements HasName
41
41
  options, onSelect, values, defaultCollapsed = false, ...otherProps } = props;
42
42
  const [collapsedKeys, setCollapsedKeys] = (0, react_1.useState)(Array.isArray(options) && defaultCollapsed ? options.map((o) => getOptionValue(o)) : []);
43
- const contextValue = (0, react_1.useMemo)(() => ({ collapsedKeys, setCollapsedKeys, getOptionValue }), [collapsedKeys, setCollapsedKeys]);
43
+ const contextValue = (0, react_1.useMemo)(() => ({ collapsedKeys, setCollapsedKeys, getOptionValue }),
44
+ // 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
45
+ // eslint-disable-next-line react-hooks/exhaustive-deps
46
+ [collapsedKeys, setCollapsedKeys]);
44
47
  return ((0, jsx_runtime_1.jsx)(exports.CollapsedContext.Provider, { value: contextValue, children: (0, jsx_runtime_1.jsx)(TreeSelectFieldBase, { ...otherProps, options: options, getOptionLabel: getOptionLabel, getOptionValue: getOptionValue, values: values, onSelect: ({ all, leaf, root }) => {
45
48
  onSelect({ all, leaf, root });
46
49
  } }) }));
@@ -136,7 +139,10 @@ function TreeSelectFieldBase(props) {
136
139
  }));
137
140
  }
138
141
  reactToCollapse.current = true;
139
- }, [collapsedKeys]);
142
+ },
143
+ // 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
144
+ // eslint-disable-next-line react-hooks/exhaustive-deps
145
+ [collapsedKeys]);
140
146
  // Update the filtered options when the input value changes
141
147
  const onInputChange = (0, react_1.useCallback)((inputValue) => {
142
148
  setFieldState((prevState) => {
@@ -147,7 +153,10 @@ function TreeSelectFieldBase(props) {
147
153
  filteredOptions: prevState.allOptions.flatMap((o) => levelOptions(o, 0, inputValue.length > 0).filter(([option]) => contains(getOptionLabel(option), inputValue))),
148
154
  };
149
155
  });
150
- }, [setFieldState]);
156
+ },
157
+ // 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
158
+ // eslint-disable-next-line react-hooks/exhaustive-deps
159
+ [setFieldState]);
151
160
  // Handle loading of the options in the case that they are loaded via a Promise.
152
161
  const maybeInitLoad = (0, react_1.useCallback)(async (options, fieldState, setFieldState) => {
153
162
  if (!Array.isArray(options)) {
@@ -162,7 +171,10 @@ function TreeSelectFieldBase(props) {
162
171
  optionsLoading: false,
163
172
  }));
164
173
  }
165
- }, []);
174
+ },
175
+ // 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
176
+ // eslint-disable-next-line react-hooks/exhaustive-deps
177
+ []);
166
178
  // Only on the first open of the listbox, we want to load the options if they haven't been loaded yet.
167
179
  const firstOpen = (0, react_1.useRef)(true);
168
180
  function onOpenChange(isOpen) {
@@ -0,0 +1,9 @@
1
+ import { MutableRefObject } from "react";
2
+ interface GrowingTextFieldProps {
3
+ inputRef: MutableRefObject<HTMLTextAreaElement | HTMLInputElement | null>;
4
+ inputWrapRef: MutableRefObject<HTMLDivElement | null>;
5
+ value: number | string | readonly string[] | undefined;
6
+ disabled?: boolean;
7
+ }
8
+ export declare function useGrowingTextField({ inputRef, inputWrapRef, value, disabled }: GrowingTextFieldProps): void;
9
+ export {};
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useGrowingTextField = void 0;
4
+ const utils_1 = require("@react-aria/utils");
5
+ const react_1 = require("react");
6
+ function useGrowingTextField({ inputRef, inputWrapRef, value, disabled }) {
7
+ // not in stately because this is so we know when to re-measure, which is a spectrum design
8
+ const onHeightChange = (0, react_1.useCallback)(() => {
9
+ if (disabled)
10
+ return;
11
+ const input = inputRef.current;
12
+ const inputWrap = inputWrapRef.current;
13
+ if (input && inputWrap) {
14
+ const prevAlignment = input.style.alignSelf;
15
+ input.style.alignSelf = "start";
16
+ input.style.height = "auto";
17
+ // Adding 2px to height avoids showing the scrollbar. This is to compensate for the border due to `box-sizing: border-box;`
18
+ inputWrap.style.height = `${input.scrollHeight + 2}px`;
19
+ // Set the textarea's height back to 100% so it takes up the full `inputWrap`
20
+ input.style.height = "100%";
21
+ input.style.alignSelf = prevAlignment;
22
+ }
23
+ }, [inputRef, disabled, inputWrapRef]);
24
+ (0, utils_1.useLayoutEffect)(() => {
25
+ if (disabled)
26
+ return;
27
+ if (inputRef.current) {
28
+ // Temp hack until we can figure out a better way to ensure proper measurements when rendered through a portal (i.e. Modals)
29
+ if (inputRef.current.scrollHeight === 0) {
30
+ setTimeout(() => onHeightChange(), 0);
31
+ return;
32
+ }
33
+ onHeightChange();
34
+ }
35
+ }, [onHeightChange, value, inputRef, disabled]);
36
+ }
37
+ exports.useGrowingTextField = useGrowingTextField;
@@ -50,6 +50,7 @@ export interface ComboBoxBaseProps<O, V extends Value> extends BeamFocusableProp
50
50
  */
51
51
  unsetLabel?: string;
52
52
  hideErrorMessage?: boolean;
53
+ multiline?: boolean;
53
54
  }
54
55
  /**
55
56
  * Provides a non-native select/dropdown widget that allows the user to type to filter the options.
@@ -30,11 +30,20 @@ function ComboBoxBase(props) {
30
30
  // Call `initializeOptions` to prepend the `unset` option if the `unsetLabel` was provided.
31
31
  const maybeOptions = (0, react_1.useMemo)(() => initializeOptions(options, unsetLabel), [options, unsetLabel]);
32
32
  // Memoize the callback functions and handle the `unset` option if provided.
33
- const getOptionLabel = (0, react_1.useCallback)((o) => (unsetLabel && o === exports.unsetOption ? unsetLabel : props.getOptionLabel(o)), [props.getOptionLabel, unsetLabel]);
34
- const getOptionValue = (0, react_1.useCallback)((o) => (unsetLabel && o === exports.unsetOption ? undefined : props.getOptionValue(o)), [props.getOptionValue, unsetLabel]);
33
+ const getOptionLabel = (0, react_1.useCallback)((o) => (unsetLabel && o === exports.unsetOption ? unsetLabel : props.getOptionLabel(o)),
34
+ // 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
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ [props.getOptionLabel, unsetLabel]);
37
+ const getOptionValue = (0, react_1.useCallback)((o) => (unsetLabel && o === exports.unsetOption ? undefined : props.getOptionValue(o)),
38
+ // 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
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ [props.getOptionValue, unsetLabel]);
35
41
  const getOptionMenuLabel = (0, react_1.useCallback)((o) => props.getOptionMenuLabel
36
42
  ? props.getOptionMenuLabel(o, Boolean(unsetLabel) && o === exports.unsetOption)
37
- : getOptionLabel(o), [props.getOptionValue, unsetLabel, getOptionLabel]);
43
+ : getOptionLabel(o),
44
+ // 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
45
+ // eslint-disable-next-line react-hooks/exhaustive-deps
46
+ [props.getOptionValue, unsetLabel, getOptionLabel]);
38
47
  const { contains } = (0, react_aria_1.useFilter)({ sensitivity: "base" });
39
48
  const isDisabled = !!disabled;
40
49
  const isReadOnly = !!readOnly;
@@ -203,7 +212,10 @@ function ComboBoxBase(props) {
203
212
  };
204
213
  });
205
214
  }
206
- }, [values]);
215
+ },
216
+ // 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
217
+ // eslint-disable-next-line react-hooks/exhaustive-deps
218
+ [values]);
207
219
  (0, react_1.useEffect)(() => {
208
220
  // When options are an array, then use them as-is.
209
221
  // If options are an object, then use the `initial` array if the menu has not been opened
@@ -231,7 +243,10 @@ function ComboBoxBase(props) {
231
243
  };
232
244
  });
233
245
  }
234
- }, [maybeOptions]);
246
+ },
247
+ // 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
248
+ // eslint-disable-next-line react-hooks/exhaustive-deps
249
+ [maybeOptions]);
235
250
  // For the most part, the returned props contain `aria-*` and `id` attributes for accessibility purposes.
236
251
  const { buttonProps: triggerProps, inputProps, listBoxProps, labelProps, } = (0, react_aria_1.useComboBox)({
237
252
  ...comboBoxProps,
@@ -28,6 +28,7 @@ interface ComboBoxInputProps<O, V extends Value> extends PresentationFieldProps
28
28
  resetField: VoidFunction;
29
29
  hideErrorMessage?: boolean;
30
30
  isTree?: boolean;
31
+ multiline?: boolean;
31
32
  }
32
33
  export declare function ComboBoxInput<O, V extends Value>(props: ComboBoxInputProps<O, V>): import("@emotion/react/jsx-runtime").JSX.Element;
33
34
  export {};
@@ -5,20 +5,27 @@ 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
7
  const components_1 = require("../../components");
8
+ const PresentationContext_1 = require("../../components/PresentationContext");
8
9
  const Css_1 = require("../../Css");
10
+ const useGrowingTextField_1 = require("../hooks/useGrowingTextField");
9
11
  const TextFieldBase_1 = require("../TextFieldBase");
10
12
  const TreeSelectField_1 = require("../TreeSelectField/TreeSelectField");
11
13
  const utils_1 = require("../TreeSelectField/utils");
12
14
  const utils_2 = require("../../utils");
13
15
  function ComboBoxInput(props) {
14
- const { inputProps, buttonProps, buttonRef, errorMsg, state, fieldDecoration, onBlur, onFocus, selectedOptions, getOptionValue, getOptionLabel, sizeToContent = false, contrast = false, nothingSelectedText, resetField, isTree, listBoxRef, ...otherProps } = props;
16
+ const { inputProps, buttonProps, buttonRef, errorMsg, state, fieldDecoration, onBlur, onFocus, selectedOptions, getOptionValue, getOptionLabel, sizeToContent = false, contrast = false, nothingSelectedText, resetField, isTree, listBoxRef, inputRef, inputWrapRef, multiline = false, ...otherProps } = props;
17
+ const { wrap = false } = (0, PresentationContext_1.usePresentationContext)();
18
+ // Allow the field to wrap whether the caller has explicitly set `multiline=true` or the `PresentationContext.wrap=true`
19
+ const allowWrap = wrap || multiline;
15
20
  const { collapsedKeys, setCollapsedKeys } = (0, TreeSelectField_1.useTreeSelectFieldProvider)();
16
21
  const [isFocused, setIsFocused] = (0, react_1.useState)(false);
17
22
  const isMultiSelect = state.selectionManager.selectionMode === "multiple";
18
23
  const showNumSelection = isMultiSelect && state.selectionManager.selectedKeys.size > 1;
19
24
  // For MultiSelect only show the `fieldDecoration` when input is not in focus.
20
25
  const showFieldDecoration = (!isMultiSelect || (isMultiSelect && !isFocused)) && fieldDecoration && selectedOptions.length === 1;
21
- return ((0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, { ...otherProps, errorMsg: errorMsg, contrast: contrast, xss: otherProps.labelStyle !== "inline" && !inputProps.readOnly ? Css_1.Css.fw5.$ : {}, startAdornment: (showNumSelection && ((0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.wPx(16).hPx(16).fs0.br100.bgBlue700.white.tinySb.df.aic.jcc.$, "data-testid": "selectedOptionsCount", children: state.selectionManager.selectedKeys.size }))) ||
26
+ const multilineProps = allowWrap ? { textAreaMinHeight: 0, multiline: true } : {};
27
+ (0, useGrowingTextField_1.useGrowingTextField)({ disabled: !allowWrap, inputRef, inputWrapRef, value: inputProps.value });
28
+ return ((0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, { ...otherProps, ...multilineProps, inputRef: inputRef, inputWrapRef: inputWrapRef, errorMsg: errorMsg, contrast: contrast, xss: otherProps.labelStyle !== "inline" && !inputProps.readOnly ? Css_1.Css.fw5.$ : {}, startAdornment: (showNumSelection && ((0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.wPx(16).hPx(16).fs0.br100.bgBlue700.white.tinySb.df.aic.jcc.$, "data-testid": "selectedOptionsCount", children: state.selectionManager.selectedKeys.size }))) ||
22
29
  (showFieldDecoration && fieldDecoration(selectedOptions[0])), endAdornment: !inputProps.readOnly && ((0, jsx_runtime_1.jsx)("button", { ...buttonProps, disabled: inputProps.disabled, ref: buttonRef, css: {
23
30
  ...Css_1.Css.br4.outline0.gray700.if(contrast).gray400.$,
24
31
  ...(inputProps.disabled ? Css_1.Css.cursorNotAllowed.gray400.if(contrast).gray600.$ : {}),
@@ -78,6 +85,13 @@ function ComboBoxInput(props) {
78
85
  }
79
86
  inputProps.onKeyDown && inputProps.onKeyDown(e);
80
87
  },
88
+ onChange: (e) => {
89
+ // Prevent user from entering any content that has new line characters.
90
+ const target = e.target;
91
+ target.value = target.value.replace(/[\n\r]/g, "");
92
+ // Call existing onChange handler if any.
93
+ inputProps.onChange && inputProps.onChange(e);
94
+ },
81
95
  onBlur: (e) => {
82
96
  var _a;
83
97
  // Do not call onBlur if readOnly or interacting within the input wrapper (such as the menu trigger button), or anything within the listbox.
@@ -51,7 +51,10 @@ function ListBox(props) {
51
51
  onListHeightChange(virtuosoListHeight.current);
52
52
  }
53
53
  firstRender.current = false;
54
- }, [state.selectionManager.selectedKeys.size]);
54
+ },
55
+ // 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
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ [state.selectionManager.selectedKeys.size]);
55
58
  return ((0, jsx_runtime_1.jsxs)("div", { css: {
56
59
  // If `horizontalLayout`, then that means `labelStyle === "left"`. In this case the label the the field both take 50% of the horizontal space.
57
60
  // Add `w50` in that case to ensure the ListBox is only the width of the field. If the width definitions ever change, we need to update here as well.
@@ -21,7 +21,10 @@ function VirtualizedOptions(props) {
21
21
  if (scrollOnFocus && virtuosoRef.current && (focusedItem === null || focusedItem === void 0 ? void 0 : focusedItem.index)) {
22
22
  virtuosoRef.current.scrollToIndex({ index: focusedItem.index, align: "center" });
23
23
  }
24
- }, [focusedItem]);
24
+ },
25
+ // 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
26
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27
+ [focusedItem]);
25
28
  return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { ref: virtuosoRef, totalListHeightChanged: onListHeightChange, totalCount: items.length, ...(process.env.NODE_ENV === "test"
26
29
  ? {
27
30
  // We don't really need to set this, but it's handy for tests, which would
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.317.2",
3
+ "version": "2.318.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -75,24 +75,24 @@
75
75
  "@emotion/babel-preset-css-prop": "^11.10.0",
76
76
  "@emotion/jest": "^11.10.5",
77
77
  "@emotion/react": "^11.10.6",
78
- "@homebound/eslint-config": "1.6.1",
78
+ "@homebound/eslint-config": "^1.8.0",
79
79
  "@homebound/rtl-react-router-utils": "1.0.3",
80
80
  "@homebound/rtl-utils": "^2.65.0",
81
81
  "@homebound/truss": "^1.131.0",
82
82
  "@homebound/tsconfig": "^1.0.3",
83
83
  "@semantic-release/exec": "^6.0.3",
84
84
  "@semantic-release/git": "^10.0.1",
85
- "@storybook/addon-docs": "^7.3.0",
86
- "@storybook/addon-essentials": "^7.3.0",
87
- "@storybook/addon-interactions": "^7.3.0",
88
- "@storybook/addon-links": "^7.3.0",
89
- "@storybook/addon-mdx-gfm": "^7.3.0",
90
- "@storybook/addons": "^7.3.0",
91
- "@storybook/manager-api": "^7.3.0",
85
+ "@storybook/addon-docs": "^7.4.5",
86
+ "@storybook/addon-essentials": "^7.4.5",
87
+ "@storybook/addon-interactions": "^7.4.5",
88
+ "@storybook/addon-links": "^7.4.5",
89
+ "@storybook/addon-mdx-gfm": "^7.4.5",
90
+ "@storybook/addons": "^7.4.5",
91
+ "@storybook/manager-api": "^7.4.5",
92
92
  "@storybook/mdx2-csf": "^1.1.0",
93
- "@storybook/react": "^7.3.0",
94
- "@storybook/react-vite": "^7.3.0",
95
- "@storybook/testing-library": "^0.2.0",
93
+ "@storybook/react": "^7.4.5",
94
+ "@storybook/react-vite": "^7.4.5",
95
+ "@storybook/testing-library": "^0.2.1",
96
96
  "@testing-library/jest-dom": "^6.1.2",
97
97
  "@testing-library/react": "^14.0.0",
98
98
  "@tsconfig/recommended": "^1.0.2",
@@ -109,7 +109,7 @@
109
109
  "chromatic": "^6.17.0",
110
110
  "conventional-changelog-conventionalcommits": "^5.0.0",
111
111
  "eslint": "^8.12.0",
112
- "eslint-plugin-storybook": "^0.6.13",
112
+ "eslint-plugin-storybook": "^0.6.14",
113
113
  "husky": "^5.1.1",
114
114
  "identity-obj-proxy": "^3.0.0",
115
115
  "jest": "^29.4.3",
@@ -123,7 +123,7 @@
123
123
  "react": "^18.2.0",
124
124
  "react-dom": "^18.2.0",
125
125
  "semantic-release": "^20.1.0",
126
- "storybook": "^7.3.0",
126
+ "storybook": "^7.4.5",
127
127
  "storybook-addon-designs": "beta",
128
128
  "ts-jest": "^29.0.5",
129
129
  "ts-node": "^10.9.1",
@@ -139,5 +139,5 @@
139
139
  "@types/react": "18.0.28",
140
140
  "react-router": "5.3.4"
141
141
  },
142
- "packageManager": "yarn@3.3.0"
142
+ "packageManager": "yarn@3.6.3"
143
143
  }