@homebound/beam 2.177.2 → 2.179.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.
@@ -27,7 +27,7 @@ function Button(props) {
27
27
  ? utils_1.noop
28
28
  : (e) => {
29
29
  const result = onPress(e);
30
- if (isPromise(result)) {
30
+ if ((0, utils_1.isPromise)(result)) {
31
31
  setAsyncInProgress(true);
32
32
  result.finally(() => setAsyncInProgress(false));
33
33
  }
@@ -130,6 +130,3 @@ const iconStyles = {
130
130
  md: Css_1.Css.mr1.$,
131
131
  lg: Css_1.Css.mrPx(10).$,
132
132
  };
133
- function isPromise(obj) {
134
- return typeof obj === "object" && "then" in obj && typeof obj.then === "function";
135
- }
@@ -87,6 +87,7 @@ export declare const Icons: {
87
87
  calendar: import("@emotion/react/jsx-runtime").JSX.Element;
88
88
  buildingHouse: import("@emotion/react/jsx-runtime").JSX.Element;
89
89
  house: import("@emotion/react/jsx-runtime").JSX.Element;
90
+ bell: import("@emotion/react/jsx-runtime").JSX.Element;
90
91
  projects: import("@emotion/react/jsx-runtime").JSX.Element;
91
92
  tasks: import("@emotion/react/jsx-runtime").JSX.Element;
92
93
  finances: import("@emotion/react/jsx-runtime").JSX.Element;
@@ -60,7 +60,7 @@ exports.Icons = {
60
60
  helpCircle: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("path", { d: "M11.9999 6C9.83092 6 8.06592 7.765 8.06592 9.934H10.0659C10.0659 8.867 10.9339 8 11.9999 8C13.0659 8 13.9339 8.867 13.9339 9.934C13.9339 10.532 13.4529 10.966 12.7179 11.56C12.4629 11.767 12.2219 11.964 12.0269 12.159C11.0289 13.156 10.9999 14.215 10.9999 14.333V15H12.9999L12.9989 14.367C12.9999 14.351 13.0319 13.981 13.4399 13.574C13.5899 13.424 13.7789 13.274 13.9749 13.116C14.7539 12.485 15.9329 11.532 15.9329 9.934C15.9339 7.765 14.1689 6 11.9999 6ZM10.9999 16H12.9999V18H10.9999V16Z" }, void 0), (0, jsx_runtime_1.jsx)("path", { d: "M12 2C6.486 2 2 6.486 2 12C2 17.514 6.486 22 12 22C17.514 22 22 17.514 22 12C22 6.486 17.514 2 12 2ZM12 20C7.589 20 4 16.411 4 12C4 7.589 7.589 4 12 4C16.411 4 20 7.589 20 12C20 16.411 16.411 20 12 20Z" }, void 0)] }, void 0)),
61
61
  error: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("path", { d: "M11.001 10H13.001V15H11.001V10ZM11 16H13V18H11V16Z" }, void 0), (0, jsx_runtime_1.jsx)("path", { d: "M13.7679 4.19994C13.4199 3.54494 12.7419 3.13794 11.9999 3.13794C11.2579 3.13794 10.5799 3.54494 10.2319 4.20094L2.89392 18.0639C2.56292 18.6899 2.58292 19.4249 2.94792 20.0319C3.31292 20.6379 3.95292 20.9999 4.66092 20.9999H19.3389C20.0469 20.9999 20.6879 20.6379 21.0529 20.0319C21.4169 19.4259 21.4379 18.6899 21.1069 18.0639L13.7679 4.19994ZM4.66092 18.9999L11.9999 5.13694L19.3439 18.9999H4.66092Z" }, void 0)] }, void 0)),
62
62
  xCircle: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("path", { d: "M9.17181 16.2421L11.9998 13.4141L14.8278 16.2421L16.2418 14.8281L13.4138 12.0001L16.2418 9.17206L14.8278 7.75806L11.9998 10.5861L9.17181 7.75806L7.75781 9.17206L10.5858 12.0001L7.75781 14.8281L9.17181 16.2421Z" }, void 0), (0, jsx_runtime_1.jsx)("path", { d: "M12 22C17.514 22 22 17.514 22 12C22 6.486 17.514 2 12 2C6.486 2 2 6.486 2 12C2 17.514 6.486 22 12 22ZM12 4C16.411 4 20 7.589 20 12C20 16.411 16.411 20 12 20C7.589 20 4 16.411 4 12C4 7.589 7.589 4 12 4Z" }, void 0)] }, void 0)),
63
- flag: ((0, jsx_runtime_1.jsx)("path", { d: "M19 4H6V2H4V20H3V22H4H6H7V20H6V15H19C19.553 15 20 14.552 20 14V5C20 4.448 19.553 4 19 4Z" }, void 0)),
63
+ flag: (0, jsx_runtime_1.jsx)("path", { d: "M19 4H6V2H4V20H3V22H4H6H7V20H6V15H19C19.553 15 20 14.552 20 14V5C20 4.448 19.553 4 19 4Z" }, void 0),
64
64
  outlineFlag: ((0, jsx_runtime_1.jsx)("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M6 2H4V20H3V22H7V20H6V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H6V2ZM6 6V13H18V6H6Z" }, void 0)),
