@homebound/beam 2.100.0 → 2.101.3

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.
@@ -185,18 +185,10 @@ export declare type GridTableApi = {
185
185
  */
186
186
  export declare function GridTable<R extends Kinded, S = {}, X extends Only<GridTableXss, X> = {}>(props: GridTableProps<R, S, X>): import("@emotion/react/jsx-runtime").JSX.Element;
187
187
  /**
188
- * Creates a `grid-template-column` specific to our virtual output.
189
- *
190
- * Because of two things:
191
- *
192
- * a) react-virtuoso puts the header in a different div than the normal rows, and
193
- *
194
- * b) content-aware sizing just in general look janky/constantly resize while scrolling
195
- *
196
- * When we're as=virtual, we change our default + enforce only fixed-sized units (% and px)
188
+ * Calculates column widths using a flexible `calc()` definition that allows for consistent column alignment without the use of `<table />`, CSS Grid, etc layouts.
189
+ * Enforces only fixed-sized units (% and px)
197
190
  */
198
- export declare function calcVirtualGridColumns(columns: GridColumn<any>[], firstLastColumnWidth: number | undefined): string[];
199
- export declare function calcDivGridColumns(columns: GridColumn<any>[], firstLastColumnWidth: number | undefined): string;
191
+ export declare function calcColumnSizes(columns: GridColumn<any>[], firstLastColumnWidth: number | undefined): string[];
200
192
  /**
201
193
  * Given an ADT of type T, performs a look up and returns the type of kind K.
202
194
  *
@@ -225,21 +217,8 @@ export declare type GridColumn<R extends Kinded, S = {}> = {
225
217
  } ? (data: D, row: GridRowKind<R, K>) => ReactNode | GridCellContent : (row: GridRowKind<R, K>) => ReactNode | GridCellContent);
226
218
  } & {
227
219
  /**
228
- * The column's grid column width.
229
- *
230
- * For `as=div` output:
231
- *
232
- * - Any CSS grid units are supported
233
- * - Numbers are treated as `fr` units
234
- * - The default value is `auto`, which in CSS grid will do content-aware/responsive layout.
235
- *
236
- * For `as=virtual` output:
237
- *
238
- * - Only px, percentage, or fr units are supported, due to a) react-virtuoso puts the sticky header
239
- * rows in a separate `div` and so we end up with two `grid-template-columns`, so cannot rely on
240
- * any content-aware sizing, and b) content-aware sizing in a scrolling/virtual table results in
241
- * a ~janky experience as the columns will constantly resize as new/different content is put in/out
242
- * of the DOM.
220
+ * The column's width.
221
+ * - Only px, percentage, or fr units are supported, due to each GridRow acting as an independent table. This ensures consistent alignment between rows.
243
222
  * - Numbers are treated as `fr` units
244
223
  * - The default value is `1fr`
245
224
  */
@@ -277,7 +256,7 @@ export declare type GridCellAlignment = "left" | "right" | "center";
277
256
  * primitive value for filtering and sorting.
278
257
  */
279
258
  export declare type GridCellContent = {
280
- /** The JSX content of the cell. Virtual tables that client-side sort should use a function to avaid perf overhead. */
259
+ /** The JSX content of the cell. Virtual tables that client-side sort should use a function to avoid perf overhead. */
281
260
  content: ReactNode | (() => ReactNode);
282
261
  alignment?: GridCellAlignment;
283
262
  /** Allow value to be a function in case it's a dynamic value i.e. reading from an inline-edited proxy. */
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.matchesFilter = exports.GridCollapseContext = exports.applyRowFn = exports.calcDivGridColumns = exports.calcVirtualGridColumns = exports.GridTable = exports.setGridTableDefaults = exports.setDefaultStyle = exports.setRunningInJest = exports.emptyCell = exports.DESC = exports.ASC = void 0;
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
27
  const memoize_one_1 = __importDefault(require("memoize-one"));
28
28
  const mobx_react_1 = require("mobx-react");
@@ -104,7 +104,7 @@ function GridTable(props) {
104
104
  var _a;
105
105
  // Break up "foo bar" into `[foo, bar]` and a row must match both `foo` and `bar`
106
106
  const filters = (filter && filter.split(/ +/)) || [];
107
- const columnSizes = as === "virtual" ? calcVirtualGridColumns(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth) : undefined;
107
+ const columnSizes = calcColumnSizes(columns, (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.firstLastColumnWidth);
108
108
  function makeRowComponent(row) {
109
109
  // We only pass sortState to header rows, b/c non-headers rows shouldn't have to re-render on sorting
110
110
  // changes, and so by not passing the sortProps, it means the data rows' React.memo will still cache them.
@@ -217,11 +217,11 @@ exports.GridTable = GridTable;
217
217
  // Determine which HTML element to use to build the GridTable
218
218
  const renders = {
219
219
  table: renderTable,
220
- div: renderCssGrid,
220
+ div: renderDiv,
221
221
  virtual: renderVirtual,
222
222
  };
223
- /** Renders as a CSS Grid, which is the default / most well-supported rendered. */
224
- function renderCssGrid(style, id, columns, headerRows, filteredRows, firstRowMessage, _stickyHeader, firstLastColumnWidth, xss, _virtuosoRef) {
223
+ /** Renders table using divs with flexbox rows, which is the default render */
224
+ function renderDiv(style, id, columns, headerRows, filteredRows, firstRowMessage, _stickyHeader, firstLastColumnWidth, xss, _virtuosoRef) {
225
225
  var _a;
226
226
  // We must determine if the header is using nested card styles to account for
227
227
  // the opening and closing Chrome rows.
@@ -247,7 +247,8 @@ function renderCssGrid(style, id, columns, headerRows, filteredRows, firstRowMes
247
247
  */
248
248
  const firstNonHeaderRowIndex = (!isNestedCardStyleHeader ? 1 : 3) + 1;
249
249
  return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: {
250
- ...Css_1.Css.dg.gtc(calcDivGridColumns(columns, firstLastColumnWidth)).$,
250
+ // Ensure all rows extend the same width
251
+ ...Css_1.Css.mw("fit-content").$,
251
252
  /*
252
253
  Using n + (firstNonHeaderRowIndex + 1) here to target all rows that
253
254
  are after the first non-header row. Since n starts at 0, we can use
@@ -263,7 +264,7 @@ function renderCssGrid(style, id, columns, headerRows, filteredRows, firstRowMes
263
264
  : {}),
264
265
  ...style.rootCss,
265
266
  ...xss,
266
- }, "data-testid": id }, { children: [headerRows.map(([, node]) => node), firstRowMessage && ((0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.add("gridColumn", `${columns.length} span`).$ }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...style.firstRowMessageCss } }, { children: firstRowMessage }), void 0) }), void 0)), filteredRows.map(([, node]) => node)] }), void 0));
267
+ }, "data-testid": id }, { children: [headerRows.map(([, node]) => node), firstRowMessage && (0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...style.firstRowMessageCss } }, { children: firstRowMessage }), void 0), filteredRows.map(([, node]) => node)] }), void 0));
267
268
  }
268
269
  /** Renders as a table, primarily/solely for good print support. */
269
270
  function renderTable(style, id, columns, headerRows, filteredRows, firstRowMessage, _stickyHeader, _firstLastColumnWidth, xss, _virtuosoRef) {
@@ -303,7 +304,9 @@ function renderVirtual(style, id, columns, headerRows, filteredRows, firstRowMes
303
304
  const { paddingBottom, ...otherRootStyles } = (_a = style.rootCss) !== null && _a !== void 0 ? _a : {};
304
305
  return { footerStyle: { paddingBottom }, listStyle: { ...style, rootCss: otherRootStyles } };
305
306
  }, [style]);
306
- return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { overscan: 5, ref: virtuosoRef, components: {
307
+ return ((0, jsx_runtime_1.jsx)(react_virtuoso_1.Virtuoso, { overscan: 5, ref: virtuosoRef,
308
+ // Add `minWidth: fit-content` to ensure a sticky header and the virtualized table body maintain same width
309
+ style: { minWidth: "fit-content" }, components: {
307
310
  List: VirtualRoot(listStyle, columns, id, firstLastColumnWidth, xss),
308
311
  Footer: () => (0, jsx_runtime_1.jsx)("div", { css: footerStyle }, void 0),
309
312
  },
@@ -346,7 +349,7 @@ function renderVirtual(style, id, columns, headerRows, filteredRows, firstRowMes
346
349
  * rows and the second represents the non-header rows (list rows).
347
350
  *
348
351
  * The main goal of this custom component is to:
349
- * - Customize the list wrapper to our css grid logic styles
352
+ * - Customize the list wrapper to our styles
350
353
  *
351
354
  * We wrap this in memoizeOne so that React.createElement sees a
352
355
  * consistent/stable component identity, even though technically we have a
@@ -359,7 +362,7 @@ const VirtualRoot = (0, memoize_one_1.default)((gs, _columns, id, _firstLastColu
359
362
  // table list generally has styles to scroll the page for windowing.
360
363
  const isHeader = Object.keys(style || {}).length === 0;
361
364
  // This re-renders each time we have new children in the viewport
362
- return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, style: { ...style, ...(gs.nestedCards ? { minWidth: "fit-content" } : {}) }, css: {
365
+ return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, style: { ...style, ...{ minWidth: "fit-content" } }, css: {
363
366
  // Add an extra `> div` due to Item + itemContent both having divs
364
367
  ...Css_1.Css.addIn("& > div + div > div > *", gs.betweenRowsCss || {}).$,
365
368
  // Table list styles only
@@ -374,17 +377,10 @@ const VirtualRoot = (0, memoize_one_1.default)((gs, _columns, id, _firstLastColu
374
377
  });
375
378
  });
376
379
  /**
377
- * Creates a `grid-template-column` specific to our virtual output.
378
- *
379
- * Because of two things:
380
- *
381
- * a) react-virtuoso puts the header in a different div than the normal rows, and
382
- *
383
- * b) content-aware sizing just in general look janky/constantly resize while scrolling
384
- *
385
- * When we're as=virtual, we change our default + enforce only fixed-sized units (% and px)
380
+ * Calculates column widths using a flexible `calc()` definition that allows for consistent column alignment without the use of `<table />`, CSS Grid, etc layouts.
381
+ * Enforces only fixed-sized units (% and px)
386
382
  */
387
- function calcVirtualGridColumns(columns, firstLastColumnWidth) {
383
+ function calcColumnSizes(columns, firstLastColumnWidth) {
388
384
  // For both default columns (1fr) as well as `w: 4fr` columns, we translate the width into an expression that looks like:
389
385
  // calc((100% - allOtherPercent - allOtherPx) * ((myFr / totalFr))`
390
386
  //
@@ -410,7 +406,7 @@ function calcVirtualGridColumns(columns, firstLastColumnWidth) {
410
406
  return { ...acc, claimedPercentages: acc.claimedPercentages + Number(w.replace("%", "")) };
411
407
  }
412
408
  else {
413
- throw new Error("as=virtual only supports px, percentage, or fr units");
409
+ throw new Error("Beam Table column width definition only supports px, percentage, or fr units");
414
410
  }
415
411
  }, { claimedPercentages: 0, claimedPixels: firstLastColumnWidth ? firstLastColumnWidth * 2 : 0, totalFr: 0 });
416
412
  // This is our "fake but for some reason it lines up better" fr calc
@@ -429,7 +425,7 @@ function calcVirtualGridColumns(columns, firstLastColumnWidth) {
429
425
  return fr(Number(w.replace("fr", "")));
430
426
  }
431
427
  else {
432
- throw new Error("as=virtual only supports px, percentage, or fr units");
428
+ throw new Error("Beam Table column width definition only supports px, percentage, or fr units");
433
429
  }
434
430
  }
435
431
  else {
@@ -438,25 +434,7 @@ function calcVirtualGridColumns(columns, firstLastColumnWidth) {
438
434
  });
439
435
  return maybeAddCardColumns(sizes, firstLastColumnWidth);
440
436
  }
441
- exports.calcVirtualGridColumns = calcVirtualGridColumns;
442
- function calcDivGridColumns(columns, firstLastColumnWidth) {
443
- const sizes = columns.map(({ w }) => {
444
- if (typeof w === "undefined") {
445
- // Hrm, I waffle between 'auto' or '1fr' being the better default here...
446
- return "auto";
447
- }
448
- else if (typeof w === "string") {
449
- // Use whatever the user passed in
450
- return w;
451
- }
452
- else {
453
- // Otherwise assume fr units
454
- return `${w}fr`;
455
- }
456
- });
457
- return maybeAddCardColumns(sizes, firstLastColumnWidth).join(" ");
458
- }
459
- exports.calcDivGridColumns = calcDivGridColumns;
437
+ exports.calcColumnSizes = calcColumnSizes;
460
438
  // If we're doing nested cards, we add extra 1st/last cells...
461
439
  function maybeAddCardColumns(sizes, firstLastColumnWidth) {
462
440
  return !firstLastColumnWidth ? sizes : [`${firstLastColumnWidth}px`, ...sizes, `${firstLastColumnWidth}px`];
@@ -480,19 +458,15 @@ function GridRow(props) {
480
458
  const rowStyle = rowStyles === null || rowStyles === void 0 ? void 0 : rowStyles[row.kind];
481
459
  const rowStyleCellCss = maybeApplyFunction(row, rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.cellCss);
482
460
  const rowCss = {
483
- // We add a display-contents so that we can have "row-level" div elements in our
484
- // DOM structure. I.e. grid is normally root-element > cell-elements, but we want
485
- // root-element > row-element > cell-elements, so that we can have a hook for
486
- // hovers and styling. In theory this would change with subgrids.
487
- // Only enable when using div as elements
488
461
  // For virtual tables use `display: flex` to keep all cells on the same row, but use `flexNone` to ensure the cells stay their defined widths
489
- ...(as === "table" ? {} : as === "virtual" ? Css_1.Css.df.addIn("&>*", Css_1.Css.flexNone.$).$ : Css_1.Css.display("contents").$),
462
+ ...(as === "table" ? {} : Css_1.Css.df.addIn("&>*", Css_1.Css.flexNone.$).$),
490
463
  ...(((rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowLink) || (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.onClick)) &&
491
464
  style.rowHoverColor && {
492
465
  // Even though backgroundColor is set on the cellCss (due to display: content), the hover target is the row.
493
466
  "&:hover > *": Css_1.Css.cursorPointer.bgColor(maybeDarken(rowStyleCellCss === null || rowStyleCellCss === void 0 ? void 0 : rowStyleCellCss.backgroundColor, style.rowHoverColor)).$,
494
467
  }),
495
468
  ...maybeApplyFunction(row, rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowCss),
469
+ ...(isHeader && stickyHeader ? Css_1.Css.sticky.top(stickyOffset).z1.$ : undefined),
496
470
  };
497
471
  const Row = as === "table" ? "tr" : "div";
498
472
  const openCardStyles = typeof openCards === "string"
@@ -543,18 +517,11 @@ function GridRow(props) {
543
517
  ...getIndentationCss(style, rowStyle, columnIndex, maybeContent),
544
518
  // Then apply any header-specific override
545
519
  ...(isHeader && style.headerCellCss),
546
- // Non-virtualized tables use h100 so that all cells are the same height across the row.
547
- // Virtualized table rows use `display: flex;`, so the flex children are set to `align-self: stretch` by default, which achieves the same goal.
548
- // Though, we need to omit setting `h100` on the flex children, as a flex container needs a defined height set for `h100` to work on flex children
549
- ...(isHeader && as !== "virtual" ? Css_1.Css.h100.$ : undefined),
550
- ...maybeStickyHeaderStyles,
551
520
  // If we're within a card, use its background color
552
521
  ...(currentCard && Css_1.Css.bgColor(currentCard.bgColor).$),
553
- // Add in colspan css if needed
554
- ...(currentColspan > 1 ? Css_1.Css.gc(`span ${currentColspan}`).$ : {}),
555
522
  // And finally the specific cell's css (if any from GridCellContent)
556
523
  ...rowStyleCellCss,
557
- // For virtual tables we define the width of the column on each cell. Supports col spans.
524
+ // Define the width of the column on each cell. Supports col spans.
558
525
  ...(columnSizes && {
559
526
  width: `calc(${columnSizes
560
527
  .slice(maybeNestedCardColumnIndex, maybeNestedCardColumnIndex + currentColspan)
@@ -641,8 +608,8 @@ function applyRowFn(column, row) {
641
608
  exports.applyRowFn = applyRowFn;
642
609
  /** Renders our default cell element, i.e. if no row links and no custom renderCell are used. */
643
610
  const defaultRenderFn = (as) => (key, css, content) => {
644
- const Row = as === "table" ? "td" : "div";
645
- return ((0, jsx_runtime_1.jsx)(Row, Object.assign({ css: { ...css, ...tableRowStyles(as) } }, { children: content }), key));
611
+ const Cell = as === "table" ? "td" : "div";
612
+ return ((0, jsx_runtime_1.jsx)(Cell, Object.assign({ css: { ...css, ...tableRowStyles(as) } }, { children: content }), key));
646
613
  };
647
614
  exports.GridCollapseContext = react_1.default.createContext({
648
615
  headerCollapsed: false,
@@ -33,7 +33,7 @@ function TextFieldBase(props) {
33
33
  const fieldHeight = 40;
34
34
  const compactFieldHeight = 32;
35
35
  const fieldStyles = {
36
- container: Css_1.Css.df.fdc.w100.maxw((0, Css_1.px)(550)).$,
36
+ container: Css_1.Css.df.fdc.w100.maxw((0, Css_1.px)(550)).relative.$,
37
37
  inputWrapper: {
38
38
  ...Css_1.Css[typeScale].df.aic.br4.px1.w100
39
39
  .hPx(fieldHeight - maybeSmaller)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.100.0",
3
+ "version": "2.101.3",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",