@homebound/beam 2.107.0 → 2.110.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.
@@ -21,6 +21,8 @@ export interface ModalProps {
21
21
  onClose?: Callback;
22
22
  /** Imperative API for interacting with the Modal */
23
23
  api?: MutableRefObject<ModalApi | undefined>;
24
+ /** Adds a border for the header. */
25
+ drawHeaderBorder?: boolean;
24
26
  }
25
27
  export declare type ModalApi = {
26
28
  setSize: (size: ModalProps["size"]) => void;
@@ -20,7 +20,7 @@ const utils_1 = require("../../utils");
20
20
  * Provides underlay, modal container, and header. Will disable scrolling of page under the modal.
21
21
  */
22
22
  function Modal(props) {
23
- const { size = "md", content, forceScrolling, api } = props;
23
+ const { size = "md", content, forceScrolling, api, drawHeaderBorder = false } = props;
24
24
  const isFixedHeight = typeof size !== "string";
25
25
  const ref = (0, react_1.useRef)(null);
26
26
  const { modalBodyDiv, modalFooterDiv, modalHeaderDiv, drawerContentStack } = (0, BeamContext_1.useBeamContext)();
@@ -69,7 +69,7 @@ function Modal(props) {
69
69
  .df.fdc.wPx(width)
70
70
  .mh((0, Css_1.px)(defaultMinHeight))
71
71
  .if(isFixedHeight)
72
- .hPx(height).$, ref: ref }, overlayProps, dialogProps, modalProps, testId, { children: [(0, jsx_runtime_1.jsxs)("header", Object.assign({ css: Css_1.Css.df.p3.fs0.$ }, { children: [(0, jsx_runtime_1.jsx)("h1", Object.assign({ css: Css_1.Css.fg1.xl2Em.gray900.$, ref: modalHeaderRef }, titleProps, testId.title), void 0), (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.fs0.pl1.$ }, { children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, Object.assign({ icon: "x", onClick: closeModal }, testId.titleClose), void 0) }), void 0)] }), void 0), (0, jsx_runtime_1.jsxs)("main", Object.assign({ ref: contentRef, css: Css_1.Css.fg1.overflowYAuto.if(hasScroll).bb.bGray200.if(!!forceScrolling).overflowYScroll.$ }, { children: [content, (0, jsx_runtime_1.jsx)("div", { ref: modalBodyRef }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)("footer", Object.assign({ css: Css_1.Css.fs0.$ }, { children: (0, jsx_runtime_1.jsx)("div", { ref: modalFooterRef }, void 0) }), void 0)] }), void 0) }), void 0) }), void 0) }, void 0));
72
+ .hPx(height).$, ref: ref }, overlayProps, dialogProps, modalProps, testId, { children: [(0, jsx_runtime_1.jsxs)("header", Object.assign({ css: Css_1.Css.df.p3.fs0.if(drawHeaderBorder).bb.bGray200.$ }, { children: [(0, jsx_runtime_1.jsx)("h1", Object.assign({ css: Css_1.Css.fg1.xl2Em.gray900.$, ref: modalHeaderRef }, titleProps, testId.title), void 0), (0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.fs0.pl1.$ }, { children: (0, jsx_runtime_1.jsx)(IconButton_1.IconButton, Object.assign({ icon: "x", onClick: closeModal }, testId.titleClose), void 0) }), void 0)] }), void 0), (0, jsx_runtime_1.jsxs)("main", Object.assign({ ref: contentRef, css: Css_1.Css.fg1.overflowYAuto.if(hasScroll).bb.bGray200.if(!!forceScrolling).overflowYScroll.$ }, { children: [content, (0, jsx_runtime_1.jsx)("div", { ref: modalBodyRef }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)("footer", Object.assign({ css: Css_1.Css.fs0.$ }, { children: (0, jsx_runtime_1.jsx)("div", { ref: modalFooterRef }, void 0) }), void 0)] }), void 0) }), void 0) }), void 0) }, void 0));
73
73
  }
74
74
  exports.Modal = Modal;
