@homebound/beam 2.118.0 → 2.118.1

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.
@@ -149,6 +149,7 @@ export interface GridTableProps<R extends Kinded, S, X> {
149
149
  /** Whether the header row should be sticky. */
150
150
  stickyHeader?: boolean;
151
151
  stickyOffset?: string;
152
+ /** Configures sorting via a hash, does not need to be stable. */
152
153
  sorting?: GridSortConfig<S>;
153
154
  /** Shown in the first row slot, if there are no rows to show, i.e. 'No rows found'. */
154
155
  fallbackMessage?: string;
@@ -85,7 +85,7 @@ exports.setGridTableDefaults = setGridTableDefaults;
85
85
  */
86
86
  function GridTable(props) {
87
87
  var _a, _b, _c, _d;
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;
88
+ const { id = "gridTable", as = "div", columns, rows, style = defaults.style, rowStyles, stickyHeader = defaults.stickyHeader, stickyOffset = "0", xss, filter, filterMaxRows, fallbackMessage = "No rows found.", infoMessage, setRowCount, observeRows, persistCollapse, api: callerApi, resizeTarget, activeRowId, } = props;
89
89
  // Create a ref that always contains the latest rows, for our effectively-singleton RowState to use
90
90
  const rowsRef = (0, react_1.useRef)(rows);
91
91
  rowsRef.current = rows;
@@ -130,14 +130,14 @@ function GridTable(props) {
130
130
  const columnSizes = (0, columnSizes_1.useSetupColumnSizes)(style, columns, tableRef, resizeTarget);
131
131
  // Make a single copy of our current collapsed state, so we'll have a single observer.
132
132
  const collapsedIds = (0, hooks_1.useComputed)(() => rowState.collapsedIds, [rowState]);
133
- const [sortState, setSortKey] = (0, useSortState_1.useSortState)(columns, sorting);
133
+ const [sortState, setSortKey, sortOn] = (0, useSortState_1.useSortState)(columns, props.sorting);
134
134
  const maybeSorted = (0, react_1.useMemo)(() => {
135
- if ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client" && sortState) {
135
+ if (sortOn === "client" && sortState) {
136
136
  // If using client-side sort, the sortState use S = number
137
137
  return (0, sortRows_1.sortRows)(columns, rows, sortState);
138
138
  }
139
139
  return rows;
140
- }, [columns, rows, sorting, sortState]);
140
+ }, [columns, rows, sortOn, sortState]);
141
141
  // Filter rows - ensures parent rows remain in the list if any children match the filter.
142
142
  const filterRows = (0, react_1.useCallback)((acc, row) => {
143
143
  var _a, _b, _c;
@@ -163,13 +163,13 @@ function GridTable(props) {
163
163
  }
164
164
  }
165
165
  return acc;
166
- }, [filter, collapsedIds]);
166
+ }, [filter, collapsedIds, columns]);
167
167
  // Flatten + component-ize the sorted rows.
