@homebound/beam 2.112.0 → 2.114.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.
@@ -1,7 +1,7 @@
1
1
  import { MutableRefObject, ReactElement, ReactNode } from "react";
2
2
  import { PresentationContextProps, PresentationFieldProps } from "../PresentationContext";
3
3
  import { GridRowLookup } from "./GridRowLookup";
4
- import { Margin, Only, Properties, Typography, Xss } from "../../Css";
4
+ import { Margin, Only, Palette, Properties, Typography, Xss } from "../../Css";
5
5
  export declare type Kinded = {
6
6
  kind: string;
7
7
  };
@@ -42,7 +42,7 @@ export interface GridStyle {
42
42
  /** Applied if there is a fallback/overflow message showing. */
43
43
  firstRowMessageCss?: Properties;
44
44
  /** Applied on hover if a row has a rowLink/onClick set. */
45
- rowHoverColor?: string;
45
+ rowHoverColor?: Palette;
46
46
  /** Styling for our special "nested card" output mode. */
47
47
  nestedCards?: NestedCardsStyle;
48
48
  /** Default content to put into an empty cell */
@@ -54,6 +54,8 @@ export interface GridStyle {
54
54
  levels?: Record<number, {
55
55
  cellCss: Properties;
56
56
  }>;
57
+ /** Allows for customization of the background color used to denote an "active" row */
58
+ activeBgColor?: Palette;
57
59
  }
58
60
  export declare type NestedCardStyleByKind = Record<string, NestedCardStyle>;
59
61
  export interface NestedCardsStyle {
@@ -67,6 +69,8 @@ export interface NestedCardsStyle {
67
69
  * Entries are optional, i.e. you can leave out kinds and they won't be wrapped/turned into cards.
68
70
  */
69
71
  kinds: NestedCardStyleByKind;
72
+ /** Allows for customization of the border color used to denote an "active" row */
73
+ activeBColor?: Palette;
70
74
  }
71
75
  /**
72
76
  * Styles for making cards nested within other cards.
@@ -172,6 +176,12 @@ export interface GridTableProps<R extends Kinded, S, X> {
172
176
  api?: MutableRefObject<GridTableApi<R> | undefined>;
173
177
  /** 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 */
174
178
  resizeTarget?: MutableRefObject<HTMLElement | null>;
179
+ /**
180
+ * Defines which row in the table should be provided with an "active" styling.
181
+ * Expected format is `${row.kind}_${row.id}`. This helps avoid id conflicts between rows of different types/kinds that may have the same id.
182
+ * Example "data_123"
183
+ */
184
+ activeRowId?: string;
175
185
  }
176
186
  /** NOTE: This API is experimental and primarily intended for story and testing purposes */
177
187
  export declare type GridTableApi<R extends Kinded> = {
@@ -180,6 +190,8 @@ export declare type GridTableApi<R extends Kinded> = {
180
190
  getSelectedRowIds(): string[];
181
191
  /** Returns the currently-selected rows. */
182
192
  getSelectedRows(): GridDataRow<R>[];
193
+ /** Sets the internal state of 'activeRowId' */
194
+ setActiveRowId: (id: string | undefined) => void;
183
195
  };
184
196
  /**
185
197
  * Renders data in our table layout.
@@ -228,7 +240,7 @@ declare type GridRowKind<R extends Kinded, P extends R["kind"]> = DiscriminateUn
228
240
  export declare type GridColumn<R extends Kinded, S = {}> = {
229
241
  [K in R["kind"]]: string | GridCellContent | (DiscriminateUnion<R, "kind", K> extends {
230
242
  data: infer D;
231
- } ? (data: D, row: GridRowKind<R, K>) => ReactNode | GridCellContent : (row: GridRowKind<R, K>) => ReactNode | GridCellContent);
243
+ } ? (data: D, row: GridRowKind<R, K>, api: GridTableApi<R>) => ReactNode | GridCellContent : (row: GridRowKind<R, K>, api: GridTableApi<R>) => ReactNode | GridCellContent);
232
244
  } & {
233
245
  /**
234
246
  * The column's width.
@@ -267,7 +279,7 @@ export interface RowStyle<R extends Kinded> {
267
279
  /** Whether the row should be a link. */
268
280
  rowLink?: (row: R) => string;
269
281
  /** Fired when the row is clicked, similar to rowLink but for actions that aren't 'go to this link'. */
270
- onClick?: (row: GridDataRow<R>) => void;
282
+ onClick?: (row: GridDataRow<R>, api: GridTableApi<R>) => void;
271
283
  }
272
284
  export declare type GridCellAlignment = "left" | "right" | "center";
273
285
  /**
@@ -310,6 +322,6 @@ export declare type GridDataRow<R extends Kinded> = {
310
322
  } & IfAny<R, {}, DiscriminateUnion<R, "kind", R["kind"]>>;
311
323
  declare type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
312
324
  /** Return the content for a given column def applied to a given row. */
313
- export declare function applyRowFn<R extends Kinded>(column: GridColumn<R>, row: GridDataRow<R>): ReactNode | GridCellContent;
325
+ export declare function applyRowFn<R extends Kinded>(column: GridColumn<R>, row: GridDataRow<R>, api: MutableRefObject<GridTableApi<R>>): ReactNode | GridCellContent;
314
326
  export declare function matchesFilter(maybeContent: ReactNode | GridCellContent, filter: string): boolean;
315
327
  export {};
@@ -43,7 +43,6 @@ const visitor_1 = require("./visitor");
43
43
  const Css_1 = require("../../Css");
44
44
  const hooks_1 = require("../../hooks");
45
45
  const useRenderCount_1 = require("../../hooks/useRenderCount");
46
- const tinycolor2_1 = __importDefault(require("tinycolor2"));
47
46
  const _1 = require(".");
48
47
  exports.ASC = "ASC";
49
48
  exports.DESC = "DESC";
@@ -86,30 +85,35 @@ exports.setGridTableDefaults = setGridTableDefaults;
86
85
  */
87
86
  function GridTable(props) {
88
87
  var _a, _b, _c, _d;
89
- 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;
88
+ 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: callerApi, resizeTarget, activeRowId, } = props;
90
89
  // Create a ref that always contains the latest rows, for our effectively-singleton RowState to use
91
90
  const rowsRef = (0, react_1.useRef)(rows);
92
91
  rowsRef.current = rows;
93
- const [rowState] = (0, react_1.useState)(() => new RowState_1.RowState(rowsRef, persistCollapse));
92
+ const [rowState] = (0, react_1.useState)(() => new RowState_1.RowState(rowsRef, persistCollapse, activeRowId));
94
93
  // We only use this in as=virtual mode, but keep this here for rowLookup to use
95
94
  const virtuosoRef = (0, react_1.useRef)(null);
96
95
  const tableRef = (0, react_1.useRef)(null);
97
- if (api) {
98
- api.current = {
99
- scrollToIndex: (index) => virtuosoRef.current && virtuosoRef.current.scrollToIndex(index),
100
- getSelectedRowIds: () => rowState.selectedIds,
101
- getSelectedRows() {
102
- const ids = rowState.selectedIds;
103
- const selected = [];
104
- (0, visitor_1.visit)(rows, (row) => {
105
- if (ids.includes(row.id)) {
106
- selected.push(row);
107
- }
108
- });
109
- return selected;
110
- },
111
- };
96
+ const api = (0, react_1.useRef)({
97
+ scrollToIndex: (index) => virtuosoRef.current && virtuosoRef.current.scrollToIndex(index),
98
+ getSelectedRowIds: () => rowState.selectedIds,
99
+ getSelectedRows() {
100
+ const ids = rowState.selectedIds;
101
+ const selected = [];
102
+ (0, visitor_1.visit)(rows, (row) => {
103
+ if (ids.includes(row.id)) {
104
+ selected.push(row);
105
+ }
106
+ });
107
+ return selected;
108
+ },
109
+ setActiveRowId: (id) => (rowState.activeRowId = id),
110
+ });
111
+ if (callerApi) {
112
+ callerApi.current = api.current;
112
113
  }
114
+ (0, react_1.useEffect)(() => {
115
+ rowState.activeRowId = activeRowId;
116
+ }, [activeRowId]);
113
117
  // We track render count at the table level, which seems odd (we should be able to track this
114
118
  // internally within each GridRow using a useRef), but we have suspicions that react-virtuoso
115
119
  // (or us) is resetting component state more than necessary, so we track render counts from
@@ -147,6 +151,7 @@ function GridTable(props) {
147
151
  columnSizes,
148
152
  level,
149
153
  getCount,
154
+ api,
150
155
  ...sortProps,
151
156
  }), `${row.kind}-${row.id}`));