75
75
  function ModalHeader({ children }) {
@@ -2,4 +2,5 @@ import { GridDataRow } from "..";
2
2
  export interface GridTableCollapseToggleProps {
3
3
  row: GridDataRow<any>;
4
4
  }
5
+ /** Provides a chevron icons to collapse/un-collapse for parent/child tables. */
5
6
  export declare function CollapseToggle(props: GridTableCollapseToggleProps): import("@emotion/react/jsx-runtime").JSX.Element | null;
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const components_1 = require("..");
7
7
  const hooks_1 = require("../../hooks");
8
+ /** Provides a chevron icons to collapse/un-collapse for parent/child tables. */
8
9
  function CollapseToggle(props) {
9
10
  const { row } = props;
10
11
  const { rowState } = (0, react_1.useContext)(components_1.RowStateContext);
@@ -169,15 +169,17 @@ export interface GridTableProps<R extends Kinded, S, X> {
169
169
  persistCollapse?: string;
170
170
  xss?: X;
171
171
  /** Experimental API allowing one to scroll to a table index. Primarily intended for stories at the moment */
172
- api?: MutableRefObject<GridTableApi | undefined>;
172
+ api?: MutableRefObject<GridTableApi<R> | undefined>;
173
173
  /** 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
174
  resizeTarget?: MutableRefObject<HTMLElement | null>;
175
175
  }
176
176
  /** NOTE: This API is experimental and primarily intended for story and testing purposes */
177
- export declare type GridTableApi = {
177
+ export declare type GridTableApi<R extends Kinded> = {
178
178
  scrollToIndex: (index: number) => void;
179
179
  /** Returns the ids of currently-selected rows. */
180
180
  getSelectedRowIds(): string[];
181
+ /** Returns the currently-selected rows. */
182
+ getSelectedRows(): GridDataRow<R>[];
181
183
  };
182
184
  /**
183
185
  * Renders data in our table layout.
@@ -244,6 +246,7 @@ export declare type GridColumn<R extends Kinded, S = {}> = {
244
246
  /** This column's sort by value (if server-side sorting). */
245
247
  serverSideSortKey?: S;
246
248
  };
249
+ export declare const nonKindGridColumnKeys: string[];
247
250
  /** Allows rendering a specific cell. */
248
251
  declare type RenderCellFn<R extends Kinded> = (idx: number, css: Properties, content: ReactNode, row: R, rowStyle: RowStyle<R> | undefined) => ReactNode;
249
252
  /** Defines row-specific styling for each given row `kind` in `R` */
@@ -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.applyRowFn = exports.calcColumnSizes = exports.GridTable = exports.setGridTableDefaults = exports.setDefaultStyle = exports.setRunningInJest = exports.emptyCell = exports.DESC = exports.ASC = void 0;
25
+ exports.matchesFilter = exports.applyRowFn = exports.nonKindGridColumnKeys = 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");
@@ -39,8 +39,10 @@ const RowState_1 = require("./RowState");
39
39
  const SortHeader_1 = require("./SortHeader");
40
40
  const sortRows_1 = require("./sortRows");
41
41
  const useSortState_1 = require("./useSortState");
42
+ const visitor_1 = require("./visitor");
42
43
  const Css_1 = require("../../Css");
43
44
  const hooks_1 = require("../../hooks");
45
+ const useRenderCount_1 = require("../../hooks/useRenderCount");
44
46
  const tinycolor2_1 = __importDefault(require("tinycolor2"));
45
47
  const _1 = require(".");
46
48
  exports.ASC = "ASC";
@@ -96,8 +98,23 @@ function GridTable(props) {
96
98
  api.current = {
97
99
  scrollToIndex: (index) => virtuosoRef.current && virtuosoRef.current.scrollToIndex(index),
98
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
+ },
99
111
  };
100
112
  }
113
+ // We track render count at the table level, which seems odd (we should be able to track this
114
+ // internally within each GridRow using a useRef), but we have suspicions that react-virtuoso
115
+ // (or us) is resetting component state more than necessary, so we track render counts from
116
+ // here instead.
117
+ const { getCount } = (0, useRenderCount_1.useRenderCount)();
101
118
  const [sortState, setSortKey] = (0, useSortState_1.useSortState)(columns, sorting);
102
119
  const maybeSorted = (0, react_1.useMemo)(() => {
103
120
  if ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client" && sortState) {
@@ -129,6 +146,7 @@ function GridTable(props) {
129
146
  openCards: nestedCards ? nestedCards.currentOpenCards() : undefined,
130
147
  columnSizes,
131
148
  level,
149
+ getCount,
132
150
  ...sortProps,
133
151
  }), `${row.kind}-${row.id}`));
134
152
  }