168
168
  let [headerRows, filteredRows] = (0, react_1.useMemo)(() => {
169
169
  function makeRowComponent(row, level) {
170
170
  // We only pass sortState to header rows, b/c non-headers rows shouldn't have to re-render on sorting
171
171
  // changes, and so by not passing the sortProps, it means the data rows' React.memo will still cache them.
172
- const sortProps = row.kind === "header" ? { sorting, sortState, setSortKey } : { sorting };
172
+ const sortProps = row.kind === "header" ? { sortOn, sortState, setSortKey } : { sortOn };
173
173
  const RowComponent = observeRows ? ObservedGridRow : MemoizedGridRow;
174
174
  return ((0, jsx_runtime_1.jsx)(RowComponent, Object.assign({}, {
175
175
  as,
@@ -222,10 +222,10 @@ function GridTable(props) {
222
222
  as,
223
223
  maybeSorted,
224
224
  columns,
225
- filter,
225
+ filterRows,
226
226
  style,
227
227
  rowStyles,
228
- sorting,
228
+ sortOn,
229
229
  setSortKey,
230
230
  sortState,
231
231
  stickyHeader,
@@ -484,7 +484,7 @@ function getFirstOrLastCellCss(style, columnIndex, columns) {
484
484
  // We extract GridRow to its own mini-component primarily so we can React.memo'ize it.
485
485
  function GridRow(props) {
486
486
  var _a;
487
- const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sorting, sortState, setSortKey, openCards, columnSizes, level, getCount, api, ...others } = props;
487
+ const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sortOn, sortState, setSortKey, openCards, columnSizes, level, getCount, api, ...others } = props;
488
488
  const { rowState } = (0, react_1.useContext)(RowState_1.RowStateContext);
489
489
  const isActive = (0, hooks_1.useComputed)(() => rowState.activeRowId === `${row.kind}_${row.id}`, [row, rowState]);
490
490
  // We treat the "header" kind as special for "good defaults" styling
@@ -527,12 +527,12 @@ function GridRow(props) {
527
527
  }
528
528
  const maybeContent = applyRowFn(column, row, api);
529
529
  currentColspan = isGridCellContent(maybeContent) ? (_a = maybeContent.colspan) !== null && _a !== void 0 ? _a : 1 : 1;
530
- const canSortColumn = ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client" && column.clientSideSort !== false) ||
531
- ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "server" && !!column.serverSideSortKey);
530
+ const canSortColumn = (sortOn === "client" && column.clientSideSort !== false) ||
531
+ (sortOn === "server" && !!column.serverSideSortKey);
532
532
  const alignment = getAlignment(column, maybeContent);
533
533
  const justificationCss = getJustification(column, maybeContent, as, alignment);
534
- const content = toContent(maybeContent, isHeader, canSortColumn, (sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client", style, as, alignment);
535
- (0, sortRows_1.ensureClientSideSortValueIsSortable)(sorting, isHeader, column, columnIndex, maybeContent);
534
+ const content = toContent(maybeContent, isHeader, canSortColumn, sortOn === "client", style, as, alignment);
535
+ (0, sortRows_1.ensureClientSideSortValueIsSortable)(sortOn, isHeader, column, columnIndex, maybeContent);
536
536
  const maybeNestedCardColumnIndex = columnIndex + (style.nestedCards ? 1 : 0);
537
537
  const maybeSticky = (_b = ((isGridCellContent(maybeContent) && maybeContent.sticky) || column.sticky)) !== null && _b !== void 0 ? _b : undefined;
538
538
  const maybeStickyColumnStyles = maybeSticky && columnSizes
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from "react";
2
- import { GridCellContent, GridColumn, GridDataRow, GridSortConfig, Kinded } from "./GridTable";
3
- import { SortState } from "./useSortState";
2
+ import { GridCellContent, GridColumn, GridDataRow, Kinded } from "./GridTable";
3
+ import { SortOn, SortState } from "./useSortState";
4
4
  export declare function sortRows<R extends Kinded>(columns: GridColumn<R>[], rows: GridDataRow<R>[], sortState: SortState<number>): GridDataRow<R>[];
5
- export declare function ensureClientSideSortValueIsSortable(sorting: GridSortConfig<any> | undefined, isHeader: boolean, column: GridColumn<any>, idx: number, maybeContent: ReactNode | GridCellContent): void;
5
+ export declare function ensureClientSideSortValueIsSortable(sortOn: SortOn, isHeader: boolean, column: GridColumn<any>, idx: number, maybeContent: ReactNode | GridCellContent): void;
@@ -64,11 +64,8 @@ function sortValue(value) {
64
64
  }
65
65
  return maybeFn;
66
66
  }
67
- function ensureClientSideSortValueIsSortable(sorting, isHeader, column, idx, maybeContent) {
68
- if (process.env.NODE_ENV !== "production" &&
69
- !isHeader &&
70
- (sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client" &&
71
- column.clientSideSort !== false) {
67
+ function ensureClientSideSortValueIsSortable(sortOn, isHeader, column, idx, maybeContent) {
68
+ if (process.env.NODE_ENV !== "production" && !isHeader && sortOn === "client" && column.clientSideSort !== false) {
72
69
  const value = sortValue(maybeContent);
73
70
  if (!canClientSideSort(value)) {
74
71
  throw new Error(`Column ${idx} passed an unsortable value, use GridCellContent or clientSideSort=false`);
@@ -8,6 +8,7 @@ import { Direction, GridColumn, GridSortConfig, Kinded } from "./GridTable";
8
8
  * b) it's index in the `columns` array, if client-side sorting
9
9
  */
10
10
  export declare type SortState<S> = readonly [S, Direction];
11
+ export declare type SortOn = "client" | "server" | undefined;
11
12
  /** Small custom hook that wraps the "setSortColumn inverts the current sort" logic. */
12
- export declare function useSortState<R extends Kinded, S>(columns: GridColumn<R, S>[], sorting?: GridSortConfig<S>): [SortState<S> | undefined, (value: S) => void];
13
+ export declare function useSortState<R extends Kinded, S>(columns: GridColumn<R, S>[], sorting?: GridSortConfig<S>): [SortState<S> | undefined, (value: S) => void, SortOn];
13
14
  export declare function deriveSortState<S>(currentSortState: SortState<S> | undefined, clickedKey: S, initialSortState: SortState<S> | undefined): SortState<S> | undefined;
@@ -28,20 +28,26 @@ function useSortState(columns, sorting) {
28
28
  else {
29
29
  return sorting === null || sorting === void 0 ? void 0 : sorting.value;
30
30
  }
31
- }, [sorting, columns]);
31
+ },
32
+ // We want to allow the user to not memoize `GridTableProps.sorting` b/c for the
33
+ // initialSortState calc, it's just a bunch of surely hard-coded primitives like
34
+ // sort on client/server, which column is initial.
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ [columns]);
32
37
  const [sortState, setSortState] = (0, react_1.useState)(initialSortState);
33
38
  // Make a custom setSortKey that is useState-like but contains the ASC->DESC->RESET logic.
39
+ const onSort = (sorting === null || sorting === void 0 ? void 0 : sorting.on) === "server" ? sorting.onSort : undefined;
34
40
  const setSortKey = (0, react_1.useCallback)((clickedKey) => {
35
41
  const newState = deriveSortState(sortState, clickedKey, initialSortState);
36
42
  setSortState(newState);
37
- if ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "server") {
43
+ if (onSort) {
38
44
  const [newKey, newDirection] = newState !== null && newState !== void 0 ? newState : [undefined, undefined];
39
- sorting.onSort(newKey, newDirection);
45
+ onSort(newKey, newDirection);
40
46
  }
41
47
  },
42
48
  // Note that sorting.onSort is not listed here, so we bind to whatever the 1st sorting.onSort was
43
- [sortState, setSortState]);
44
- return [sortState, setSortKey];
49
+ [initialSortState, sortState, onSort]);
50
+ return [sortState, setSortKey, sorting === null || sorting === void 0 ? void 0 : sorting.on];
45
51
  }
46
52
  exports.useSortState = useSortState;
47
53
  // Exported for testing purposes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.118.0",
3
+ "version": "2.118.1",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",