152
157
  }
@@ -160,7 +165,7 @@ function GridTable(props) {
160
165
  var _a;
161
166
  const matches = filters.length === 0 ||
162
167
  row.pin ||
163
- filters.every((filter) => columns.map((c) => applyRowFn(c, row)).some((maybeContent) => matchesFilter(maybeContent, filter)));
168
+ filters.every((filter) => columns.map((c) => applyRowFn(c, row, api)).some((maybeContent) => matchesFilter(maybeContent, filter)));
164
169
  let isCard = false;
165
170
  // Even if we don't pass the filter, one of our children might, so we continue on after this check
166
171
  if (matches) {
@@ -452,7 +457,10 @@ function getFirstOrLastCellCss(style, columnIndex, columns) {
452
457
  }
453
458
  // We extract GridRow to its own mini-component primarily so we can React.memo'ize it.
454
459
  function GridRow(props) {
455
- const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sorting, sortState, setSortKey, openCards, columnSizes, level, getCount, ...others } = props;
460
+ var _a;
461
+ const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sorting, sortState, setSortKey, openCards, columnSizes, level, getCount, api, ...others } = props;
462
+ const { rowState } = (0, react_1.useContext)(RowState_1.RowStateContext);
463
+ const isActive = (0, hooks_1.useComputed)(() => rowState.activeRowId === `${row.kind}_${row.id}`, [row, rowState]);
456
464
  // We treat the "header" kind as special for "good defaults" styling
457
465
  const isHeader = row.kind === "header";
458
466
  const rowStyle = rowStyles === null || rowStyles === void 0 ? void 0 : rowStyles[row.kind];
@@ -467,19 +475,18 @@ function GridRow(props) {
467
475
  const rowCss = {
468
476
  // For virtual tables use `display: flex` to keep all cells on the same row. For each cell in the row use `flexNone` to ensure they stay their defined widths
469
477
  ...(as === "table" ? {} : Css_1.Css.relative.df.fg1.fs1.addIn("&>*", Css_1.Css.flexNone.$).$),
470
- ...(((rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowLink) || (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.onClick)) &&
471
- style.rowHoverColor && {
472
- // Even though backgroundColor is set on the cellCss (due to display: content), the hover target is the row.
473
- "&:hover > *": Css_1.Css.cursorPointer.bgColor(maybeDarken(rowStyleCellCss === null || rowStyleCellCss === void 0 ? void 0 : rowStyleCellCss.backgroundColor, style.rowHoverColor)).$,
478
+ ...(((rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowLink) || (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.onClick)) && {
479
+ // Even though backgroundColor is set on the cellCss, the hover target is the row.
480
+ "&:hover > *": Css_1.Css.cursorPointer.bgColor((_a = style.rowHoverColor) !== null && _a !== void 0 ? _a : Css_1.Palette.LightBlue100).$,
474
481
  }),
475
482
  ...maybeApplyFunction(row, rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowCss),
476
483
  // Maybe add the sticky header styles
477
484
  ...(isHeader && stickyHeader ? Css_1.Css.sticky.top(stickyOffset).z2.$ : undefined),
478
- ...(0, nestedCards_1.getNestedCardStyles)(row, openCardStyles, style),
485
+ ...(0, nestedCards_1.getNestedCardStyles)(row, openCardStyles, style, isActive),
479
486
  };
480
487
  let currentColspan = 1;
481
488
  const rowNode = ((0, jsx_runtime_1.jsx)(Row, Object.assign({ css: rowCss }, others, { "data-gridrow": true }, getCount(row.id), { children: columns.map((column, columnIndex) => {
482
- var _a, _b, _c, _d;
489
+ var _a, _b, _c, _d, _e;
483
490
  if (column.mw) {
484
491
  // Validate the column's minWidth definition if set.
485
492
  if (!column.mw.endsWith("px") && !column.mw.endsWith("%")) {
@@ -491,7 +498,7 @@ function GridRow(props) {
491
498
  currentColspan -= 1;
492
499
  return null;
493
500
  }
494
- const maybeContent = applyRowFn(column, row);
501
+ const maybeContent = applyRowFn(column, row, api);
495
502
  currentColspan = isGridCellContent(maybeContent) ? (_a = maybeContent.colspan) !== null && _a !== void 0 ? _a : 1 : 1;
496
503
  const canSortColumn = ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client" && column.clientSideSort !== false) ||
497
504
  ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "server" && !!column.serverSideSortKey);
@@ -548,6 +555,10 @@ function GridRow(props) {
548
555
  ...(!isHeader && !!style.levels && ((_d = style.levels[level]) === null || _d === void 0 ? void 0 : _d.cellCss)),
549
556
  // The specific cell's css (if any from GridCellContent)
550
557
  ...rowStyleCellCss,
558
+ // Apply active row styling for non-nested card styles.
559
+ ...(style.nestedCards === undefined && isActive
560
+ ? Css_1.Css.bgColor((_e = style.activeBgColor) !== null && _e !== void 0 ? _e : Css_1.Palette.LightBlue50).$
561
+ : {}),
551
562
  // Add any cell specific style overrides
552
563
  ...(isGridCellContent(maybeContent) && maybeContent.typeScale ? Css_1.Css[maybeContent.typeScale].$ : {}),
553
564
  // Define the width of the column on each cell. Supports col spans.
@@ -563,7 +574,7 @@ function GridRow(props) {
563
574
  : isHeader
564
575
  ? headerRenderFn(columns, column, sortState, setSortKey, as)
565
576
  : (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.onClick)
566
- ? rowClickRenderFn(as)
577
+ ? rowClickRenderFn(as, api)
567
578
  : defaultRenderFn(as);
568
579
  return renderFn(columnIndex, cellCss, content, row, rowStyle);
569
580
  }) }), void 0));
@@ -620,16 +631,16 @@ function isContentEmpty(content) {
620
631
  return emptyValues.includes(content);
621
632
  }
622
633
  /** Return the content for a given column def applied to a given row. */
623
- function applyRowFn(column, row) {
634
+ function applyRowFn(column, row, api) {
624
635
  // Usually this is a function to apply against the row, but sometimes it's a hard-coded value, i.e. for headers
625
636
  const maybeContent = column[row.kind];
626
637
  if (typeof maybeContent === "function") {
627
638
  if ("data" in row && "id" in row) {
628
639
  // Auto-destructure data
629
- return maybeContent(row["data"], row["id"]);
640
+ return maybeContent(row["data"], row["id"], api.current);
630
641
  }
631
642
  else {
632
- return maybeContent(row);
643
+ return maybeContent(row, api.current);
633
644
  }
634
645
  }
635
646
  else {
@@ -663,9 +674,9 @@ const rowLinkRenderFn = (as) => (key, css, content, row, rowStyle) => {
663
674
  return ((0, jsx_runtime_1.jsx)(react_router_dom_1.Link, Object.assign({ to: to, css: { ...Css_1.Css.noUnderline.color("unset").$, ...css }, className: CssReset_1.navLink }, { children: content }), key));
664
675
  };
665
676
  /** Renders a cell that will fire the RowStyle.onClick. */
666
- const rowClickRenderFn = (as) => (key, css, content, row, rowStyle) => {
677
+ const rowClickRenderFn = (as, api) => (key, css, content, row, rowStyle) => {
667
678
  const Row = as === "table" ? "tr" : "div";
668
- return ((0, jsx_runtime_1.jsx)(Row, Object.assign({}, { key }, { css: { ...css, ...tableRowStyles(as) }, onClick: () => rowStyle.onClick(row) }, { children: content }), void 0));
679
+ return ((0, jsx_runtime_1.jsx)(Row, Object.assign({}, { key }, { css: { ...css, ...tableRowStyles(as) }, onClick: () => rowStyle.onClick(row, api.current) }, { children: content }), void 0));
669
680
  };
670
681
  const alignmentToJustify = {
671
682
  left: "flex-start",
@@ -720,9 +731,6 @@ function matchesFilter(maybeContent, filter) {
720
731
  return false;
721
732
  }
722
733
  exports.matchesFilter = matchesFilter;
723
- function maybeDarken(color, defaultColor) {
724
- return color ? (0, tinycolor2_1.default)(color).darken(4).toString() : defaultColor;
725
- }
726
734
  /** GridTable as Table utility to apply <tr> element override styles. */
727
735
  function tableRowStyles(as, column) {
728
736
  const thWidth = column === null || column === void 0 ? void 0 : column.w;
@@ -21,10 +21,11 @@ export declare class RowState {
21
21
  private persistCollapse;
22
22
  private readonly collapsedRows;
23
23
  private readonly selectedRows;
24
+ activeRowId: string | undefined;
24
25
  /**
25
26
  * Creates the `RowState` for a given `GridTable`.
26
27
  */
27
- constructor(rows: MutableRefObject<GridDataRow<any>[]>, persistCollapse: string | undefined);
28
+ constructor(rows: MutableRefObject<GridDataRow<any>[]>, persistCollapse: string | undefined, activeRowId: string | undefined);
28
29
  get selectedIds(): string[];
29
30
  getSelected(id: string): SelectedState;
30
31
  selectRow(id: string, selected: boolean): void;
@@ -26,11 +26,12 @@ class RowState {
26
26
  /**
27
27
  * Creates the `RowState` for a given `GridTable`.
28
28
  */
29
- constructor(rows, persistCollapse) {
29
+ constructor(rows, persistCollapse, activeRowId) {
30
30
  this.rows = rows;
31
31
  this.persistCollapse = persistCollapse;
32
32
  this.selectedRows = new mobx_1.ObservableMap();
33
33
  this.collapsedRows = new mobx_1.ObservableSet(persistCollapse ? readLocalCollapseState(persistCollapse) : []);
34
+ this.activeRowId = activeRowId;
34
35
  // Make ourselves an observable so that mobx will do caching of .collapseIds so
35
36
  // that it'll be a stable identity for GridTable to useMemo against.
36
37
  (0, mobx_1.makeAutoObservable)(this, { rows: false }); // as any b/c rows is private, so the mapped type doesn't see it
@@ -77,7 +77,8 @@ export declare function makeOpenOrCloseCard(openCards: string[], cardStyles: Nes
77
77
  * <div parent> <div child> <div grandchild /> </div> </div>
78
78
  */
79
79
  export declare function wrapCard(openCards: NestedCardStyle[], row: JSX.Element): JSX.Element;
80
- export declare function getNestedCardStyles(row: GridDataRow<any>, openCardStyles: NestedCardStyle[] | undefined, style: GridStyle): {
80
+ export declare function getNestedCardStyles(row: GridDataRow<any>, openCardStyles: NestedCardStyle[] | undefined, style: GridStyle, isActive: boolean): {
81
+ boxShadow?: import("csstype").Property.BoxShadow | undefined;
81
82
  paddingTop?: import("csstype").Property.PaddingTop<0 | (string & {})> | undefined;
82
83
  paddingBottom?: import("csstype").Property.PaddingBottom<0 | (string & {})> | undefined;
83
84
  borderRadius?: import("csstype").Property.BorderRadius<0 | (string & {})> | undefined;
@@ -143,15 +143,13 @@ exports.makeOpenOrCloseCard = makeOpenOrCloseCard;
143
143
  function wrapCard(openCards, row) {
144
144
  let div = row;
145
145
  [...openCards].reverse().forEach((card) => {
146
- div = ((0, jsx_runtime_1.jsx)("div", Object.assign({ css: {
147
- ...Css_1.Css.h100.pxPx(card.pxPx).bgColor(card.bgColor).if(!!card.bColor).bc(card.bColor).bl.br.$,
148
- } }, { children: div }), void 0));
146
+ div = ((0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.h100.pxPx(card.pxPx).bgColor(card.bgColor).if(!!card.bColor).bc(card.bColor).bl.br.$ }, { children: div }), void 0));
149
147
  });
150
148
  return div;
151
149
  }
152
150
  exports.wrapCard = wrapCard;
153
- function getNestedCardStyles(row, openCardStyles, style) {
154
- var _a, _b, _c;
151
+ function getNestedCardStyles(row, openCardStyles, style, isActive) {
152
+ var _a, _b, _c, _d, _e;
155
153
  const leafCardStyles = isLeafRow(row) ? (_a = style.nestedCards) === null || _a === void 0 ? void 0 : _a.kinds[row.kind] : undefined;
156
154
  // Calculate the horizontal space already allocated by the open cards (paddings and borders)
157
155
  const openCardWidth = openCardStyles ? openCardStyles.reduce((acc, o) => acc + o.pxPx + (o.bColor ? 1 : 0), 0) : 0;
@@ -167,11 +165,16 @@ function getNestedCardStyles(row, openCardStyles, style) {
167
165
  // When it is not a leaf then it has chrome rows that create the top and bottom "padding" based on border-radius size. (brPx = "chrome" row height)
168
166
  // When it is a leaf, then we need to apply the brPx to the row to ensure consistent spacing between leaf & non-leaf renders
169
167
  // Additionally, if the leaf card has a border, then subtract the 1px border width from the padding to keep consistent with the "chrome" row
170
- Css_1.Css.pyPx(leafCardStyles.brPx - (leafCardStyles.bColor ? 1 : 0))
171
- .borderRadius(`${leafCardStyles.brPx}px`)
172
- .bgColor(leafCardStyles.bgColor)
173
- .if(!!leafCardStyles.bColor)
174
- .bc(leafCardStyles.bColor).ba.$
168
+ {
169
+ ...Css_1.Css.pyPx(leafCardStyles.brPx - (leafCardStyles.bColor ? 1 : 0))
170
+ .borderRadius(`${leafCardStyles.brPx}px`)
171
+ .bgColor(leafCardStyles.bgColor)
172
+ .if(!!leafCardStyles.bColor)
173
+ .bc(leafCardStyles.bColor).ba.$,
174
+ ...(isActive
175
+ ? Css_1.Css.boxShadow(`0px 0px 0px 2px rgba(254,254,254,1), 0px 0px 0px 4px ${(_e = (_d = style.nestedCards) === null || _d === void 0 ? void 0 : _d.activeBColor) !== null && _e !== void 0 ? _e : Css_1.Palette.LightBlue700}`).$
176
+ : {}),
177
+ }
175
178
  : undefined),
176
179
  };
177
180
  }
@@ -21,8 +21,8 @@ function sortBatch(columns, batch, sortState) {
21
21
  const invert = direction === "DESC";
22
22
  // Make a shallow copy for sorting to avoid mutating the original list
23
23
  return [...batch].sort((a, b) => {
24
- const v1 = sortValue((0, GridTable_1.applyRowFn)(column, a));
25
- const v2 = sortValue((0, GridTable_1.applyRowFn)(column, b));
24
+ const v1 = sortValue((0, GridTable_1.applyRowFn)(column, a, {}));
25
+ const v2 = sortValue((0, GridTable_1.applyRowFn)(column, b, {}));
26
26
  const v1e = v1 === null || v1 === undefined;
27
27
  const v2e = v2 === null || v2 === undefined;
28
28
  if (a.pin || b.pin) {
@@ -14,7 +14,6 @@ exports.defaultStyle = {
14
14
  indentTwoCss: Css_1.Css.pl7.$,
15
15
  headerCellCss: Css_1.Css.nowrap.py1.bgGray100.aife.$,
16
16
  firstRowMessageCss: Css_1.Css.px1.py2.$,
17
- rowHoverColor: Css_1.Palette.Gray200,
18
17
  };
19
18
  /** Tightens up the padding of rows, great for rows that have form elements in them. */
20
19
  exports.condensedStyle = {
@@ -45,7 +44,6 @@ exports.beamFixedStyle = {
45
44
  cellCss: Css_1.Css.gray900.xs.bgWhite.aic.nowrap.pxPx(12).hPx(36).boxShadow(`inset 0 -1px 0 ${Css_1.Palette.Gray100}`).$,
46
45
  emptyCell: "-",
47
46
  presentationSettings: { borderless: true, typeScale: "xs", wrap: false },
48
- rowHoverColor: Css_1.Palette.Gray200,
49
47
  // Included as a hacky "treat indent as deprecated for this table" hint to GridTable
50
48
  levels: {},
51
49
  };
@@ -7,28 +7,45 @@ const react_1 = require("react");
7
7
  function useComputed(fn, deps) {
8
8
  // We always return the useRef value, and use this just to trigger re-renders
9
9
  const [, setValue] = (0, react_1.useState)(0);
10
- const autoRunner = (0, react_1.useRef)();
11
- const autoRanValue = (0, react_1.useRef)();
10
+ const ref = (0, react_1.useRef)({
11
+ runner: undefined,
12
+ value: undefined,
13
+ hasRan: false,
14
+ });
15
+ // We use a `useMemo` b/c we want this to synchronously calc, so that even
16
+ // the very 1st render can use the result of our computed, i.e. instead of
17
+ // with `useEffect`, which would only get calc'd after the 1st render has
18
+ // already been done.
12
19
  (0, react_1.useMemo)(() => {
13
20
  let tick = 0;
21
+ const { current } = ref;
14
22
  // If deps has changed, unhook the previous observer
15
- if (autoRunner.current) {
16
- autoRunner.current();
23
+ if (current.runner) {
24
+ current.runner();
17
25
  }
18
- autoRunner.current = (0, mobx_1.autorun)(() => {
26
+ current.runner = (0, mobx_1.autorun)(() => {
19
27
  // Always eval fn() (even on 1st render) to register our observable.
20
- autoRanValue.current = fn();
28
+ const newValue = fn();
29
+ const oldValue = current.value;
30
+ current.value = newValue;
31
+ current.hasRan = true;
21
32
  // Only trigger a re-render if this is not the 1st autorun. Note
22
33
  // that if deps has changed, we're inherently in a re-render so also
23
34
  // don't need to trigger an additional re-render.
24
- if (tick > 0) {
35
+ if (tick > 0 && newValue !== oldValue) {
25
36
  setValue(tick);
26
37
  }
27
38
  tick++;
28
39
  });
29
40
  // eslint-disable-next-line react-hooks/exhaustive-deps
30
41
  }, deps);
42
+ // Occasionally autorun will not have run yet, in which case we have to just
43
+ // accept running the eval fn twice (here to get the value for the 1st render,
44
+ // and again for mobx to watch what observables we touch).
45
+ if (!ref.current.hasRan) {
46
+ ref.current.value = fn();
47
+ }
31
48
  // We can use `!` here b/c we know that `autorun` set current
32
- return autoRanValue.current;
49
+ return ref.current.value;
33
50
  }
34
51
  exports.useComputed = useComputed;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.112.0",
3
+ "version": "2.114.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -37,7 +37,6 @@
37
37
  "@internationalized/number": "^3.0.3",
38
38
  "@react-aria/utils": "^3.9.0",
39
39
  "@react-hook/resize-observer": "^1.2.2",
40
- "@types/tinycolor2": "^1.4.2",
41
40
  "change-case": "^4.1.2",
42
41
  "date-fns": "^2.21.3",
43
42
  "dompurify": "^2.3.0",
@@ -50,7 +49,6 @@
50
49
  "react-router-dom": "^5.2.0",
51
50
  "react-stately": "^3.9.0",
52
51
  "react-virtuoso": "^2.4.0",
53
- "tinycolor2": "^1.4.2",
54
52
  "tributejs": "^5.1.3",
55
53
  "trix": "^1.3.1",
56
54
  "use-query-params": "^1.2.2",