@@ -417,6 +435,7 @@ function calcColumnSizes(columns, firstLastColumnWidth, tableWidth, tableMinWidt
417
435
  return !firstLastColumnWidth ? sizes : [`${firstLastColumnWidth}px`, ...sizes, `${firstLastColumnWidth}px`];
418
436
  }
419
437
  exports.calcColumnSizes = calcColumnSizes;
438
+ exports.nonKindGridColumnKeys = ["w", "mw", "align", "clientSideSort", "serverSideSortKey"];
420
439
  function getIndentationCss(style, rowStyle, columnIndex, maybeContent) {
421
440
  // Look for cell-specific indent or row-specific indent (row-specific is only one the first column)
422
441
  const indent = (isGridCellContent(maybeContent) && maybeContent.indent) || (columnIndex === 0 && (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.indent));
@@ -433,7 +452,7 @@ function getFirstOrLastCellCss(style, columnIndex, columns) {
433
452
  }
434
453
  // We extract GridRow to its own mini-component primarily so we can React.memo'ize it.
435
454
  function GridRow(props) {
436
- const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sorting, sortState, setSortKey, openCards, columnSizes, level, ...others } = props;
455
+ const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sorting, sortState, setSortKey, openCards, columnSizes, level, getCount, ...others } = props;
437
456
  // We treat the "header" kind as special for "good defaults" styling
438
457
  const isHeader = row.kind === "header";
439
458
  const rowStyle = rowStyles === null || rowStyles === void 0 ? void 0 : rowStyles[row.kind];
@@ -459,7 +478,7 @@ function GridRow(props) {
459
478
  ...(0, nestedCards_1.getNestedCardStyles)(row, openCardStyles, style),
460
479
  };
461
480
  let currentColspan = 1;