65
65
  // Arrows
66
66
  chevronsDown: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("path", { d: "M12 15.586L7.70697 11.293L6.29297 12.707L12 18.414L17.707 12.707L16.293 11.293L12 15.586Z" }, void 0), (0, jsx_runtime_1.jsx)("path", { d: "M17.707 7.70697L16.293 6.29297L12 10.586L7.70697 6.29297L6.29297 7.70697L12 13.414L17.707 7.70697Z" }, void 0)] }, void 0)),
@@ -92,6 +92,7 @@ exports.Icons = {
92
92
  calendar: ((0, jsx_runtime_1.jsx)("path", { d: "M2.99902 6V8V20C2.99902 21.103 3.89602 22 4.99902 22H18.999C20.102 22 20.999 21.103 20.999 20V8V6C20.999 4.897 20.102 4 18.999 4H16.999V2H14.999V4H8.99902V2H6.99902V4H4.99902C3.89602 4 2.99902 4.897 2.99902 6ZM19.001 20H4.99902V8H18.999L19.001 20Z" }, void 0)),
93
93
  buildingHouse: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("path", { d: "M19.0002 2.00002H9.00019C7.89719 2.00002 7.00019 2.89702 7.00019 4.00002V9.58602L2.29319 14.293C2.00719 14.579 1.92119 15.009 2.07619 15.383C2.23119 15.757 2.59619 16 3.00019 16V17V21C3.00019 21.553 3.44819 22 4.00019 22H12.0002H20.0002C20.5532 22 21.0002 21.553 21.0002 21V4.00002C21.0002 2.89702 20.1032 2.00002 19.0002 2.00002ZM11.0002 20H5.00019V17V15V14.414L8.00019 11.414L11.0002 14.414V15V18V20ZM19.0002 20H13.0002V18V16C13.4042 16 13.7702 15.757 13.9242 15.383C14.0792 15.009 13.9932 14.579 13.7072 14.293L9.00019 9.58602V4.00002H19.0002V20Z" }, void 0), (0, jsx_runtime_1.jsx)("path", { d: "M11 6.00002H13V8.00002H11V6.00002ZM15 6.00002H17V8.00002H15V6.00002ZM15 10.031H17V12H15V10.031ZM15 14H17V16H15V14ZM7 15H9V17H7V15Z" }, void 0)] }, void 0)),
94
94
  house: ((0, jsx_runtime_1.jsx)("path", { d: "M5.00299 22H9.00299H15.003H19.003C20.106 22 21.003 21.103 21.003 20V11C21.003 10.735 20.898 10.48 20.71 10.293L12.71 2.29301C12.319 1.90201 11.687 1.90201 11.296 2.29301L3.29599 10.293C3.10799 10.48 3.00299 10.735 3.00299 11V20C3.00299 21.103 3.89999 22 5.00299 22ZM10.003 20V15H14.003V20H10.003ZM5.00299 11.414L12.003 4.41401L19.003 11.414L19.004 20H16.003V15C16.003 13.897 15.106 13 14.003 13H10.003C8.89999 13 8.00299 13.897 8.00299 15V20H5.00299V11.414Z" }, void 0)),
95
+ bell: ((0, jsx_runtime_1.jsx)("path", { d: "M19 13.586V10C19 6.783 16.815 4.073 13.855 3.258C13.562 2.52 12.846 2 12 2C11.154 2 10.438 2.52 10.145 3.258C7.185 4.074 5 6.783 5 10V13.586L3.293 15.293C3.105 15.48 3 15.734 3 16V18C3 18.553 3.447 19 4 19H20C20.553 19 21 18.553 21 18V16C21 15.734 20.895 15.48 20.707 15.293L19 13.586ZM19 17H5V16.414L6.707 14.707C6.895 14.52 7 14.266 7 14V10C7 7.243 9.243 5 12 5C14.757 5 17 7.243 17 10V14C17 14.266 17.105 14.52 17.293 14.707L19 16.414V17ZM12 22C13.311 22 14.407 21.166 14.818 20H9.182C9.593 21.166 10.689 22 12 22Z" }, void 0)),
95
96
  // Navigation
96
97
  projects: ((0, jsx_runtime_1.jsx)("path", { d: "M4 6H6V8H4V6ZM4 11H6V13H4V11ZM4 16H6V18H4V16ZM20 8V6H18.8H9.2H8.023V8H9.2H18.8H20ZM8 11H20V13H8V11ZM8 16H20V18H8V16Z" }, void 0)),
97
98
  tasks: ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("path", { d: "M5 22H19C20.103 22 21 21.103 21 20V5C21 3.897 20.103 3 19 3H17C17 2.447 16.553 2 16 2H8C7.447 2 7 2.447 7 3H5C3.897 3 3 3.897 3 5V20C3 21.103 3.897 22 5 22ZM5 5H7V7H17V5H19V20H5V5Z" }, void 0), (0, jsx_runtime_1.jsx)("path", { d: "M11 13.586L9.20697 11.793L7.79297 13.207L11 16.414L16.207 11.207L14.793 9.79297L11 13.586Z" }, void 0)] }, void 0)),
