@homebound/beam 2.132.4 → 2.134.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.
@@ -45,6 +45,15 @@ const ourReset = (0, react_1.css) `
45
45
  background-color: ${Css_1.Palette.Gray500};
46
46
  }
47
47
  }
48
+
49
+ @keyframes spin {
50
+ 0% {
51
+ transform: rotate(0deg);
52
+ }
53
+ 100% {
54
+ transform: rotate(360deg);
55
+ }
56
+ }
48
57
  `;
49
58
  // Copy/pasted from TW which uses this as their base reset.
50
59
  const modernNormalizeReset = (0, react_1.css) `
@@ -0,0 +1,6 @@
1
+ interface LoaderProps {
2
+ size?: "sm" | "md" | "lg";
3
+ contrast?: boolean;
4
+ }
5
+ export declare function Loader({ size, contrast }: LoaderProps): import("@emotion/react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Loader = void 0;
4
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
+ const Css_1 = require("../Css");
6
+ function Loader({ size = "lg", contrast = false }) {
7
+ const [dimensions, borderSize] = sizeToPixels[size];
8
+ const [bgColor, spinnerColor] = contrast ? [Css_1.Palette.Gray600, Css_1.Palette.Gray200] : [Css_1.Palette.White, Css_1.Palette.LightBlue700];
9
+ return ((0, jsx_runtime_1.jsx)("div", { "aria-label": "Loading", css: Css_1.Css.br100.ba
10
+ .hPx(dimensions)
11
+ .wPx(dimensions)
12
+ .bc(bgColor)
13
+ .bw(`${borderSize}px`)
14
+ .add("borderTopColor", spinnerColor)
15
+ .add("textIndent", "-999px")
16
+ .add("animationName", "spin")
17
+ .add("animationDuration", "800ms")
18
+ .add("animationIterationCount", "infinite")
19
+ .add("animationTimingFunction", "linear")
20
+ .add("transform", "translateZ(0)").$ }, void 0));
21
+ }
22
+ exports.Loader = Loader;
23
+ const sizeToPixels = {
24
+ sm: [32, 4],
25
+ md: [64, 8],
26
+ lg: [96, 12],
27
+ };
@@ -92,7 +92,8 @@ function GridTable(props) {
92
92
  const { id = "gridTable", as = "div", columns, rows, style: maybeStyle = defaults.style, rowStyles, stickyHeader = defaults.stickyHeader, stickyOffset = 0, xss, filter, filterMaxRows, fallbackMessage = "No rows found.", infoMessage, setRowCount, observeRows, persistCollapse, resizeTarget, activeRowId, } = props;
93
93
  // We only use this in as=virtual mode, but keep this here for rowLookup to use
94
94
  const virtuosoRef = (0, react_1.useRef)(null);
95
- const tableRef = (0, react_1.useRef)(null);
95
+ // Use this ref to watch for changes in the GridTable's container and resize columns accordingly.
96
+ const resizeRef = (0, react_1.useRef)(null);
96
97
  const api = (0, react_1.useMemo)(() => {
97
98
  var _a;
98
99
  const api = (_a = props.api) !== null && _a !== void 0 ? _a : new GridTableApi_1.GridTableApiImpl();
@@ -111,7 +112,7 @@ function GridTable(props) {
111
112
  // (or us) is resetting component state more than necessary, so we track render counts from
112
113
  // here instead.
113
114
  const { getCount } = (0, useRenderCount_1.useRenderCount)();
114
- const columnSizes = (0, columnSizes_1.useSetupColumnSizes)(style, columns, tableRef, resizeTarget);
115
+ const columnSizes = (0, columnSizes_1.useSetupColumnSizes)(style, columns, resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : resizeRef);
115
116
  // Make a single copy of our current collapsed state, so we'll have a single observer.
116
117
  const collapsedIds = (0, hooks_1.useComputed)(() => rowState.collapsedIds, [rowState]);
117
118
  const [sortState, setSortKey, sortOn, caseSensitive] = (0, useSortState_1.useSortState)(columns, props.sorting);
@@ -122,7 +123,7 @@ function GridTable(props) {
122
123
  }
123
124
  return rows;
124
125
  }, [columns, rows, sortOn, sortState, caseSensitive]);
125
- let hasTotalsRow = false;
126
+ const hasTotalsRow = rows.some((row) => row.id === "totals");
126
127
  // Filter rows - ensures parent rows remain in the list if any children match the filter.
127
128
  const filterRows = (0, react_1.useCallback)((acc, row) => {
128
129
  var _a, _b, _c;
@@ -133,7 +134,6 @@ function GridTable(props) {
133
134
  filters.length === 0 ||
134
135
  !!row.pin ||
135
136
  filters.every((f) => columns.map((c) => applyRowFn(c, row, api, 0)).some((maybeContent) => matchesFilter(maybeContent, f)));
136
- hasTotalsRow || (hasTotalsRow = row.kind === "totals");
137
137
  // If the row matches, add it in
138
138
  if (matches) {
139
139
  return acc.concat([[row, (_b = (_a = row.children) === null || _a === void 0 ? void 0 : _a.reduce(filterRows, [])) !== null && _b !== void 0 ? _b : []]]);
@@ -227,6 +227,7 @@ function GridTable(props) {
227
227
  columnSizes,
228
228
  collapsedIds,
229
229
  getCount,
230
+ hasTotalsRow,
230
231
  ]);
231
232
  let tooManyClientSideRows = false;
232
233
  if (filterMaxRows && filteredRows.length > filterMaxRows) {
@@ -262,7 +263,7 @@ function GridTable(props) {
262
263
  // behave semantically the same as `as=div` did for its tests.
263
264
  const _as = as === "virtual" && runningInJest ? "div" : as;
264
265
  const rowStateContext = (0, react_1.useMemo)(() => ({ rowState }), [rowState]);
265
- return ((0, jsx_runtime_1.jsx)(RowState_1.RowStateContext.Provider, Object.assign({ value: rowStateContext }, { children: (0, jsx_runtime_1.jsx)(PresentationContext_1.PresentationProvider, Object.assign({ fieldProps: fieldProps, wrap: (_c = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _c === void 0 ? void 0 : _c.wrap }, { children: renders[_as](style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, stickyHeader, (_d = style.nestedCards) === null || _d === void 0 ? void 0 : _d.firstLastColumnWidth, xss, virtuosoRef, tableRef) }), void 0) }), void 0));
266
+ return ((0, jsx_runtime_1.jsx)(RowState_1.RowStateContext.Provider, Object.assign({ value: rowStateContext }, { children: (0, jsx_runtime_1.jsxs)(PresentationContext_1.PresentationProvider, Object.assign({ fieldProps: fieldProps, wrap: (_c = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _c === void 0 ? void 0 : _c.wrap }, { children: [(0, jsx_runtime_1.jsx)("div", { ref: resizeRef, css: Css_1.Css.w100.$ }, void 0), renders[_as](style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, stickyHeader, (_d = style.nestedCards) === null || _d === void 0 ? void 0 : _d.firstLastColumnWidth, xss, virtuosoRef)] }), void 0) }), void 0));
266
267
  }
267
268
  exports.GridTable = GridTable;
268
269
  // Determine which HTML element to use to build the GridTable
@@ -272,8 +273,8 @@ const renders = {
272
273
  virtual: renderVirtual,
273
274
  };
274
275
  /** Renders table using divs with flexbox rows, which is the default render */
275
- function renderDiv(style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, _stickyHeader, firstLastColumnWidth, xss, _virtuosoRef, tableRef) {
276
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: tableRef, css: {
276
+ function renderDiv(style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, _stickyHeader, firstLastColumnWidth, xss, _virtuosoRef) {
277
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: {
277
278
  // Use `fit-content` to ensure the width of the table takes up the full width of its content.
278
279
  // Otherwise, the table's width would be that of its container, which may not be as wide as the table itself.
279
280
  // In cases where we have sticky columns on a very wide table, then the container which the columns "stick" to (which is the table),
@@ -292,8 +293,8 @@ function renderDiv(style, id, columns, headerRows, totalsRows, filteredRows, fir
292
293
  }, "data-testid": id }, { children: [totalsRows.map(([, node]) => node), headerRows.map(([, node]) => node), firstRowMessage && ((0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...style.firstRowMessageCss }, "data-gridrow": true }, { children: firstRowMessage }), void 0)), filteredRows.map(([, node]) => node)] }), void 0));
293
294
  }
294
295
  /** Renders as a table, primarily/solely for good print support. */
295
- function renderTable(style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, _stickyHeader, _firstLastColumnWidth, xss, _virtuosoRef, tableRef) {
296
- return ((0, jsx_runtime_1.jsxs)("table", Object.assign({ ref: tableRef, css: {
296
+ function renderTable(style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, _stickyHeader, _firstLastColumnWidth, xss, _virtuosoRef) {
297
+ return ((0, jsx_runtime_1.jsxs)("table", Object.assign({ css: {
297
298
  ...Css_1.Css.w100.add("borderCollapse", "collapse").$,
298
299
  ...Css_1.Css.addIn("& > tbody > tr ", style.betweenRowsCss || {})
299
300
  // removes border between header and second row
@@ -323,19 +324,14 @@ function renderTable(style, id, columns, headerRows, totalsRows, filteredRows, f
323
324
  * [2]: https://github.com/tannerlinsley/react-virtual/issues/85
324
325
  * [3]: https://github.com/tannerlinsley/react-virtual/issues/108
325
326
  */
326
- function renderVirtual(style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, stickyHeader, firstLastColumnWidth, xss, virtuosoRef, tableRef) {
327
+ function renderVirtual(style, id, columns, headerRows, totalsRows, filteredRows, firstRowMessage, stickyHeader, firstLastColumnWidth, xss, virtuosoRef) {
327
328
  // eslint-disable-next-line react-hooks/rules-of-hooks
328
329
  const { footerStyle, listStyle } = (0, react_1.useMemo)(() => {
329
330
  var _a;
330
331
  const { paddingBottom, ...otherRootStyles } = (_a = style.rootCss) !== null && _a !== void 0 ? _a : {};
331
332
  return { footerStyle: { paddingBottom }, listStyle: { ...style, rootCss: otherRootStyles } };
332
333
  }, [style]);
333
- return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { overscan: 5, ref: virtuosoRef, scrollerRef: (ref) => {
334
- // This is fired multiple times per render. Only set `tableRef.current` if it has changed
335
- if (ref && tableRef.current !== ref) {
336
- tableRef.current = ref;
337
- }
338
- }, components: {
334
+ return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { overscan: 5, ref: virtuosoRef, components: {
339
335
  // Applying a zIndex: 2 to ensure it stays on top of sticky columns
340
336
  TopItemList: react_1.default.forwardRef((props, ref) => ((0, jsx_runtime_1.jsx)("div", Object.assign({}, props, { ref: ref, style: { ...props.style, ...{ zIndex: 2 } } }), void 0))),
341
337
  List: VirtualRoot(listStyle, columns, id, firstLastColumnWidth, xss),
@@ -19,4 +19,4 @@ import { GridColumn, GridStyle } from "./GridTable";
19
19
  *
20
20
  * Disclaimer that we roll our own `fr` b/c we're not in CSS grid anymore.
21
21
  */
22
- export declare function useSetupColumnSizes(style: GridStyle, columns: GridColumn<any>[], tableRef: MutableRefObject<HTMLElement | null>, resizeTarget: MutableRefObject<HTMLElement | null> | undefined): string[];
22
+ export declare function useSetupColumnSizes(style: GridStyle, columns: GridColumn<any>[], resizeRef: MutableRefObject<HTMLElement | null>): string[];
@@ -24,8 +24,8 @@ const use_debounce_1 = require("use-debounce");
24
24
  *
25
25
  * Disclaimer that we roll our own `fr` b/c we're not in CSS grid anymore.
26
26
  */
27
- function useSetupColumnSizes(style, columns, tableRef, resizeTarget) {
28
- var _a, _b;
27
+ function useSetupColumnSizes(style, columns, resizeRef) {
28
+ var _a;
29
29
  // Calculate the column sizes immediately rather than via the `debounce` method.
30
30
  // We do this for Storybook integrations that may use MockDate. MockDate changes the behavior of `new Date()`,
31
31
  // which is used internally by `useDebounce`, so the frozen clock means the callback is never called.
@@ -41,8 +41,8 @@ function useSetupColumnSizes(style, columns, tableRef, resizeTarget) {
41
41
  setColumnSizes((0, GridTable_1.calcColumnSizes)(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth, width, style.minWidthPx));
42
42
  }, [setTableWidth, setColumnSizes, columns, style]);
43
43
  const setTableAndColumnWidthsDebounced = (0, use_debounce_1.useDebouncedCallback)(setTableAndColumnWidths, 100);
44
- const target = (_b = resizeTarget === null || resizeTarget === void 0 ? void 0 : resizeTarget.current) !== null && _b !== void 0 ? _b : tableRef.current;
45
44
  const onResize = (0, react_1.useCallback)(() => {
45
+ const target = resizeRef.current;
46
46
  if (target && target.clientWidth !== tableWidth) {
47
47
  if (calculateImmediately.current) {
48
48
  calculateImmediately.current = false;
@@ -52,8 +52,8 @@ function useSetupColumnSizes(style, columns, tableRef, resizeTarget) {
52
52
  setTableAndColumnWidthsDebounced(target.clientWidth);
53
53
  }
54
54
  }
55
- }, [target, tableWidth, setTableAndColumnWidths, setTableAndColumnWidthsDebounced]);
56
- (0, utils_1.useResizeObserver)({ ref: resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : tableRef, onResize });
55
+ }, [tableWidth, setTableAndColumnWidths, setTableAndColumnWidthsDebounced]);
56
+ (0, utils_1.useResizeObserver)({ ref: resizeRef, onResize });
57
57
  return columnSizes;
58
58
  }
59
59
  exports.useSetupColumnSizes = useSetupColumnSizes;
@@ -15,6 +15,7 @@ export * from "./Filters";
15
15
  export * from "./Icon";
16
16
  export * from "./IconButton";
17
17
  export * from "./Layout";
18
+ export * from "./Loader";
18
19
  export * from "./Modal";
19
20
  export * from "./Modal/useModal";
20
21
  export { NavLink } from "./NavLink";
@@ -29,6 +29,7 @@ __exportStar(require("./Filters"), exports);
29
29
  __exportStar(require("./Icon"), exports);
30
30
  __exportStar(require("./IconButton"), exports);
31
31
  __exportStar(require("./Layout"), exports);
32
+ __exportStar(require("./Loader"), exports);
32
33
  __exportStar(require("./Modal"), exports);
33
34
  __exportStar(require("./Modal/useModal"), exports);
34
35
  var NavLink_1 = require("./NavLink");
@@ -6,5 +6,6 @@ export declare type BoundCheckboxGroupFieldProps = Omit<CheckboxGroupProps, "val
6
6
  onChange?: (values: string[]) => void;
7
7
  label?: string;
8
8
  };
9
- /** Wraps `TextField` and binds it to a form field. */
9
+ /** Wraps `CheckboxGroup` and binds it to a form field.
10
+ * To make the field agnostic to the order of selected values, add `strictOrder: false` to the field's ObjectConfig */
10
11
  export declare function BoundCheckboxGroupField(props: BoundCheckboxGroupFieldProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -6,7 +6,8 @@ const mobx_react_1 = require("mobx-react");
6
6
  const inputs_1 = require("../inputs");
7
7
  const utils_1 = require("../utils");
8
8
  const defaultLabel_1 = require("../utils/defaultLabel");
9
- /** Wraps `TextField` and binds it to a form field. */
9
+ /** Wraps `CheckboxGroup` and binds it to a form field.
10
+ * To make the field agnostic to the order of selected values, add `strictOrder: false` to the field's ObjectConfig */
10
11
  function BoundCheckboxGroupField(props) {
11
12
  const { field, onChange = (value) => field.set(value), label = (0, defaultLabel_1.defaultLabel)(field.key), onBlur, onFocus, ...others } = props;
12
13
  const testId = (0, utils_1.useTestIds)(props, field.key);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.132.4",
3
+ "version": "2.134.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  "format": "prettier --loglevel warn --write \"**/*.{ts,tsx,css,md}\""
33
33
  },
34
34
  "dependencies": {
35
- "@homebound/form-state": "2.13.0",
35
+ "@homebound/form-state": "2.14.0",
36
36
  "@internationalized/number": "^3.0.3",
37
37
  "@react-aria/utils": "^3.11.3",
38
38
  "@react-hook/resize-observer": "^1.2.2",