462
- const rowNode = ((0, jsx_runtime_1.jsx)(Row, Object.assign({ css: rowCss }, others, { "data-gridrow": true }, { children: columns.map((column, columnIndex) => {
481
+ const rowNode = ((0, jsx_runtime_1.jsx)(Row, Object.assign({ css: rowCss }, others, { "data-gridrow": true }, getCount(row.id), { children: columns.map((column, columnIndex) => {
463
482
  var _a, _b;
464
483
  if (column.mw) {
465
484
  // Validate the column's minWidth definition if set.
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.RowStateContext = exports.RowState = void 0;
7
7
  const mobx_1 = require("mobx");
8
8
  const react_1 = __importDefault(require("react"));
9
+ const visitor_1 = require("./visitor");
9
10
  /**
10
11
  * Stores the collapsed & selected state of rows.
11
12
  *
@@ -56,7 +57,7 @@ class RowState {
56
57
  // Just mash the header + all rows + children as selected
57
58
  const map = new Map();
58
59
  map.set("header", "checked");
59
- visit(this.rows.current, (row) => map.set(row.id, "checked"));
60
+ (0, visitor_1.visit)(this.rows.current, (row) => map.set(row.id, "checked"));
60
61
  this.selectedRows.replace(map);
61
62
  }
62
63
  else {
@@ -74,7 +75,7 @@ class RowState {
74
75
  }
75
76
  // Everything here & down is deterministically on/off
76
77
  const map = new Map();
77
- visit([curr.row], (row) => map.set(row.id, selected ? "checked" : "unchecked"));
78
+ (0, visitor_1.visit)([curr.row], (row) => map.set(row.id, selected ? "checked" : "unchecked"));
78
79
  // Now walk up the parents and see if they are now-all-checked/now-all-unchecked/some-of-each
79
80
  for (const parent of [...curr.parents].reverse()) {
80
81
  if (parent.children) {
@@ -173,13 +174,3 @@ function deriveParentSelected(children) {
173
174
  const allUnchecked = children.every((child) => child === "unchecked");
174
175
  return allChecked ? "checked" : allUnchecked ? "unchecked" : "partial";
175
176
  }
176
- function visit(rows, fn) {
177
- const todo = [...rows];
178
- while (todo.length > 0) {
179
- const row = todo.pop();
180
- fn(row);
181
- if (row.children) {
182
- todo.push(...row.children);
183
- }
184
- }
185
- }
@@ -0,0 +1,4 @@
1
+ /** Provides a checkbox to show/drive this row's selected state. */
2
+ export declare function SelectToggle({ id }: {
3
+ id: string;
4
+ }): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SelectToggle = void 0;
4
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const RowState_1 = require("./RowState");
7
+ const index_1 = require("../../hooks/index");
8
+ const index_2 = require("../../inputs/index");
9
+ /** Provides a checkbox to show/drive this row's selected state. */
10
+ function SelectToggle({ id }) {
11
+ const { rowState } = (0, react_1.useContext)(RowState_1.RowStateContext);
12
+ const state = (0, index_1.useComputed)(() => rowState.getSelected(id), [rowState]);
13
+ const selected = state === "checked" ? true : state === "unchecked" ? false : "indeterminate";
14
+ return ((0, jsx_runtime_1.jsx)(index_2.Checkbox, { label: "Select", checkboxOnly: true, selected: selected, onChange: (selected) => {
15
+ rowState.selectRow(id, selected);
16
+ } }, void 0));
17
+ }
18
+ exports.SelectToggle = SelectToggle;
@@ -8,7 +8,19 @@ export declare function dateColumn<T extends Kinded, S = {}>(columnDef: GridColu
8
8
  export declare function numericColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
9
9
  /** Provides default styling for a GridColumn representing an Action. */
10
10
  export declare function actionColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
11
- /** Provides default styling for a GridColumn containing a checkbox. */
12
- export declare function selectColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
13
- /** Provides default styling for a GridColumn containing the CollapseToggle component. */
14
- export declare function collapseColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
11
+ /**
12
+ * Provides default styling for a GridColumn containing a checkbox.
13
+ *
14
+ * We allow either no `columnDef` at all, or a partial column def (i.e. to say a Totals row should
15
+ * not have a `SelectToggle`, b/c we can provide the default behavior a `SelectToggle` for basically
16
+ * all rows.
17
+ */
18
+ export declare function selectColumn<T extends Kinded, S = {}>(columnDef?: Partial<GridColumn<T, S>>): GridColumn<T, S>;
19
+ /**
20
+ * Provides default styling for a GridColumn containing a collapse icon.
21
+ *
22
+ * We allow either no `columnDef` at all, or a partial column def (i.e. to say a Totals row should
23
+ * not have a `CollapseToggle`, b/c we can provide the default behavior a `CollapseToggle` for basically
24
+ * all rows.
25
+ */
26
+ export declare function collapseColumn<T extends Kinded, S = {}>(columnDef?: Partial<GridColumn<T, S>>): GridColumn<T, S>;
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.collapseColumn = exports.selectColumn = exports.actionColumn = exports.numericColumn = exports.dateColumn = exports.column = void 0;
4
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
+ const CollapseToggle_1 = require("./CollapseToggle");
6
+ const GridTable_1 = require("./GridTable");
7
+ const SelectToggle_1 = require("./SelectToggle");
8
+ const index_1 = require("../../utils/index");
4
9
  /** Provides default styling for a GridColumn representing a Date. */
5
10
  function column(columnDef) {
6
11
  return { ...columnDef };
@@ -22,15 +27,50 @@ function actionColumn(columnDef) {
22
27
  return { clientSideSort: false, ...columnDef, align: "center" };
23
28
  }
24
29
  exports.actionColumn = actionColumn;
25
- /** Provides default styling for a GridColumn containing a checkbox. */
30
+ /**
31
+ * Provides default styling for a GridColumn containing a checkbox.
32
+ *
33
+ * We allow either no `columnDef` at all, or a partial column def (i.e. to say a Totals row should
34
+ * not have a `SelectToggle`, b/c we can provide the default behavior a `SelectToggle` for basically
35
+ * all rows.
36
+ */
26
37
  function selectColumn(columnDef) {
27
- // Defining `w: 48px` to accommodate for the `16px` wide checkbox and `16px` of padding on either side.
28
- return { clientSideSort: false, ...columnDef, align: "center", w: "48px" };
38
+ const base = {
39
+ ...nonKindDefaults(),
40
+ clientSideSort: false,
41
+ align: "center",
42
+ // Defining `w: 48px` to accommodate for the `16px` wide checkbox and `16px` of padding on either side.
43
+ w: "48px",
44
+ // Use any of the user's per-row kind methods if they have them.
45
+ ...columnDef,
46
+ };
47
+ return (0, index_1.newMethodMissingProxy)(base, (key) => {
48
+ return (row) => ({ content: (0, jsx_runtime_1.jsx)(SelectToggle_1.SelectToggle, { id: row.id }, void 0) });
49
+ });
29
50
  }
30
51
  exports.selectColumn = selectColumn;
31
- /** Provides default styling for a GridColumn containing the CollapseToggle component. */
52
+ /**
53
+ * Provides default styling for a GridColumn containing a collapse icon.
54
+ *
55
+ * We allow either no `columnDef` at all, or a partial column def (i.e. to say a Totals row should
56
+ * not have a `CollapseToggle`, b/c we can provide the default behavior a `CollapseToggle` for basically
57
+ * all rows.
58
+ */
32
59
  function collapseColumn(columnDef) {
33
- // Defining `w: 38px` based on the designs
34
- return { ...columnDef, clientSideSort: false, align: "center", w: "38px" };
60
+ const base = {
61
+ ...nonKindDefaults(),
62
+ clientSideSort: false,
63
+ align: "center",
64
+ // Defining `w: 38px` based on the designs
65
+ w: "38px",
66
+ ...columnDef,
67
+ };
68
+ return (0, index_1.newMethodMissingProxy)(base, (key) => {
69
+ return (row) => ({ content: (0, jsx_runtime_1.jsx)(CollapseToggle_1.CollapseToggle, { row: row }, void 0) });
70
+ });
35
71
  }
36
72
  exports.collapseColumn = collapseColumn;
73
+ // Keep keys like `w` and `mw` from hitting the method missing proxy
74
+ function nonKindDefaults() {
75
+ return Object.fromEntries(GridTable_1.nonKindGridColumnKeys.map((key) => [key, undefined]));
76
+ }
@@ -5,6 +5,7 @@ export { GridSortContext } from "./GridSortContext";
5
5
  export { ASC, DESC, GridTable, setDefaultStyle, setGridTableDefaults } from "./GridTable";
6
6
  export type { Direction, GridCellAlignment, GridCellContent, GridColumn, GridDataRow, GridRowStyles, GridSortConfig, GridStyle, GridTableDefaults, GridTableProps, GridTableXss, Kinded, RowStyle, setRunningInJest, } from "./GridTable";
7
7
  export { RowState, RowStateContext } from "./RowState";
8
+ export * from "./SelectToggle";
8
9
  export { simpleDataRows, simpleHeader, simpleRows } from "./simpleHelpers";
9
10
  export type { SimpleHeaderAndDataOf, SimpleHeaderAndDataWith } from "./simpleHelpers";
10
11
  export { SortHeader } from "./SortHeader";
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "setGridTableDefaults", { enumerable: true, get:
24
24
  var RowState_1 = require("./RowState");
25
25
  Object.defineProperty(exports, "RowState", { enumerable: true, get: function () { return RowState_1.RowState; } });
26
26
  Object.defineProperty(exports, "RowStateContext", { enumerable: true, get: function () { return RowState_1.RowStateContext; } });
27
+ __exportStar(require("./SelectToggle"), exports);
27
28
  var simpleHelpers_1 = require("./simpleHelpers");
28
29
  Object.defineProperty(exports, "simpleDataRows", { enumerable: true, get: function () { return simpleHelpers_1.simpleDataRows; } });
29
30
  Object.defineProperty(exports, "simpleHeader", { enumerable: true, get: function () { return simpleHelpers_1.simpleHeader; } });
@@ -0,0 +1,2 @@
1
+ import { GridDataRow } from "./GridTable";
2
+ export declare function visit(rows: GridDataRow<any>[], fn: (row: GridDataRow<any>) => void): void;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.visit = void 0;
4
+ function visit(rows, fn) {
5
+ const todo = [...rows];
6
+ while (todo.length > 0) {
7
+ const row = todo.pop();
8
+ fn(row);
9
+ if (row.children) {
10
+ todo.push(...row.children);
11
+ }
12
+ }
13
+ }
14
+ exports.visit = visit;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * A hook to add `data-render=${count}` to an element.
3
+ *
4
+ * This will output even in production mode, which in theory is not necessary
5
+ * and we could/should avoid, but it should also be np.
6
+ *
7
+ * The intent is to leave it "always on" for dev & tests, so that engineers
8
+ * and test suites can very easily grab "what was the render count of that?"
9
+ * w/o bringing in one-off modes/tools.
10
+ *
11
+ * (One-off modes/tools are more appropriate for truly adhoc performance
12
+ * but the intent is to use this in GridTable where "what's the render count?"
13
+ * will be a common question.)
14
+ */
15
+ export declare function useRenderCount(): {
16
+ getCount: (id: string) => object;
17
+ };
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useRenderCount = void 0;
4
+ const react_1 = require("react");
5
+ /**
6
+ * A hook to add `data-render=${count}` to an element.
7
+ *
8
+ * This will output even in production mode, which in theory is not necessary
9
+ * and we could/should avoid, but it should also be np.
10
+ *
11
+ * The intent is to leave it "always on" for dev & tests, so that engineers
12
+ * and test suites can very easily grab "what was the render count of that?"
13
+ * w/o bringing in one-off modes/tools.
14
+ *
15
+ * (One-off modes/tools are more appropriate for truly adhoc performance
16
+ * but the intent is to use this in GridTable where "what's the render count?"
17
+ * will be a common question.)
18
+ */
19
+ function useRenderCount() {
20
+ const ref = (0, react_1.useRef)(new Map());
21
+ const getCount = (0, react_1.useCallback)((id) => {
22
+ const count = ref.current.get(id) || 1;
23
+ ref.current.set(id, count + 1);
24
+ return { "data-render": count };
25
+ }, []);
26
+ return { getCount };
27
+ }
28
+ exports.useRenderCount = useRenderCount;
@@ -1,2 +1,4 @@
1
1
  export declare type TestIds = Record<string, object>;
2
2
  export declare function useTestIds(props: object, defaultPrefix?: string): Record<string, object>;
3
+ /** Uses `object` for any keys that exist on it, otherwise calls `methodMissing` fn. */
4
+ export declare function newMethodMissingProxy<T extends object, Y>(object: T, methodMissing: (key: string) => Y): T & Record<string, Y>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useTestIds = void 0;
3
+ exports.newMethodMissingProxy = exports.useTestIds = void 0;
4
4
  /**
5
5
  * Provides a way to easily generate `data-testid`s.
6
6
  *
@@ -59,3 +59,4 @@ function newMethodMissingProxy(object, methodMissing) {
59
59
  },
60
60
  });
61
61
  }
62
+ exports.newMethodMissingProxy = newMethodMissingProxy;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.107.0",
3
+ "version": "2.110.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",