@homebound/beam 2.105.7 → 2.105.10

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.
@@ -48,6 +48,8 @@ export interface GridStyle {
48
48
  /** Default content to put into an empty cell */
49
49
  emptyCell?: ReactNode;
50
50
  presentationSettings?: Pick<PresentationFieldProps, "borderless" | "typeScale"> & Pick<PresentationContextProps, "wrap">;
51
+ /** Minimum table width in pixels. Used when calculating columns sizes */
52
+ minWidthPx?: number;
51
53
  }
52
54
  export declare type NestedCardStyleByKind = Record<string, NestedCardStyle>;
53
55
  export interface NestedCardsStyle {
@@ -164,6 +166,8 @@ export interface GridTableProps<R extends Kinded, S, X> {
164
166
  xss?: X;
165
167
  /** Experimental API allowing one to scroll to a table index. Primarily intended for stories at the moment */
166
168
  api?: MutableRefObject<GridTableApi | undefined>;
169
+ /** Experimental, expecting to be removed - Specify the element in which the table should resize its columns against. If not set, the table will resize columns based on its owns container's width */
170
+ resizeTarget?: MutableRefObject<HTMLElement | null>;
167
171
  }
168
172
  /** NOTE: This API is experimental and primarily intended for story and testing purposes */
169
173
  export declare type GridTableApi = {
@@ -190,7 +194,7 @@ export declare function GridTable<R extends Kinded, S = {}, X extends Only<GridT
190
194
  * Calculates column widths using a flexible `calc()` definition that allows for consistent column alignment without the use of `<table />`, CSS Grid, etc layouts.
191
195
  * Enforces only fixed-sized units (% and px)
192
196
  */
193
- export declare function calcColumnSizes(columns: GridColumn<any>[], firstLastColumnWidth: number | undefined): string[];
197
+ export declare function calcColumnSizes(columns: GridColumn<any>[], firstLastColumnWidth: number | undefined, tableWidth: number | undefined, tableMinWidthPx?: number): string[];
194
198
  /**
195
199
  * Given an ADT of type T, performs a look up and returns the type of kind K.
196
200
  *
@@ -24,6 +24,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.matchesFilter = exports.GridCollapseContext = exports.applyRowFn = exports.calcColumnSizes = exports.GridTable = exports.setGridTableDefaults = exports.setDefaultStyle = exports.setRunningInJest = exports.emptyCell = exports.DESC = exports.ASC = void 0;
26
26
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
27
+ const utils_1 = require("@react-aria/utils");
27
28
  const memoize_one_1 = __importDefault(require("memoize-one"));
28
29
  const mobx_react_1 = require("mobx-react");
29
30
  const react_1 = __importStar(require("react"));
@@ -39,6 +40,7 @@ const sortRows_1 = require("./sortRows");
39
40
  const useSortState_1 = require("./useSortState");
40
41
  const Css_1 = require("../../Css");
41
42
  const tinycolor2_1 = __importDefault(require("tinycolor2"));
43
+ const use_debounce_1 = require("use-debounce");
42
44
  const _1 = require(".");
43
45
  exports.ASC = "ASC";
44
46
  exports.DESC = "DESC";
@@ -81,10 +83,11 @@ exports.setGridTableDefaults = setGridTableDefaults;
81
83
  */
82
84
  function GridTable(props) {
83
85
  var _a, _b, _c, _d, _e;
84
- const { id = "gridTable", as = "div", columns, rows, style = defaults.style, rowStyles, stickyHeader = defaults.stickyHeader, stickyOffset = "0", xss, sorting, filter, filterMaxRows, fallbackMessage = "No rows found.", infoMessage, setRowCount, observeRows, persistCollapse, api, } = props;
86
+ const { id = "gridTable", as = "div", columns, rows, style = defaults.style, rowStyles, stickyHeader = defaults.stickyHeader, stickyOffset = "0", xss, sorting, filter, filterMaxRows, fallbackMessage = "No rows found.", infoMessage, setRowCount, observeRows, persistCollapse, api, resizeTarget, } = props;
85
87
  const [collapsedIds, collapseAllContext, collapseRowContext] = useToggleIds(rows, persistCollapse);
86
88
  // We only use this in as=virtual mode, but keep this here for rowLookup to use
87
89
  const virtuosoRef = (0, react_1.useRef)(null);
90
+ const tableRef = (0, react_1.useRef)(null);
88
91
  if (api) {
89
92
  api.current = {
90
93
  scrollToIndex: (index) => virtuosoRef.current && virtuosoRef.current.scrollToIndex(index),
@@ -98,7 +101,37 @@ function GridTable(props) {
98
101
  }
99
102
  return rows;
100
103
  }, [columns, rows, sorting, sortState]);
101
- const columnSizes = (0, react_1.useMemo)(() => { var _a; return calcColumnSizes(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth); }, [columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth]);
104
+ // Calculate the column sizes immediately rather than via the `debounce` method.
105
+ // We do this for Storybook integrations that may use MockDate. MockDate changes the behavior of `new Date()`, which is used by `useDebounce` and essentially turns off the callback.
106
+ const calculateImmediately = (0, react_1.useRef)(true);
107
+ const [tableWidth, setTableWidth] = (0, react_1.useState)();
108
+ // Calc our initial/first render sizes where we won't have a width yet
109
+ const [columnSizes, setColumnSizes] = (0, react_1.useState)(calcColumnSizes(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth, tableWidth, style.minWidthPx));
110
+ const setTableAndColumnWidths = (0, react_1.useCallback)((width) => {
111
+ var _a;
112
+ setTableWidth(width);
113
+ setColumnSizes(calcColumnSizes(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth, width, style.minWidthPx));
114
+ }, [setTableWidth, setColumnSizes, columns, style]);
115
+ const setTableAndColumnWidthsDebounced = (0, use_debounce_1.useDebouncedCallback)(setTableAndColumnWidths, 100);
116
+ const onResize = (0, react_1.useCallback)(() => {
117
+ const target = (resizeTarget === null || resizeTarget === void 0 ? void 0 : resizeTarget.current) ? resizeTarget.current : tableRef.current;
118
+ if (target && target.clientWidth !== tableWidth) {
119
+ if (calculateImmediately.current) {
120
+ calculateImmediately.current = false;
121
+ setTableAndColumnWidths(target.clientWidth);
122
+ }
123
+ else {
124
+ setTableAndColumnWidthsDebounced(target.clientWidth);
125
+ }
126
+ }
127
+ }, [
128
+ resizeTarget === null || resizeTarget === void 0 ? void 0 : resizeTarget.current,
129
+ tableRef.current,
130
+ setTableAndColumnWidths,
131
+ calculateImmediately,
132
+ setTableAndColumnWidthsDebounced,
133
+ ]);
134
+ (0, utils_1.useResizeObserver)({ ref: resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : tableRef, onResize });
102
135
  // Filter + flatten + component-ize the sorted rows.
103
136
  let [headerRows, filteredRows] = (0, react_1.useMemo)(() => {
104
137
  // Break up "foo bar" into `[foo, bar]` and a row must match both `foo` and `bar`
@@ -176,6 +209,7 @@ function GridTable(props) {
176
209
  collapseAllContext,
177
210
  collapseRowContext,
178
211
  observeRows,
212
+ columnSizes,
179
213
  ]);
180
214
  let tooManyClientSideRows = false;
181
215
  if (filterMaxRows && filteredRows.length > filterMaxRows) {
@@ -208,7 +242,7 @@ function GridTable(props) {
208
242
  // just trust the GridTable impl that, at runtime, `as=virtual` will (other than being virtualized)
209
243
  // behave semantically the same as `as=div` did for its tests.
210
244
  const _as = as === "virtual" && runningInJest ? "div" : as;
211
- return ((0, jsx_runtime_1.jsx)(PresentationContext_1.PresentationProvider, Object.assign({ fieldProps: fieldProps, wrap: (_d = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _d === void 0 ? void 0 : _d.wrap }, { children: renders[_as](style, id, columns, headerRows, filteredRows, firstRowMessage, stickyHeader, (_e = style.nestedCards) === null || _e === void 0 ? void 0 : _e.firstLastColumnWidth, xss, virtuosoRef) }), void 0));
245
+ return ((0, jsx_runtime_1.jsx)(PresentationContext_1.PresentationProvider, Object.assign({ fieldProps: fieldProps, wrap: (_d = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _d === void 0 ? void 0 : _d.wrap }, { children: renders[_as](style, id, columns, headerRows, filteredRows, firstRowMessage, stickyHeader, (_e = style.nestedCards) === null || _e === void 0 ? void 0 : _e.firstLastColumnWidth, xss, virtuosoRef, tableRef) }), void 0));
212
246
  }
213
247
  exports.GridTable = GridTable;
214
248
  // Determine which HTML element to use to build the GridTable
@@ -218,10 +252,8 @@ const renders = {
218
252
  virtual: renderVirtual,
219
253
  };
220
254
  /** Renders table using divs with flexbox rows, which is the default render */
221
- function renderDiv(style, id, columns, headerRows, filteredRows, firstRowMessage, _stickyHeader, firstLastColumnWidth, xss, _virtuosoRef) {
222
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: {
223
- // Ensure all rows extend the same width
224
- ...Css_1.Css.mw("fit-content").$,
255
+ function renderDiv(style, id, columns, headerRows, filteredRows, firstRowMessage, _stickyHeader, firstLastColumnWidth, xss, _virtuosoRef, tableRef) {
256
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: tableRef, css: {
225
257
  /*
226
258
  Using (n + 3) here to target all rows that are after the first non-header row. Since n starts at 0, we can use
227
259
  the + operator as an offset.
@@ -230,17 +262,19 @@ function renderDiv(style, id, columns, headerRows, filteredRows, firstRowMessage
230
262
  ...(style.betweenRowsCss ? Css_1.Css.addIn(`& > div:nth-of-type(n+3) > *`, style.betweenRowsCss).$ : {}),
231
263
  ...(style.firstNonHeaderRowCss ? Css_1.Css.addIn(`& > div:nth-of-type(2) > *`, style.firstNonHeaderRowCss).$ : {}),
232
264
  ...style.rootCss,
265
+ ...(style.minWidthPx ? Css_1.Css.mwPx(style.minWidthPx).$ : {}),
233
266
  ...xss,
234
267
  }, "data-testid": id }, { children: [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));
235
268
  }
236
269
  /** Renders as a table, primarily/solely for good print support. */
237
- function renderTable(style, id, columns, headerRows, filteredRows, firstRowMessage, _stickyHeader, _firstLastColumnWidth, xss, _virtuosoRef) {
238
- return ((0, jsx_runtime_1.jsxs)("table", Object.assign({ css: {
270
+ function renderTable(style, id, columns, headerRows, filteredRows, firstRowMessage, _stickyHeader, _firstLastColumnWidth, xss, _virtuosoRef, tableRef) {
271
+ return ((0, jsx_runtime_1.jsxs)("table", Object.assign({ ref: tableRef, css: {
239
272
  ...Css_1.Css.w100.add("borderCollapse", "collapse").$,
240
273
  ...Css_1.Css.addIn("& > tbody > tr ", style.betweenRowsCss || {})
241
274
  // removes border between header and second row
242
275
  .addIn("& > tbody > tr:first-of-type", style.firstNonHeaderRowCss || {}).$,
243
276
  ...style.rootCss,
277
+ ...(style.minWidthPx ? Css_1.Css.mwPx(style.minWidthPx).$ : {}),
244
278
  ...xss,
245
279
  }, "data-testid": id }, { children: [(0, jsx_runtime_1.jsx)("thead", { children: headerRows.map(([, node]) => node) }, void 0), (0, jsx_runtime_1.jsxs)("tbody", { children: [firstRowMessage && ((0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", Object.assign({ colSpan: columns.length, css: { ...style.firstRowMessageCss } }, { children: firstRowMessage }), void 0) }, void 0)), filteredRows.map(([, node]) => node)] }, void 0)] }), void 0));
246
280
  }
@@ -264,16 +298,19 @@ function renderTable(style, id, columns, headerRows, filteredRows, firstRowMessa
264
298
  * [2]: https://github.com/tannerlinsley/react-virtual/issues/85
265
299
  * [3]: https://github.com/tannerlinsley/react-virtual/issues/108
266
300
  */
267
- function renderVirtual(style, id, columns, headerRows, filteredRows, firstRowMessage, stickyHeader, firstLastColumnWidth, xss, virtuosoRef) {
301
+ function renderVirtual(style, id, columns, headerRows, filteredRows, firstRowMessage, stickyHeader, firstLastColumnWidth, xss, virtuosoRef, tableRef) {
268
302
  // eslint-disable-next-line react-hooks/rules-of-hooks
269
303
  const { footerStyle, listStyle } = (0, react_1.useMemo)(() => {
270
304
  var _a;
271
305
  const { paddingBottom, ...otherRootStyles } = (_a = style.rootCss) !== null && _a !== void 0 ? _a : {};
272
306
  return { footerStyle: { paddingBottom }, listStyle: { ...style, rootCss: otherRootStyles } };
273
307
  }, [style]);
274
- return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { overscan: 5, ref: virtuosoRef,
275
- // Add `minWidth: fit-content` to ensure a sticky header and the virtualized table body maintain same width
276
- style: { minWidth: "fit-content" }, components: {
308
+ return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { overscan: 5, ref: virtuosoRef, scrollerRef: (ref) => {
309
+ // This is fired multiple times per render. Only set `tableRef.current` if it has changed
310
+ if (ref && tableRef.current !== ref) {
311
+ tableRef.current = ref;
312
+ }
313
+ }, components: {
277
314
  List: VirtualRoot(listStyle, columns, id, firstLastColumnWidth, xss),
278
315
  Footer: () => (0, jsx_runtime_1.jsx)("div", { css: footerStyle }, void 0),
279
316
  },
@@ -330,6 +367,7 @@ const VirtualRoot = (0, memoize_one_1.default)((gs, _columns, id, _firstLastColu
330
367
  ...Css_1.Css.addIn("& > div:first-of-type > *", gs.firstNonHeaderRowCss).$,
331
368
  }),
332
369
  ...gs.rootCss,
370
+ ...(gs.minWidthPx ? Css_1.Css.mwPx(gs.minWidthPx).$ : {}),
333
371
  ...xss,
334
372
  }, "data-testid": id }, { children: children }), void 0));
335
373
  });
@@ -338,7 +376,7 @@ const VirtualRoot = (0, memoize_one_1.default)((gs, _columns, id, _firstLastColu
338
376
  * Calculates column widths using a flexible `calc()` definition that allows for consistent column alignment without the use of `<table />`, CSS Grid, etc layouts.
339
377
  * Enforces only fixed-sized units (% and px)
340
378
  */
341
- function calcColumnSizes(columns, firstLastColumnWidth) {
379
+ function calcColumnSizes(columns, firstLastColumnWidth, tableWidth, tableMinWidthPx = 0) {
342
380
  // For both default columns (1fr) as well as `w: 4fr` columns, we translate the width into an expression that looks like:
343
381
  // calc((100% - allOtherPercent - allOtherPx) * ((myFr / totalFr))`
344
382
  //
@@ -369,6 +407,14 @@ function calcColumnSizes(columns, firstLastColumnWidth) {
369
407
  }, { claimedPercentages: 0, claimedPixels: 0, totalFr: 0 });
370
408
  // This is our "fake but for some reason it lines up better" fr calc
371
409
  function fr(myFr) {
410
+ // If the tableWidth, then return a pixel value
411
+ if (tableWidth) {
412
+ const widthBasis = Math.max(tableWidth, tableMinWidthPx);
413
+ // When the tableWidth is defined, then we need to account for the `firstLastColumnWidth`s.
414
+ return `(${(widthBasis - (claimedPercentages / 100) * widthBasis - claimedPixels - (firstLastColumnWidth !== null && firstLastColumnWidth !== void 0 ? firstLastColumnWidth : 0) * 2) *
415
+ (myFr / totalFr)}px)`;
416
+ }
417
+ // Otherwise return the `calc()` value
372
418
  return `((100% - ${claimedPercentages}% - ${claimedPixels}px) * (${myFr} / ${totalFr}))`;
373
419
  }
374
420
  let sizes = columns.map(({ w }) => {
@@ -390,13 +436,10 @@ function calcColumnSizes(columns, firstLastColumnWidth) {
390
436
  return fr(w);
391
437
  }
392
438
  });
393
- return maybeAddCardColumns(sizes, firstLastColumnWidth);
394
- }
395
- exports.calcColumnSizes = calcColumnSizes;
396
- // If we're doing nested cards, we add extra 1st/last cells...
397
- function maybeAddCardColumns(sizes, firstLastColumnWidth) {
439
+ // If we're doing nested cards, we add extra 1st/last cells...
398
440
  return !firstLastColumnWidth ? sizes : [`${firstLastColumnWidth}px`, ...sizes, `${firstLastColumnWidth}px`];
399
441
  }
442
+ exports.calcColumnSizes = calcColumnSizes;
400
443
  function getIndentationCss(style, rowStyle, columnIndex, maybeContent) {
401
444
  // Look for cell-specific indent or row-specific indent (row-specific is only one the first column)
402
445
  const indent = (isGridCellContent(maybeContent) && maybeContent.indent) || (columnIndex === 0 && (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.indent));
@@ -484,12 +527,12 @@ function GridRow(props) {
484
527
  // Add any cell specific style overrides
485
528
  ...(isGridCellContent(maybeContent) && maybeContent.typeScale ? Css_1.Css[maybeContent.typeScale].$ : {}),
486
529
  // Define the width of the column on each cell. Supports col spans.
487
- ...(columnSizes && {
530
+ ...{
488
531
  width: `calc(${columnSizes
489
532
  .slice(maybeNestedCardColumnIndex, maybeNestedCardColumnIndex + currentColspan)
490
533
  .join(" + ")})`,
491
- ...(column.mw ? Css_1.Css.mw(column.mw).$ : {}),
492
- }),
534
+ },
535
+ ...(column.mw ? Css_1.Css.mw(column.mw).$ : {}),
493
536
  };
494
537
  const renderFn = (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.renderCell) || (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowLink)
495
538
  ? rowLinkRenderFn(as)
@@ -97,9 +97,8 @@ export declare function getNestedCardStyles(row: GridDataRow<any>, openCardStyle
97
97
  export declare function makeSpacer(height: number, openCards: string[], styles: NestedCardsStyle): Chrome;
98
98
  interface ChromeRowProps {
99
99
  chromeBuffer: ChromeBuffer;
100
- columns: number;
101
100
  }
102
- export declare function ChromeRow({ chromeBuffer, columns }: ChromeRowProps): import("@emotion/react/jsx-runtime").JSX.Element;
101
+ export declare function ChromeRow({ chromeBuffer }: ChromeRowProps): import("@emotion/react/jsx-runtime").JSX.Element;
103
102
  export declare function dropChromeRows<R extends Kinded>(rows: RowTuple<R>[]): [GridDataRow<R>, ReactElement][];
104
103
  export declare function isLeafRow<R extends Kinded>(row: GridDataRow<R>): boolean;
105
104
  export {};
@@ -82,10 +82,7 @@ class NestedCards {
82
82
  */
83
83
  maybeCreateChromeRow() {
84
84
  if (this.chromeBuffer.length > 0) {
85
- this.rows.push([
86
- undefined,
87
- (0, jsx_runtime_1.jsx)(ChromeRow, { chromeBuffer: [...this.chromeBuffer], columns: this.columns.length }, this.chromeRowIndex++),
88
- ]);
85
+ this.rows.push([undefined, (0, jsx_runtime_1.jsx)(ChromeRow, { chromeBuffer: [...this.chromeBuffer] }, this.chromeRowIndex++)]);
89
86
  // clear the Chrome buffer
90
87
  this.chromeBuffer.splice(0, this.chromeBuffer.length);
91
88
  }
@@ -201,10 +198,8 @@ function makeSpacer(height, openCards, styles) {
201
198
  };
202
199
  }
203
200
  exports.makeSpacer = makeSpacer;
204
- function ChromeRow({ chromeBuffer, columns }) {
205
- return (
206
- // We add 2 to account for our dedicated open/close columns
207
- (0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.gc(`span ${columns + 2}`).$ }, { children: chromeBuffer.map((c, i) => ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: c() }, i))) }), void 0));
201
+ function ChromeRow({ chromeBuffer }) {
202
+ return ((0, jsx_runtime_1.jsx)("div", { children: chromeBuffer.map((c, i) => ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: c() }, i))) }, void 0));
208
203
  }
209
204
  exports.ChromeRow = ChromeRow;
210
205
  function dropChromeRows(rows) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.105.7",
3
+ "version": "2.105.10",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -53,7 +53,8 @@
53
53
  "tinycolor2": "^1.4.2",
54
54
  "tributejs": "^5.1.3",
55
55
  "trix": "^1.3.1",
56
- "use-query-params": "^1.2.2"
56
+ "use-query-params": "^1.2.2",
57
+ "use-debounce": "^7.0.1"
57
58
  },
58
59
  "peerDependencies": {
59
60
  "@emotion/react": ">=11",
@@ -80,6 +81,7 @@
80
81
  "@homebound/rtl-react-router-utils": "^1.0.3",
81
82
  "@homebound/rtl-utils": "^2.51.0",
82
83
  "@homebound/tsconfig": "^1.0.3",
84
+ "@semantic-release/exec": "^6.0.3",
83
85
  "@semantic-release/git": "^9.0.0",
84
86
  "@storybook/addon-essentials": "^6.4.9",
85
87
  "@storybook/addon-interactions": "^6.4.9",