@@ -169,8 +169,6 @@ export interface GridTableProps<R extends Kinded, S, X> {
169
169
  filterMaxRows?: number;
170
170
  /** Accepts the number of filtered rows (based on `filter`), for the caller to observe and display if they want. */
171
171
  setRowCount?: (rowCount: number) => void;
172
- /** Sets the rows to be wrapped by mobx observers. */
173
- observeRows?: boolean;
174
172
  /** A combination of CSS settings to set the static look & feel (vs. rowStyles which is per-row styling). */
175
173
  style?: GridStyle | GridStyleDef;
176
174
  /**
@@ -191,6 +189,11 @@ export interface GridTableProps<R extends Kinded, S, X> {
191
189
  * Example "data_123"
192
190
  */
193
191
  activeRowId?: string;
192
+ /**
193
+ * Defines which cell in the table should be provided with an "active" styling.
194
+ * Expected format is `${row.kind}_${row.id}_${column.name}`.
195
+ */
196
+ activeCellId?: string;
194
197
  }
195
198
  /**
196
199
  * Renders data in our table layout.
@@ -271,10 +274,12 @@ export declare type GridColumn<R extends Kinded, S = {}> = {
271
274
  wrapAction?: false;
272
275
  /** Used as a signal to defer adding the 'indent' styling */
273
276
  isAction?: true;
277
+ /** Column name that will be used to generate an unique identifier for every row cell */
278
+ name?: string;
274
279
  };
275
280
  export declare const nonKindGridColumnKeys: string[];
276
281
  /** Allows rendering a specific cell. */
277
- declare type RenderCellFn<R extends Kinded> = (idx: number, css: Properties, content: ReactNode, row: R, rowStyle: RowStyle<R> | undefined, classNames: string | undefined) => ReactNode;
282
+ declare type RenderCellFn<R extends Kinded> = (idx: number, css: Properties, content: ReactNode, row: R, rowStyle: RowStyle<R> | undefined, classNames: string | undefined, onClick: (() => void) | undefined) => ReactNode;
278
283
  /** Defines row-specific styling for each given row `kind` in `R` */
279
284
  export declare type GridRowStyles<R extends Kinded> = {
280
285
  [P in R["kind"]]?: RowStyle<DiscriminateUnion<R, "kind", P>>;
@@ -89,7 +89,7 @@ exports.setGridTableDefaults = setGridTableDefaults;
89
89
  */
90
90
  function GridTable(props) {
91
91
  var _a, _b, _c, _d;
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;
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, persistCollapse, resizeTarget, activeRowId, activeCellId, } = 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
95
  // Use this ref to watch for changes in the GridTable's container and resize columns accordingly.
@@ -99,6 +99,7 @@ function GridTable(props) {
99
99
  const api = (_a = props.api) !== null && _a !== void 0 ? _a : new GridTableApi_1.GridTableApiImpl();
100
100
  api.init(persistCollapse, virtuosoRef, rows);
101
101
  api.setActiveRowId(activeRowId);
102
+ api.setActiveCellId(activeCellId);
102
103
  return api;
103
104
  }, [props.api]);
104
105
  const style = resolveStyles(maybeStyle);
@@ -107,6 +108,9 @@ function GridTable(props) {
107
108
  (0, react_1.useEffect)(() => {
108
109
  rowState.activeRowId = activeRowId;
109
110
  }, [rowState, activeRowId]);
111
+ (0, react_1.useEffect)(() => {
112
+ rowState.activeCellId = activeCellId;
113
+ }, [rowState, activeCellId]);
110
114
  // We track render count at the table level, which seems odd (we should be able to track this
111
115
  // internally within each GridRow using a useRef), but we have suspicions that react-virtuoso
112
116
  // (or us) is resetting component state more than necessary, so we track render counts from
@@ -130,8 +134,7 @@ function GridTable(props) {
130
134
  // We only pass sortState to header rows, b/c non-headers rows shouldn't have to re-render on sorting
131
135
  // changes, and so by not passing the sortProps, it means the data rows' React.memo will still cache them.
132
136
  const sortProps = row.kind === "header" ? { sortOn, sortState, setSortKey } : { sortOn };
133
- const RowComponent = observeRows ? ObservedGridRow : MemoizedGridRow;
134
- return ((0, jsx_runtime_1.jsx)(RowComponent, Object.assign({}, {
137
+ return ((0, jsx_runtime_1.jsx)(MemoizedGridRow, Object.assign({}, {
135
138
  as,
136
139
  columns,
137
140
  row,
@@ -203,7 +206,6 @@ function GridTable(props) {
203
206
  sortState,
204
207
  stickyHeader,
205
208
  stickyOffset,
206
- observeRows,
207
209
  columnSizes,
208
210
  collapsedIds,
209
211
  getCount,
@@ -265,7 +267,7 @@ function renderDiv(style, id, columns, headerRows, totalsRows, visibleDataRows,
265
267
  the + operator as an offset.
266
268
  Inspired by: https://stackoverflow.com/a/25005740/2551333
267
269
  */
268
- ...(style.betweenRowsCss ? Css_1.Css.addIn(`& > div:nth-of-type(n+3) > *`, style.betweenRowsCss).$ : {}),
270
+ ...(style.betweenRowsCss ? Css_1.Css.addIn(`& > div:nth-of-type(n+${headerRows.length + totalsRows.length + 2}) > *`, style.betweenRowsCss).$ : {}),
269
271
  ...(style.firstNonHeaderRowCss ? Css_1.Css.addIn(`& > div:nth-of-type(2) > *`, style.firstNonHeaderRowCss).$ : {}),
270
272
  ...style.rootCss,
271
273
  ...(style.minWidthPx ? Css_1.Css.mwPx(style.minWidthPx).$ : {}),
@@ -478,7 +480,8 @@ function GridRow(props) {
478
480
  var _a;
479
481
  const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sortOn, sortState, setSortKey, openCards, columnSizes, level, getCount, api, ...others } = props;
480
482
  const { rowState } = (0, react_1.useContext)(RowState_1.RowStateContext);
481
- const isActive = (0, hooks_1.useComputed)(() => rowState.activeRowId === `${row.kind}_${row.id}`, [row, rowState]);
483
+ const rowId = `${row.kind}_${row.id}`;
484
+ const isActive = (0, hooks_1.useComputed)(() => rowState.activeRowId === rowId, [rowId, rowState]);
482
485
  // We treat the "header" and "totals" kind as special for "good defaults" styling
483
486
  const isHeader = row.kind === "header";
484
487
  const isTotals = row.kind === "totals";
@@ -557,6 +560,9 @@ function GridRow(props) {
557
560
  : {}),
558
561
  }
559
562
  : {};
563
+ const cellId = `${row.kind}_${row.id}_${column.name}`;
564
+ const applyCellHighlight = !!column.name && !isHeader && !isTotals;
565
+ const isCellActive = rowState.activeCellId === cellId;
560
566
  // Note that it seems expensive to calc a per-cell class name/CSS-in-JS output,
561
567
  // vs. setting global/table-wide CSS like `style.cellCss` on the root grid div with
562
568
  // a few descendent selectors. However, that approach means the root grid-applied
@@ -596,6 +602,8 @@ function GridRow(props) {
596
602
  ...(isGridCellContent(maybeContent) && maybeContent.typeScale ? Css_1.Css[maybeContent.typeScale].$ : {}),
597
603
  // And any cell specific css
598
604
  ...(isGridCellContent(maybeContent) && maybeContent.css ? maybeContent.css : {}),
605
+ // Apply cell highlight styles to active cell and hover
606
+ ...Css_1.Css.if(applyCellHighlight && isCellActive).br4.boxShadow(`inset 0 0 0 1px ${Css_1.Palette.LightBlue700}`).$,
599
607
  // Define the width of the column on each cell. Supports col spans.
600
608
  ...{
601
609
  width: `calc(${columnSizes
@@ -605,6 +613,7 @@ function GridRow(props) {
605
613
  ...(column.mw ? Css_1.Css.mw(column.mw).$ : {}),
606
614
  };
607
615
  const cellClassNames = revealOnRowHover ? revealOnRowHoverClass : undefined;
616
+ const cellOnClick = applyCellHighlight ? () => api.setActiveCellId(cellId) : undefined;
608
617
  const renderFn = ((rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.renderCell) || (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowLink)) && wrapAction
609
618
  ? rowLinkRenderFn(as)
610
619
  : isHeader
@@ -612,7 +621,7 @@ function GridRow(props) {
612
621
  : (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.onClick) && wrapAction
613
622
  ? rowClickRenderFn(as, api)
614
623
  : defaultRenderFn(as);
615
- return renderFn(columnIndex, cellCss, content, row, rowStyle, cellClassNames);
624
+ return renderFn(columnIndex, cellCss, content, row, rowStyle, cellClassNames, cellOnClick);
616
625
  }) }), void 0));
617
626
  return openCardStyles && openCardStyles.length > 0 ? (0, nestedCards_1.wrapCard)(openCardStyles, rowNode) : rowNode;
618
627
  }
@@ -628,7 +637,7 @@ function GridRow(props) {
628
637
  * memoization is.
629
638
  */
630
639
  // Declared as a const + `as typeof GridRow` to work with generics, see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/37087#issuecomment-656596623
631
- const MemoizedGridRow = react_1.default.memo(GridRow, (one, two) => {
640
+ const MemoizedGridRow = react_1.default.memo((0, mobx_react_1.observer)(GridRow), (one, two) => {
632
641
  const { row: row1, ...others1 } = one;
633
642
  const { row: row2, ...others2 } = two;
634
643
  return (0, shallowEqual_1.shallowEqual)(row1, row2) && (0, shallowEqual_1.shallowEqual)(others1, others2);
@@ -703,9 +712,9 @@ function applyRowFn(column, row, api, level) {
703
712
  }
704
713
  exports.applyRowFn = applyRowFn;
705
714
  /** Renders our default cell element, i.e. if no row links and no custom renderCell are used. */
706
- const defaultRenderFn = (as) => (key, css, content, row, rowStyle, classNames) => {
715
+ const defaultRenderFn = (as) => (key, css, content, row, rowStyle, classNames, onClick) => {
707
716
  const Cell = as === "table" ? "td" : "div";
708
- return ((0, jsx_runtime_1.jsx)(Cell, Object.assign({ css: { ...css, ...tableRowStyles(as) }, className: classNames }, { children: content }), key));
717
+ return ((0, jsx_runtime_1.jsx)(Cell, Object.assign({ css: { ...css, ...tableRowStyles(as) }, className: classNames, onClick: onClick }, { children: content }), key));
709
718
  };
710
719
  /** Sets up the `GridContext` so that header cells can access the current sort settings. */
711
720
  const headerRenderFn = (columns, column, sortState, setSortKey, as) => (key, css, content, row, rowStyle, classNames) => {
@@ -728,9 +737,12 @@ const rowLinkRenderFn = (as) => (key, css, content, row, rowStyle, classNames) =
728
737
  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} ${classNames}` }, { children: content }), key));
729
738
  };
730
739
  /** Renders a cell that will fire the RowStyle.onClick. */
731
- const rowClickRenderFn = (as, api) => (key, css, content, row, rowStyle, classNames) => {
740
+ const rowClickRenderFn = (as, api) => (key, css, content, row, rowStyle, classNames, onClick) => {
732
741
  const Row = as === "table" ? "tr" : "div";
733
- return ((0, jsx_runtime_1.jsx)(Row, Object.assign({}, { key }, { css: { ...css, ...tableRowStyles(as) }, className: classNames, onClick: () => rowStyle.onClick(row, api) }, { children: content }), void 0));
742
+ return ((0, jsx_runtime_1.jsx)(Row, Object.assign({}, { key }, { css: { ...css, ...tableRowStyles(as) }, className: classNames, onClick: (e) => {
743
+ rowStyle.onClick(row, api);
744
+ onClick && onClick();
745
+ } }, { children: content }), void 0));
734
746
  };
735
747
  const alignmentToJustify = {
736
748
  left: "flex-start",
@@ -796,7 +808,7 @@ function tableRowStyles(as, column) {
796
808
  : {};
797
809
  }
798
810
  function resolveStyles(style) {
799
- const defKeys = ["inlineEditing", "grouped", "rowHeight"];
811
+ const defKeys = ["inlineEditing", "grouped", "rowHeight", "cellHighlight"];
800
812
  const keys = (0, utils_1.safeKeys)(style);
801
813
  if (keys.length === 0 || keys.some((k) => defKeys.includes(k))) {
802
814
  return (0, styles_1.getTableStyles)(style);
@@ -32,6 +32,8 @@ export declare type GridTableApi<R extends Kinded> = {
32
32
  clearSelections(): void;
33
33
  /** Sets the internal state of 'activeRowId' */
34
34
  setActiveRowId: (id: string | undefined) => void;
35
+ /** Sets the internal state of 'activeCellId' */
36
+ setActiveCellId: (id: string | undefined) => void;
35
37
  /** Set selected state of a row by id */
36
38
  selectRow: (id: string, selected?: boolean) => void;
37
39
  };
@@ -45,5 +47,6 @@ export declare class GridTableApiImpl<R extends Kinded> implements GridTableApi<
45
47
  getSelectedRows(kind?: string): any;
46
48
  clearSelections(id?: string): void;
47
49
  setActiveRowId(id: string | undefined): void;
50
+ setActiveCellId(id: string | undefined): void;
48
51
  selectRow(id: string, selected?: boolean): void;
49
52
  }
@@ -59,6 +59,9 @@ class GridTableApiImpl {
59
59
  setActiveRowId(id) {
60
60
  this.rowState.activeRowId = id;
61
61
  }
62
+ setActiveCellId(id) {
63
+ this.rowState.activeCellId = id;
64
+ }
62
65
  selectRow(id, selected = true) {
63
66
  this.rowState.selectRow(id, selected);
64
67
  }
@@ -23,6 +23,7 @@ export declare class RowState {
23
23
  private matchedRows;
24
24
  rows: GridDataRow<any>[];
25
25
  activeRowId: string | undefined;
26
+ activeCellId: string | undefined;
26
27
  /**
27
28
  * Creates the `RowState` for a given `GridTable`.
28
29
  */
@@ -36,6 +36,8 @@ class RowState {
36
36
  this.rows = [];
37
37
  // Keeps track of the 'active' row, formatted `${row.kind}_${row.id}`
38
38
  this.activeRowId = undefined;
39
+ // Keeps track of the 'active' cell, formatted `${row.kind}_${row.id}_${column.name}`
40
+ this.activeCellId = undefined;
39
41
  // Make ourselves an observable so that mobx will do caching of .collapseIds so
40
42
  // that it'll be a stable identity for GridTable to useMemo against.
41
43
  (0, mobx_1.makeAutoObservable)(this,
@@ -9,5 +9,7 @@ export interface GridStyleDef {
9
9
  inlineEditing?: boolean;
10
10
  grouped?: boolean;
11
11
  rowHeight?: "fixed" | "flexible";
12
+ /** Enables cells Highlight and hover */
13
+ cellHighlight?: boolean;
12
14
  }
13
15
  export declare const getTableStyles: (props?: GridStyleDef | undefined) => GridStyle;
@@ -44,7 +44,7 @@ exports.cardStyle = {
44
44
  function memoizedTableStyles() {
45
45
  const cache = {};
46
46
  return (props) => {
47
- const { inlineEditing = false, grouped = false, rowHeight = "flexible" } = props || {};
47
+ const { inlineEditing = false, grouped = false, rowHeight = "flexible", cellHighlight } = props || {};
48
48
  const key = `${inlineEditing}|${grouped}|${rowHeight}`;
49
49
  if (!cache[key]) {
50
50
  const groupedLevels = {
@@ -63,6 +63,7 @@ function memoizedTableStyles() {
63
63
  cellCss: {
64
64
  ...Css_1.Css.gray900.xs.bgWhite.aic.pxPx(12).boxShadow(`inset 0 -1px 0 ${Css_1.Palette.Gray200}`).$,
65
65
  ...(rowHeight === "flexible" ? Css_1.Css.pyPx(12).$ : Css_1.Css.nowrap.hPx(inlineEditing ? 48 : 36).$),
66
+ ...(cellHighlight ? { "&:hover": Css_1.Css.bgGray100.$ } : {})
66
67
  },
67
68
  presentationSettings: { borderless: true, typeScale: "xs", wrap: rowHeight === "flexible" },
68
69
  levels: grouped ? groupedLevels : defaultLevels,
@@ -56,7 +56,7 @@ function FormStateApp() {
56
56
  { value: "a:4", label: "Iguana" },
57
57
  { value: "a:5", label: "Turtle" },
58
58
  ];
59
- return ((0, jsx_runtime_1.jsx)(mobx_react_1.Observer, { children: () => ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.$ }, { children: [(0, jsx_runtime_1.jsxs)("header", Object.assign({ css: Css_1.Css.wPx(700).$ }, { children: [(0, jsx_runtime_1.jsxs)(FormLines_1.FormLines, Object.assign({ labelSuffix: { required: "*", optional: "(Opt)" } }, { children: [(0, jsx_runtime_1.jsx)("b", { children: "Author" }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundTextField, { field: formState.firstName }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundTextField, { field: formState.middleInitial }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundTextField, { field: formState.lastName }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundDateField, { field: formState.birthday }, void 0), (0, jsx_runtime_1.jsxs)(forms_1.FieldGroup, { children: [(0, jsx_runtime_1.jsx)(forms_1.StaticField, { label: "Revenue", value: "$500" }, void 0), (0, jsx_runtime_1.jsx)(forms_1.StaticField, Object.assign({ label: "Website" }, { children: (0, jsx_runtime_1.jsx)("a", Object.assign({ href: "https://google.com" }, { children: "google.com" }), void 0) }), void 0)] }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundNumberField, { field: formState.heightInInches }, void 0), (0, jsx_runtime_1.jsx)(forms_1.FormDivider, {}, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundSelectField, { field: formState.favoriteSport, options: sports }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundMultiSelectField, { field: formState.favoriteShapes, options: shapes }, void 0), (0, jsx_runtime_1.jsx)(BoundCheckboxGroupField_1.BoundCheckboxGroupField, { field: formState.favoriteColors, options: colors }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundToggleChipGroupField, { field: formState.animals, options: animals }, void 0), (0, jsx_runtime_1.jsx)(forms_1.FormDivider, {}, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundSwitchField, { field: formState.isAvailable }, void 0)] }), void 0), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("strong", { children: ["Books", (0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "plus", onClick: () => formState.books.add({ id: String(formState.books.value.length) }) }, void 0)] }, void 0), (0, jsx_runtime_1.jsx)(components_1.GridTable, { columns: columns, rows: rows, observeRows: true }, void 0)] }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.childGap1.$ }, { children: [(0, jsx_runtime_1.jsx)(components_1.Button, { onClick: () => formState.revertChanges(), label: "Cancel" }, void 0), (0, jsx_runtime_1.jsx)(components_1.Button, { onClick: () => {
59
+ return ((0, jsx_runtime_1.jsx)(mobx_react_1.Observer, { children: () => ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.$ }, { children: [(0, jsx_runtime_1.jsxs)("header", Object.assign({ css: Css_1.Css.wPx(700).$ }, { children: [(0, jsx_runtime_1.jsxs)(FormLines_1.FormLines, Object.assign({ labelSuffix: { required: "*", optional: "(Opt)" } }, { children: [(0, jsx_runtime_1.jsx)("b", { children: "Author" }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundTextField, { field: formState.firstName }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundTextField, { field: formState.middleInitial }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundTextField, { field: formState.lastName }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundDateField, { field: formState.birthday }, void 0), (0, jsx_runtime_1.jsxs)(forms_1.FieldGroup, { children: [(0, jsx_runtime_1.jsx)(forms_1.StaticField, { label: "Revenue", value: "$500" }, void 0), (0, jsx_runtime_1.jsx)(forms_1.StaticField, Object.assign({ label: "Website" }, { children: (0, jsx_runtime_1.jsx)("a", Object.assign({ href: "https://google.com" }, { children: "google.com" }), void 0) }), void 0)] }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundNumberField, { field: formState.heightInInches }, void 0), (0, jsx_runtime_1.jsx)(forms_1.FormDivider, {}, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundSelectField, { field: formState.favoriteSport, options: sports }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundMultiSelectField, { field: formState.favoriteShapes, options: shapes }, void 0), (0, jsx_runtime_1.jsx)(BoundCheckboxGroupField_1.BoundCheckboxGroupField, { field: formState.favoriteColors, options: colors }, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundToggleChipGroupField, { field: formState.animals, options: animals }, void 0), (0, jsx_runtime_1.jsx)(forms_1.FormDivider, {}, void 0), (0, jsx_runtime_1.jsx)(forms_1.BoundSwitchField, { field: formState.isAvailable }, void 0)] }), void 0), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("strong", { children: ["Books", (0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "plus", onClick: () => formState.books.add({ id: String(formState.books.value.length) }) }, void 0)] }, void 0), (0, jsx_runtime_1.jsx)(components_1.GridTable, { columns: columns, rows: rows }, void 0)] }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.childGap1.$ }, { children: [(0, jsx_runtime_1.jsx)(components_1.Button, { onClick: () => formState.revertChanges(), label: "Cancel" }, void 0), (0, jsx_runtime_1.jsx)(components_1.Button, { onClick: () => {
60
60
  if (formState.canSave()) {
61
61
  formState.commitChanges();
62
62
  }
@@ -72,7 +72,7 @@ function AuthorDetails({ formState, onNext }) {
72
72
  function BookList({ formState, onNext, onBack }) {
73
73
  const columns = (0, react_1.useMemo)(() => createColumns(formState), [formState]);
74
74
  const rows = (0, hooks_1.useComputed)(() => [components_1.simpleHeader, ...formState.books.rows.map((data) => ({ kind: "data", id: data.id.value, data }))], []);
75
- return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("h1", Object.assign({ css: Css_1.Css.df.aic.$ }, { children: ["Books", (0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "plus", onClick: () => { var _a; return formState.books.add({ id: String(((_a = formState.books.value) === null || _a === void 0 ? void 0 : _a.length) || 1) }); } }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)(components_1.GridTable, { columns: columns, rows: rows, observeRows: true }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.jcsb.bt.bGray300.py1.mt2.$ }, { children: [(0, jsx_runtime_1.jsx)(components_1.Button, { variant: "tertiary", label: "Back", onClick: onBack }, void 0), (0, jsx_runtime_1.jsx)(components_1.Button, { label: "Continue to Misc.", disabled: !formState.books.valid, onClick: onNext }, void 0)] }), void 0)] }, void 0));
75
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsxs)("h1", Object.assign({ css: Css_1.Css.df.aic.$ }, { children: ["Books", (0, jsx_runtime_1.jsx)(components_1.IconButton, { icon: "plus", onClick: () => { var _a; return formState.books.add({ id: String(((_a = formState.books.value) === null || _a === void 0 ? void 0 : _a.length) || 1) }); } }, void 0)] }), void 0), (0, jsx_runtime_1.jsx)(components_1.GridTable, { columns: columns, rows: rows }, void 0), (0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.jcsb.bt.bGray300.py1.mt2.$ }, { children: [(0, jsx_runtime_1.jsx)(components_1.Button, { variant: "tertiary", label: "Back", onClick: onBack }, void 0), (0, jsx_runtime_1.jsx)(components_1.Button, { label: "Continue to Misc.", disabled: !formState.books.valid, onClick: onNext }, void 0)] }), void 0)] }, void 0));
76
76
  }
77
77
  function createColumns(formState) {
78
78
  return [
@@ -0,0 +1,24 @@
1
+ import { ReactNode } from "react";
2
+ import { IconKey } from "../components";
3
+ export interface ToggleButtonProps {
4
+ /** Input label */
5
+ label: string;
6
+ selected?: boolean;
7
+ onChange: ((selected: boolean) => void) | ((selected: boolean) => Promise<void>);
8
+ autoFocus?: boolean;
9
+ icon?: IconKey;
10
+ /** Whether the field is disabled. If a ReactNode, it's treated as a "disabled reason" that's shown in a tooltip. */
11
+ disabled?: boolean | ReactNode;
12
+ tooltip?: ReactNode;
13
+ }
14
+ export declare function ToggleButton(props: ToggleButtonProps): import("@emotion/react/jsx-runtime").JSX.Element;
15
+ /** Styles */
16
+ export declare const toggleHoverStyles: {
17
+ backgroundColor: import("csstype").Property.BackgroundColor | undefined;
18
+ };
19
+ export declare const toggleFocusStyles: {
20
+ boxShadow: import("csstype").Property.BoxShadow | undefined;
21
+ };
22
+ export declare const togglePressStyles: {
23
+ backgroundColor: import("csstype").Property.BackgroundColor | undefined;
24
+ };
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.togglePressStyles = exports.toggleFocusStyles = exports.toggleHoverStyles = exports.ToggleButton = void 0;
4
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_aria_1 = require("react-aria");
7
+ const react_stately_1 = require("react-stately");
8
+ const components_1 = require("../components");
9
+ const Css_1 = require("../Css");
10
+ const utils_1 = require("../utils");
11
+ function ToggleButton(props) {
12
+ const { selected: isSelected = false, disabled = false, label, onChange, icon, ...otherProps } = props;
13
+ const [asyncInProgress, setAsyncInProgress] = (0, react_1.useState)(false);
14
+ const isDisabled = !!disabled || asyncInProgress;
15
+ const ariaProps = { "aria-label": label, isSelected, isDisabled, ...otherProps };
16
+ const state = (0, react_stately_1.useToggleState)({
17
+ ...ariaProps,
18
+ onChange: (e) => {
19
+ const result = onChange(e);
20
+ if ((0, utils_1.isPromise)(result)) {
21
+ setAsyncInProgress(true);
22
+ result.finally(() => setAsyncInProgress(false));
23
+ }
24
+ return result;
25
+ },
26
+ });
27
+ const labelRef = (0, react_1.useRef)(null);
28
+ const ref = (0, react_1.useRef)(null);
29
+ const tid = (0, utils_1.useTestIds)(props, label);
30
+ const { isPressed, pressProps } = (0, react_aria_1.usePress)({ ref: labelRef, isDisabled });
31
+ const { inputProps } = (0, react_aria_1.useSwitch)(ariaProps, state, ref);
32
+ const { isFocusVisible: isKeyboardFocus, focusProps } = (0, react_aria_1.useFocusRing)({ ...otherProps, within: true });
33
+ const { hoverProps, isHovered } = (0, react_aria_1.useHover)({ isDisabled });
34
+ const tooltip = (0, components_1.resolveTooltip)(disabled);
35
+ const labelAttrs = {
36
+ ...focusProps,
37
+ ...hoverProps,
38
+ ...pressProps,
39
+ css: {
40
+ ...Css_1.Css.br4.dif.aic.gap1.bgTransparent.gray500.hPx(32).plPx(4).pr1.relative.cursorPointer.w("max-content").smEm
41
+ .selectNone.$,
42
+ ...(isHovered && exports.toggleHoverStyles),
43
+ ...(isPressed && exports.togglePressStyles),
44
+ ...(isSelected && !isDisabled && Css_1.Css.lightBlue700.$),
45
+ ...(isKeyboardFocus && exports.toggleFocusStyles),
46
+ ...(isDisabled && Css_1.Css.gray300.cursorNotAllowed.$),
47
+ },
48
+ ...tid,
49
+ };
50
+ return (0, components_1.maybeTooltip)({
51
+ title: tooltip,
52
+ placement: "top",
53
+ children: ((0, jsx_runtime_1.jsxs)("label", Object.assign({}, labelAttrs, { children: [icon && (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: icon }, void 0), label, (0, jsx_runtime_1.jsx)(react_aria_1.VisuallyHidden, { children: (0, jsx_runtime_1.jsx)("input", Object.assign({ ref: ref }, inputProps, tid.value), void 0) }, void 0)] }), void 0)),
54
+ });
55
+ }
56
+ exports.ToggleButton = ToggleButton;
57
+ /** Styles */
58
+ // Toggle element styles
59
+ exports.toggleHoverStyles = Css_1.Css.bgGray100.$;
60
+ exports.toggleFocusStyles = Css_1.Css.bshFocus.$;
61
+ exports.togglePressStyles = Css_1.Css.bgGray300.$;
@@ -28,3 +28,4 @@ export declare class EmptyRef<T> implements MutableRefObject<T> {
28
28
  }
29
29
  export declare const isAbsoluteUrl: (url: string) => boolean;
30
30
  export declare function areArraysEqual(a: any[], b: any[]): boolean;
31
+ export declare function isPromise(obj: void | Promise<void>): obj is Promise<void>;
@@ -10,7 +10,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
10
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.areArraysEqual = exports.isAbsoluteUrl = exports.EmptyRef = exports.safeEntries = exports.noop = exports.omitKey = exports.safeKeys = exports.maybeCall = exports.toGroupState = exports.toToggleState = void 0;
13
+ exports.isPromise = exports.areArraysEqual = exports.isAbsoluteUrl = exports.EmptyRef = exports.safeEntries = exports.noop = exports.omitKey = exports.safeKeys = exports.maybeCall = exports.toGroupState = exports.toToggleState = void 0;
14
14
  /** Adapts our state to what useToggleState returns in a stateless manner. */
15
15
  function toToggleState(isSelected, onChange) {
16
16
  return {
@@ -78,3 +78,7 @@ function areArraysEqual(a, b) {
78
78
  return a.length === b.length && a.every((val, idx) => val === b[idx]);
79
79
  }
80
80
  exports.areArraysEqual = areArraysEqual;
81
+ function isPromise(obj) {
82
+ return typeof obj === "object" && "then" in obj && typeof obj.then === "function";
83
+ }
84
+ exports.isPromise = isPromise;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.177.2",
3
+ "version": "2.179.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",