@homebound/beam 2.198.0 → 2.199.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.
Files changed (32) hide show
  1. package/dist/components/Table/GridTable.d.ts +11 -11
  2. package/dist/components/Table/GridTable.js +24 -20
  3. package/dist/components/Table/GridTableApi.d.ts +2 -2
  4. package/dist/components/Table/GridTableApi.js +10 -10
  5. package/dist/components/Table/components/CollapseToggle.js +3 -3
  6. package/dist/components/Table/components/EditColumnsButton.d.ts +5 -5
  7. package/dist/components/Table/components/Row.d.ts +5 -7
  8. package/dist/components/Table/components/Row.js +7 -7
  9. package/dist/components/Table/components/SelectToggle.js +4 -4
  10. package/dist/components/Table/components/SortHeader.d.ts +9 -5
  11. package/dist/components/Table/components/SortHeader.js +7 -3
  12. package/dist/components/Table/components/cell.d.ts +2 -3
  13. package/dist/components/Table/components/cell.js +2 -10
  14. package/dist/components/Table/hooks/useColumns.d.ts +1 -1
  15. package/dist/components/Table/index.d.ts +2 -6
  16. package/dist/components/Table/index.js +4 -8
  17. package/dist/components/Table/types.d.ts +5 -2
  18. package/dist/components/Table/types.js +1 -1
  19. package/dist/components/Table/utils/GridRowLookup.d.ts +3 -3
  20. package/dist/components/Table/utils/{RowState.d.ts → TableState.d.ts} +24 -4
  21. package/dist/components/Table/utils/{RowState.js → TableState.js} +91 -7
  22. package/dist/components/Table/utils/columns.d.ts +10 -7
  23. package/dist/components/Table/utils/columns.js +12 -1
  24. package/dist/components/Table/utils/sortRows.d.ts +3 -3
  25. package/dist/components/Table/utils/sortRows.js +7 -5
  26. package/dist/components/Table/utils/utils.d.ts +6 -6
  27. package/dist/components/Table/utils/utils.js +2 -2
  28. package/package.json +1 -1
  29. package/dist/components/Table/hooks/useSortState.d.ts +0 -15
  30. package/dist/components/Table/hooks/useSortState.js +0 -76
  31. package/dist/components/Table/utils/GridSortContext.d.ts +0 -13
  32. package/dist/components/Table/utils/GridSortContext.js +0 -11
@@ -1,7 +1,7 @@
1
1
  import { MutableRefObject } from "react";
2
2
  import { GridTableApi } from "./GridTableApi";
3
3
  import { GridStyle, GridStyleDef, RowStyles } from "./TableStyles";
4
- import { Direction, GridColumn, GridTableXss, Kinded, ParentChildrenTuple, RenderAs } from "./types";
4
+ import { Direction, GridColumn, GridColumnWithId, GridTableXss, Kinded, ParentChildrenTuple, RenderAs } from "./types";
5
5
  import { GridRowLookup } from "./utils/GridRowLookup";
6
6
  import { Only } from "../../Css";
7
7
  import { GridDataRow } from "./components/Row";
@@ -27,21 +27,21 @@ export declare function setGridTableDefaults(opts: Partial<GridTableDefaults>):
27
27
  * Note that we don't support multiple sort criteria, i.e. sort by column1 desc _and then_
28
28
  * column2 asc.
29
29
  */
30
- export declare type GridSortConfig<S> = {
30
+ export declare type GridSortConfig = {
31
31
  on: "client";
32
32
  /** The optional initial column (index in columns) and direction to sort. */
33
- initial?: [S | GridColumn<any>, Direction] | undefined;
33
+ initial?: [string, Direction] | undefined;
34
34
  caseSensitive?: boolean;
35
35
  /** The optional primary sort column, this will be sorted first above/below table sort */
36
- primary?: [S | GridColumn<any>, Direction] | undefined;
36
+ primary?: [string, Direction] | undefined;
37
37
  } | {
38
38
  on: "server";
39
39
  /** The current sort by value + direction (if server-side sorting). */
40
- value?: [S, Direction];
40
+ value?: [string, Direction];
41
41
  /** Callback for when the column is sorted (if server-side sorting). Parameters set to `undefined` is a signal to return to the initial sort state */
42
- onSort: (orderBy: S | undefined, direction: Direction | undefined) => void;
42
+ onSort: (orderBy: string | undefined, direction: Direction | undefined) => void;
43
43
  };
44
- export interface GridTableProps<R extends Kinded, S, X> {
44
+ export interface GridTableProps<R extends Kinded, X> {
45
45
  id?: string;
46
46
  /**
47
47
  * The HTML used to create the table.
@@ -57,7 +57,7 @@ export interface GridTableProps<R extends Kinded, S, X> {
57
57
  */
58
58
  as?: RenderAs;
59
59
  /** The column definitions i.e. how each column should render each row kind. */
60
- columns: GridColumn<R, S>[];
60
+ columns: GridColumn<R>[];
61
61
  /** The rows of data (including any header/footer rows), to be rendered by the column definitions. */
62
62
  rows: GridDataRow<R>[];
63
63
  /** Optional row-kind-level styling / behavior like onClick/rowLinks. */
@@ -68,7 +68,7 @@ export interface GridTableProps<R extends Kinded, S, X> {
68
68
  stickyHeader?: boolean;
69
69
  stickyOffset?: number;
70
70
  /** Configures sorting via a hash, does not need to be stable. */
71
- sorting?: GridSortConfig<S>;
71
+ sorting?: GridSortConfig;
72
72
  /** Shown in the first row slot, if there are no rows to show, i.e. 'No rows found'. */
73
73
  fallbackMessage?: string;
74
74
  /** Shown in the first row, kinda-like the fallbackMessage, but shown even if there are rows as well. */
@@ -121,7 +121,7 @@ export interface GridTableProps<R extends Kinded, S, X> {
121
121
  * row `kind` along with the data rows. (Admittedly, out of pragmatism, we do apply some
122
122
  * special styling to the row that uses `kind: "header"`.)
123
123
  */
124
- export declare function GridTable<R extends Kinded, S = {}, X extends Only<GridTableXss, X> = {}>(props: GridTableProps<R, S, X>): import("@emotion/react/jsx-runtime").JSX.Element;
124
+ export declare function GridTable<R extends Kinded, X extends Only<GridTableXss, X> = {}>(props: GridTableProps<R, X>): import("@emotion/react/jsx-runtime").JSX.Element;
125
125
  /**
126
126
  * Filters rows given a client-side text `filter.
127
127
  *
@@ -129,4 +129,4 @@ export declare function GridTable<R extends Kinded, S = {}, X extends Only<GridT
129
129
  *
130
130
  * We return a copy of `[Parent, [Child]]` tuples so that we don't modify the `GridDataRow.children`.
131
131
  */
132
- export declare function filterRows<R extends Kinded>(api: GridTableApi<R>, columns: GridColumn<R>[], rows: GridDataRow<R>[], filter: string | undefined): ParentChildrenTuple<R>[];
132
+ export declare function filterRows<R extends Kinded>(api: GridTableApi<R>, columns: GridColumnWithId<R>[], rows: GridDataRow<R>[], filter: string | undefined): ParentChildrenTuple<R>[];
@@ -25,16 +25,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.filterRows = exports.GridTable = exports.setGridTableDefaults = exports.setDefaultStyle = exports.setRunningInJest = void 0;
26
26
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
27
27
  const memoize_one_1 = __importDefault(require("memoize-one"));
28
+ const mobx_1 = require("mobx");
28
29
  const react_1 = __importStar(require("react"));
29
30
  const react_virtuoso_1 = require("react-virtuoso");
30
31
  const PresentationContext_1 = require("../PresentationContext");
31
32
  const GridTableApi_1 = require("./GridTableApi");
32
33
  const useSetupColumnSizes_1 = require("./hooks/useSetupColumnSizes");
33
- const useSortState_1 = require("./hooks/useSortState");
34
34
  const TableStyles_1 = require("./TableStyles");
35
+ const columns_1 = require("./utils/columns");
35
36
  const GridRowLookup_1 = require("./utils/GridRowLookup");
36
- const RowState_1 = require("./utils/RowState");
37
37
  const sortRows_1 = require("./utils/sortRows");
38
+ const TableState_1 = require("./utils/TableState");
38
39
  const utils_1 = require("./utils/utils");
39
40
  const Css_1 = require("../../Css");
40
41
  const hooks_1 = require("../../hooks");
@@ -78,7 +79,8 @@ exports.setGridTableDefaults = setGridTableDefaults;
78
79
  */
79
80
  function GridTable(props) {
80
81
  var _a, _b, _c;
81
- 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;
82
+ const { id = "gridTable", as = "div", columns: _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;
83
+ const columns = (0, react_1.useMemo)(() => (0, columns_1.assignDefaultColumnIds)(_columns), [_columns]);
82
84
  // We only use this in as=virtual mode, but keep this here for rowLookup to use
83
85
  const virtuosoRef = (0, react_1.useRef)(null);
84
86
  // Use this ref to watch for changes in the GridTable's container and resize columns accordingly.
@@ -92,14 +94,21 @@ function GridTable(props) {
92
94
  return api;
93
95
  }, [props.api]);
94
96
  const style = (0, TableStyles_1.resolveStyles)(maybeStyle);
95
- const { rowState } = api;
96
- rowState.setRows(rows);
97
+ const { tableState } = api;
98
+ // Initialize the sort state. This will only happen on the first render.
99
+ // Once the `TableState.sort` is defined, it will not re-initialize.
100
+ tableState.initSortState(props.sorting, columns);
101
+ const [sortOn, caseSensitive] = (0, hooks_1.useComputed)(() => {
102
+ const { sortConfig } = tableState;
103
+ return [sortConfig === null || sortConfig === void 0 ? void 0 : sortConfig.on, (sortConfig === null || sortConfig === void 0 ? void 0 : sortConfig.on) === "client" ? !!sortConfig.caseSensitive : false];
104
+ }, [tableState]);
105
+ tableState.setRows(rows);
97
106
  (0, react_1.useEffect)(() => {
98
- rowState.activeRowId = activeRowId;
99
- }, [rowState, activeRowId]);
107
+ tableState.activeRowId = activeRowId;
108
+ }, [tableState, activeRowId]);
100
109
  (0, react_1.useEffect)(() => {
101
- rowState.activeCellId = activeCellId;
102
- }, [rowState, activeCellId]);
110
+ tableState.activeCellId = activeCellId;
111
+ }, [tableState, activeCellId]);
103
112
  // We track render count at the table level, which seems odd (we should be able to track this
104
113
  // internally within each GridRow using a useRef), but we have suspicions that react-virtuoso
105
114
  // (or us) is resetting component state more than necessary, so we track render counts from
@@ -107,8 +116,8 @@ function GridTable(props) {
107
116
  const { getCount } = (0, useRenderCount_1.useRenderCount)();
108
117
  const columnSizes = (0, useSetupColumnSizes_1.useSetupColumnSizes)(style, columns, resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : resizeRef);
109
118
  // Make a single copy of our current collapsed state, so we'll have a single observer.
110
- const collapsedIds = (0, hooks_1.useComputed)(() => rowState.collapsedIds, [rowState]);
111
- const [sortState, setSortKey, sortOn, caseSensitive] = (0, useSortState_1.useSortState)(columns, props.sorting);
119
+ const collapsedIds = (0, hooks_1.useComputed)(() => tableState.collapsedIds, [tableState]);
120
+ const sortState = (0, hooks_1.useComputed)(() => (0, mobx_1.toJS)(tableState.sortState), [tableState]);
112
121
  const maybeSorted = (0, react_1.useMemo)(() => {
113
122
  if (sortOn === "client" && sortState) {
114
123
  // If using client-side sort, the sortState use S = number
@@ -120,9 +129,6 @@ function GridTable(props) {
120
129
  // Flatten + component-ize the sorted rows.
121
130
  let [headerRows, visibleDataRows, totalsRows, filteredRowIds] = (0, react_1.useMemo)(() => {
122
131
  function makeRowComponent(row, level) {
123
- // We only pass sortState to header rows, b/c non-headers rows shouldn't have to re-render on sorting
124
- // changes, and so by not passing the sortProps, it means the data rows' React.memo will still cache them.
125
- const sortProps = row.kind === "header" ? { sortOn, sortState, setSortKey } : { sortOn };
126
132
  return ((0, jsx_runtime_1.jsx)(Row_1.Row, Object.assign({}, {
127
133
  as,
128
134
  columns,
@@ -138,7 +144,7 @@ function GridTable(props) {
138
144
  api,
139
145
  cellHighlight: "cellHighlight" in maybeStyle && maybeStyle.cellHighlight === true,
140
146
  omitRowHover: "rowHover" in maybeStyle && maybeStyle.rowHover === false,
141
- ...sortProps,
147
+ sortOn,
142
148
  }), `${row.kind}-${row.id}`));
143
149
  }
144
150
  // Split out the header rows from the data rows so that we can put an `infoMessage` in between them (if needed).
@@ -183,8 +189,6 @@ function GridTable(props) {
183
189
  style,
184
190
  rowStyles,
185
191
  sortOn,
186
- setSortKey,
187
- sortState,
188
192
  stickyHeader,
189
193
  stickyOffset,
190
194
  columnSizes,
@@ -197,7 +201,7 @@ function GridTable(props) {
197
201
  tooManyClientSideRows = true;
198
202
  visibleDataRows = visibleDataRows.slice(0, filterMaxRows);
199
203
  }
200
- rowState.setMatchedRows(filteredRowIds);
204
+ tableState.setMatchedRows(filteredRowIds);
201
205
  // Push back to the caller a way to ask us where a row is.
202
206
  const { rowLookup } = props;
203
207
  if (rowLookup) {
@@ -225,8 +229,8 @@ function GridTable(props) {
225
229
  // just trust the GridTable impl that, at runtime, `as=virtual` will (other than being virtualized)
226
230
  // behave semantically the same as `as=div` did for its tests.
227
231
  const _as = as === "virtual" && runningInJest ? "div" : as;
228
- const rowStateContext = (0, react_1.useMemo)(() => ({ rowState }), [rowState]);
229
- return ((0, jsx_runtime_1.jsx)(RowState_1.RowStateContext.Provider, Object.assign({ value: rowStateContext }, { children: (0, jsx_runtime_1.jsxs)(PresentationContext_1.PresentationProvider, Object.assign({ fieldProps: fieldProps, wrap: (_c = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _c === void 0 ? void 0 : _c.wrap }, { children: [(0, jsx_runtime_1.jsx)("div", { ref: resizeRef, css: Css_1.Css.w100.if(as === "virtual").w("calc(100% - 20px)").$ }, void 0), renders[_as](style, id, columns, headerRows, totalsRows, visibleDataRows, firstRowMessage, stickyHeader, xss, virtuosoRef)] }), void 0) }), void 0));
232
+ const rowStateContext = (0, react_1.useMemo)(() => ({ tableState: tableState }), [tableState]);
233
+ return ((0, jsx_runtime_1.jsx)(TableState_1.TableStateContext.Provider, Object.assign({ value: rowStateContext }, { children: (0, jsx_runtime_1.jsxs)(PresentationContext_1.PresentationProvider, Object.assign({ fieldProps: fieldProps, wrap: (_c = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _c === void 0 ? void 0 : _c.wrap }, { children: [(0, jsx_runtime_1.jsx)("div", { ref: resizeRef, css: Css_1.Css.w100.if(as === "virtual").w("calc(100% - 20px)").$ }, void 0), renders[_as](style, id, columns, headerRows, totalsRows, visibleDataRows, firstRowMessage, stickyHeader, xss, virtuosoRef)] }), void 0) }), void 0));
230
234
  }
231
235
  exports.GridTable = GridTable;
232
236
  // Determine which HTML element to use to build the GridTable
@@ -2,7 +2,7 @@ import { MutableRefObject } from "react";
2
2
  import { VirtuosoHandle } from "react-virtuoso";
3
3
  import { GridDataRow } from "./components/Row";
4
4
  import { DiscriminateUnion, Kinded } from "./types";
5
- import { RowState } from "./utils/RowState";
5
+ import { TableState } from "./utils/TableState";
6
6
  /**
7
7
  * Creates an `api` handle to drive a `GridTable`.
8
8
  *
@@ -39,7 +39,7 @@ export declare type GridTableApi<R extends Kinded> = {
39
39
  selectRow: (id: string, selected?: boolean) => void;
40
40
  };
41
41
  export declare class GridTableApiImpl<R extends Kinded> implements GridTableApi<R> {
42
- readonly rowState: RowState;
42
+ readonly tableState: TableState;
43
43
  virtuosoRef: MutableRefObject<VirtuosoHandle | null>;
44
44
  /** Called once by the GridTable when it takes ownership of this api instance. */
45
45
  init(persistCollapse: string | undefined, virtuosoRef: MutableRefObject<VirtuosoHandle | null>, rows: GridDataRow<R>[]): void;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GridTableApiImpl = exports.useGridTableApi = void 0;
4
4
  const react_1 = require("react");
5
- const RowState_1 = require("./utils/RowState");
5
+ const TableState_1 = require("./utils/TableState");
6
6
  const visitor_1 = require("./utils/visitor");
7
7
  /**
8
8
  * Creates an `api` handle to drive a `GridTable`.
@@ -27,13 +27,13 @@ exports.useGridTableApi = useGridTableApi;
27
27
  class GridTableApiImpl {
28
28
  constructor() {
29
29
  // This is public to GridTable but not exported outside of Beam
30
- this.rowState = new RowState_1.RowState();
30
+ this.tableState = new TableState_1.TableState();
31
31
  this.virtuosoRef = { current: null };
32
32
  }
33
33
  /** Called once by the GridTable when it takes ownership of this api instance. */
34
34
  init(persistCollapse, virtuosoRef, rows) {
35
- this.rowState.loadCollapse(persistCollapse, rows);
36
- this.rowState.loadSelected(rows);
35
+ this.tableState.loadCollapse(persistCollapse, rows);
36
+ this.tableState.loadSelected(rows);
37
37
  this.virtuosoRef = virtuosoRef;
38
38
  }
39
39
  scrollToIndex(index) {
@@ -44,9 +44,9 @@ class GridTableApiImpl {
44
44
  }
45
45
  // The any is not great, but getting the overload to handle the optional kind is annoying
46
46
  getSelectedRows(kind) {
47
- const ids = this.rowState.selectedIds;
47
+ const ids = this.tableState.selectedIds;
48
48
  const selected = [];
49
- (0, visitor_1.visit)(this.rowState.rows, (row) => {
49
+ (0, visitor_1.visit)(this.tableState.rows, (row) => {
50
50
  if (row.selectable !== false && ids.includes(row.id) && (!kind || row.kind === kind)) {
51
51
  selected.push(row);
52
52
  }
@@ -54,16 +54,16 @@ class GridTableApiImpl {
54
54
  return selected;
55
55
  }
56
56
  clearSelections(id) {
57
- this.rowState.selectRow("header", false);
57
+ this.tableState.selectRow("header", false);
58
58
  }
59
59
  setActiveRowId(id) {
60
- this.rowState.activeRowId = id;
60
+ this.tableState.activeRowId = id;
61
61
  }
62
62
  setActiveCellId(id) {
63
- this.rowState.activeCellId = id;
63
+ this.tableState.activeCellId = id;
64
64
  }
65
65
  selectRow(id, selected = true) {
66
- this.rowState.selectRow(id, selected);
66
+ this.tableState.selectRow(id, selected);
67
67
  }
68
68
  }
69
69
  exports.GridTableApiImpl = GridTableApiImpl;
@@ -8,8 +8,8 @@ const hooks_1 = require("../../../hooks");
8
8
  /** Provides a chevron icons to collapse/un-collapse for parent/child tables. */
9
9
  function CollapseToggle(props) {
10
10
  const { row, compact } = props;
11
- const { rowState } = (0, react_1.useContext)(index_1.RowStateContext);
12
- const isCollapsed = (0, hooks_1.useComputed)(() => rowState.isCollapsed(row.id), [rowState]);
11
+ const { tableState } = (0, react_1.useContext)(index_1.TableStateContext);
12
+ const isCollapsed = (0, hooks_1.useComputed)(() => tableState.isCollapsed(row.id), [tableState]);
13
13
  const iconKey = isCollapsed ? "chevronRight" : "chevronDown";
14
14
  const headerIconKey = isCollapsed ? "chevronsRight" : "chevronsDown";
15
15
  // If we're not a header, only render a toggle if we have child rows to actually collapse
@@ -17,6 +17,6 @@ function CollapseToggle(props) {
17
17
  if (!isHeader && (!row.children || row.children.length === 0)) {
18
18
  return null;
19
19
  }
20
- return ((0, jsx_runtime_1.jsx)(index_1.IconButton, { onClick: () => rowState.toggleCollapsed(row.id), icon: isHeader ? headerIconKey : iconKey, compact: compact }, void 0));
20
+ return ((0, jsx_runtime_1.jsx)(index_1.IconButton, { onClick: () => tableState.toggleCollapsed(row.id), icon: isHeader ? headerIconKey : iconKey, compact: compact }, void 0));
21
21
  }
22
22
  exports.CollapseToggle = CollapseToggle;
@@ -1,12 +1,12 @@
1
1
  import { Dispatch, SetStateAction } from "react";
2
2
  import { OverlayTriggerProps } from "../../internal/OverlayTrigger";
3
3
  import { GridColumn, Kinded } from "../types";
4
- interface EditColumnsButtonProps<R extends Kinded, S> extends Pick<OverlayTriggerProps, "trigger" | "placement" | "disabled" | "tooltip"> {
5
- allColumns: GridColumn<R, S>[];
6
- selectedColumns: GridColumn<R, S>[];
7
- setSelectedColumns: Dispatch<SetStateAction<GridColumn<R, S>[]>>;
4
+ interface EditColumnsButtonProps<R extends Kinded> extends Pick<OverlayTriggerProps, "trigger" | "placement" | "disabled" | "tooltip"> {
5
+ allColumns: GridColumn<R>[];
6
+ selectedColumns: GridColumn<R>[];
7
+ setSelectedColumns: Dispatch<SetStateAction<GridColumn<R>[]>>;
8
8
  title?: string;
9
9
  defaultOpen?: boolean;
10
10
  }
11
- export declare function EditColumnsButton<R extends Kinded, S = {}>(props: EditColumnsButtonProps<R, S>): import("@emotion/react/jsx-runtime").JSX.Element;
11
+ export declare function EditColumnsButton<R extends Kinded>(props: EditColumnsButtonProps<R>): import("@emotion/react/jsx-runtime").JSX.Element;
12
12
  export {};
@@ -1,19 +1,17 @@
1
1
  import { ReactElement } from "react";
2
2
  import { GridTableApi } from "../GridTableApi";
3
- import { SortOn, SortState } from "../hooks/useSortState";
4
3
  import { GridStyle, RowStyles } from "../TableStyles";
5
- import { DiscriminateUnion, GridColumn, IfAny, Kinded, Pin, RenderAs } from "../types";
6
- interface RowProps<R extends Kinded, S> {
4
+ import { DiscriminateUnion, GridColumnWithId, IfAny, Kinded, Pin, RenderAs } from "../types";
5
+ import { SortOn } from "../utils/TableState";
6
+ interface RowProps<R extends Kinded> {
7
7
  as: RenderAs;
8
- columns: GridColumn<R>[];
8
+ columns: GridColumnWithId<R>[];
9
9
  row: GridDataRow<R>;
10
10
  style: GridStyle;
11
11
  rowStyles: RowStyles<R> | undefined;
12
12
  stickyHeader: boolean;
13
13
  stickyOffset: number;
14
14
  sortOn: SortOn;
15
- sortState?: SortState<S>;
16
- setSortKey?: (value: S) => void;
17
15
  columnSizes: string[];
18
16
  level: number;
19
17
  getCount: (id: string) => object;
@@ -21,7 +19,7 @@ interface RowProps<R extends Kinded, S> {
21
19
  cellHighlight: boolean;
22
20
  omitRowHover: boolean;
23
21
  }
24
- declare function RowImpl<R extends Kinded, S>(props: RowProps<R, S>): ReactElement;
22
+ declare function RowImpl<R extends Kinded, S>(props: RowProps<R>): ReactElement;
25
23
  /**
26
24
  * Memoizes Rows so that re-rendering the table doesn't re-render every single row.
27
25
  *
@@ -24,8 +24,8 @@ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
24
24
  const mobx_react_1 = require("mobx-react");
25
25
  const react_1 = __importStar(require("react"));
26
26
  const cell_1 = require("./cell");
27
- const RowState_1 = require("../utils/RowState");
28
27
  const sortRows_1 = require("../utils/sortRows");
28
+ const TableState_1 = require("../utils/TableState");
29
29
  const utils_1 = require("../utils/utils");
30
30
  const Css_1 = require("../../../Css");
31
31
  const hooks_1 = require("../../../hooks");
@@ -33,10 +33,10 @@ const shallowEqual_1 = require("../../../utils/shallowEqual");
33
33
  // We extract Row to its own mini-component primarily so we can React.memo'ize it.
34
34
  function RowImpl(props) {
35
35
  var _a;
36
- const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sortOn, sortState, setSortKey, columnSizes, level, getCount, api, cellHighlight, omitRowHover, ...others } = props;
37
- const { rowState } = (0, react_1.useContext)(RowState_1.RowStateContext);
36
+ const { as, columns, row, style, rowStyles, stickyHeader, stickyOffset, sortOn, columnSizes, level, getCount, api, cellHighlight, omitRowHover, ...others } = props;
37
+ const { tableState } = (0, react_1.useContext)(TableState_1.TableStateContext);
38
38
  const rowId = `${row.kind}_${row.id}`;
39
- const isActive = (0, hooks_1.useComputed)(() => rowState.activeRowId === rowId, [rowId, rowState]);
39
+ const isActive = (0, hooks_1.useComputed)(() => tableState.activeRowId === rowId, [rowId, tableState]);
40
40
  // We treat the "header" and "totals" kind as special for "good defaults" styling
41
41
  const isHeader = row.kind === "header";
42
42
  const isTotals = row.kind === "totals";
@@ -87,7 +87,7 @@ function RowImpl(props) {
87
87
  (sortOn === "server" && !!column.serverSideSortKey);
88
88
  const alignment = (0, utils_1.getAlignment)(column, maybeContent);
89
89
  const justificationCss = (0, utils_1.getJustification)(column, maybeContent, as, alignment);
90
- const content = (0, utils_1.toContent)(maybeContent, isHeader, canSortColumn, sortOn === "client", style, as, alignment);
90
+ const content = (0, utils_1.toContent)(maybeContent, isHeader, canSortColumn, sortOn === "client", style, as, alignment, column);
91
91
  (0, sortRows_1.ensureClientSideSortValueIsSortable)(sortOn, isHeader, column, columnIndex, maybeContent);
92
92
  const maybeSticky = (_b = (((0, utils_1.isGridCellContent)(maybeContent) && maybeContent.sticky) || column.sticky)) !== null && _b !== void 0 ? _b : undefined;
93
93
  const maybeStickyColumnStyles = maybeSticky && columnSizes
@@ -105,7 +105,7 @@ function RowImpl(props) {
105
105
  : {};
106
106
  const cellId = `${row.kind}_${row.id}_${column.id}`;
107
107
  const applyCellHighlight = cellHighlight && !!column.id && !isHeader && !isTotals;
108
- const isCellActive = rowState.activeCellId === cellId;
108
+ const isCellActive = tableState.activeCellId === cellId;
109
109
  // Note that it seems expensive to calc a per-cell class name/CSS-in-JS output,
110
110
  // vs. setting global/table-wide CSS like `style.cellCss` on the root grid div with
111
111
  // a few descendent selectors. However, that approach means the root grid-applied
@@ -154,7 +154,7 @@ function RowImpl(props) {
154
154
  const renderFn = ((rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.renderCell) || (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.rowLink)) && wrapAction
155
155
  ? (0, cell_1.rowLinkRenderFn)(as)
156
156
  : isHeader
157
- ? (0, cell_1.headerRenderFn)(columns, column, sortState, setSortKey, as)
157
+ ? (0, cell_1.headerRenderFn)(column, as)
158
158
  : (rowStyle === null || rowStyle === void 0 ? void 0 : rowStyle.onClick) && wrapAction
159
159
  ? (0, cell_1.rowClickRenderFn)(as, api)
160
160
  : (0, cell_1.defaultRenderFn)(as);
@@ -3,16 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SelectToggle = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const RowState_1 = require("../utils/RowState");
6
+ const TableState_1 = require("../utils/TableState");
7
7
  const hooks_1 = require("../../../hooks");
8
8
  const inputs_1 = require("../../../inputs");
9
9
  /** Provides a checkbox to show/drive this row's selected state. */
10
10
  function SelectToggle({ id, disabled }) {
11
- const { rowState } = (0, react_1.useContext)(RowState_1.RowStateContext);
12
- const state = (0, hooks_1.useComputed)(() => rowState.getSelected(id), [rowState]);
11
+ const { tableState } = (0, react_1.useContext)(TableState_1.TableStateContext);
12
+ const state = (0, hooks_1.useComputed)(() => tableState.getSelected(id), [tableState]);
13
13
  const selected = state === "checked" ? true : state === "unchecked" ? false : "indeterminate";
14
14
  return ((0, jsx_runtime_1.jsx)(inputs_1.Checkbox, { checkboxOnly: true, disabled: disabled, label: "Select", onChange: (selected) => {
15
- rowState.selectRow(id, selected);
15
+ tableState.selectRow(id, selected);
16
16
  }, selected: selected }, void 0));
17
17
  }
18
18
  exports.SelectToggle = SelectToggle;
@@ -1,4 +1,11 @@
1
+ import { GridColumnWithId } from "../types";
1
2
  import { Properties } from "../../../Css";
3
+ interface SortHeaderProps {
4
+ content: string;
5
+ xss?: Properties;
6
+ iconOnLeft?: boolean;
7
+ column: GridColumnWithId<any>;
8
+ }
2
9
  /**
3
10
  * Wraps column header names with up/down sorting icons.
4
11
  *
@@ -10,8 +17,5 @@ import { Properties } from "../../../Css";
10
17
  * - Write their own component that uses `GridSortContext` to access the column's
11
18
  * current sort state + `toggleSort` function
12
19
  */
13
- export declare function SortHeader(props: {
14
- content: string;
15
- xss?: Properties;
16
- iconOnLeft?: boolean;
17
- }): import("@emotion/react/jsx-runtime").JSX.Element;
20
+ export declare function SortHeader(props: SortHeaderProps): import("@emotion/react/jsx-runtime").JSX.Element;
21
+ export {};
@@ -4,7 +4,7 @@ exports.SortHeader = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const Icon_1 = require("../../Icon");
7
- const GridSortContext_1 = require("../utils/GridSortContext");
7
+ const TableState_1 = require("../utils/TableState");
8
8
  const Css_1 = require("../../../Css");
9
9
  const hooks_1 = require("../../../hooks");
10
10
  const useTestIds_1 = require("../../../utils/useTestIds");
@@ -20,9 +20,13 @@ const useTestIds_1 = require("../../../utils/useTestIds");
20
20
  * current sort state + `toggleSort` function
21
21
  */
22
22
  function SortHeader(props) {
23
- const { content, xss, iconOnLeft = false } = props;
23
+ const { content, xss, iconOnLeft = false, column } = props;
24
24
  const { isHovered, hoverProps } = (0, hooks_1.useHover)({});
25
- const { sorted, toggleSort } = (0, react_1.useContext)(GridSortContext_1.GridSortContext);
25
+ const ourSortKey = column.serverSideSortKey || column.id;
26
+ const { tableState } = (0, react_1.useContext)(TableState_1.TableStateContext);
27
+ const current = (0, hooks_1.useComputed)(() => { var _a; return (_a = tableState.sortState) === null || _a === void 0 ? void 0 : _a.current; }, [tableState]);
28
+ const sorted = ourSortKey === (current === null || current === void 0 ? void 0 : current.columnId) ? current === null || current === void 0 ? void 0 : current.direction : undefined;
29
+ const toggleSort = (0, react_1.useCallback)(() => tableState.setSortKey(ourSortKey), [ourSortKey, tableState]);
26
30
  const tid = (0, useTestIds_1.useTestIds)(props, "sortHeader");
27
31
  const icon = ((0, jsx_runtime_1.jsx)("span", Object.assign({ css: Css_1.Css.fs0.$ }, { children: (0, jsx_runtime_1.jsx)(Icon_1.Icon, Object.assign({ icon: sorted === "DESC" ? "sortDown" : "sortUp", color: sorted !== undefined ? Css_1.Palette.LightBlue700 : Css_1.Palette.Gray400, xss: {
28
32
  ...Css_1.Css.ml1.if(iconOnLeft).mr1.ml0.$,
@@ -1,8 +1,7 @@
1
1
  import { ReactNode } from "react";
2
2
  import { GridTableApi } from "../GridTableApi";
3
- import { SortState } from "../hooks/useSortState";
4
3
  import { RowStyle } from "../TableStyles";
5
- import { GridCellAlignment, GridColumn, Kinded, MaybeFn, RenderAs } from "../types";
4
+ import { GridCellAlignment, GridColumnWithId, Kinded, MaybeFn, RenderAs } from "../types";
6
5
  import { Properties, Typography } from "../../../Css";
7
6
  /**
8
7
  * Allows a cell to be more than just a RectNode, i.e. declare its alignment or
@@ -34,7 +33,7 @@ export declare type RenderCellFn<R extends Kinded> = (idx: number, css: Properti
34
33
  /** Renders our default cell element, i.e. if no row links and no custom renderCell are used. */
35
34
  export declare const defaultRenderFn: (as: RenderAs) => RenderCellFn<any>;
36
35
  /** Sets up the `GridContext` so that header cells can access the current sort settings. */
37
- export declare const headerRenderFn: (columns: GridColumn<any>[], column: GridColumn<any>, sortState: SortState<any> | undefined, setSortKey: Function | undefined, as: RenderAs) => RenderCellFn<any>;
36
+ export declare const headerRenderFn: (column: GridColumnWithId<any>, as: RenderAs) => RenderCellFn<any>;
38
37
  /** Renders a cell element when a row link is in play. */
39
38
  export declare const rowLinkRenderFn: (as: RenderAs) => RenderCellFn<any>;
40
39
  /** Renders a cell that will fire the RowStyle.onClick. */
@@ -5,7 +5,6 @@ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_router_dom_1 = require("react-router-dom");
6
6
  const CssReset_1 = require("../../CssReset");
7
7
  const TableStyles_1 = require("../TableStyles");
8
- const GridSortContext_1 = require("../utils/GridSortContext");
9
8
  const Css_1 = require("../../../Css");
10
9
  /** Renders our default cell element, i.e. if no row links and no custom renderCell are used. */
11
10
  const defaultRenderFn = (as) => (key, css, content, row, rowStyle, classNames, onClick) => {
@@ -14,16 +13,9 @@ const defaultRenderFn = (as) => (key, css, content, row, rowStyle, classNames, o
14
13
  };
15
14
  exports.defaultRenderFn = defaultRenderFn;
16
15
  /** Sets up the `GridContext` so that header cells can access the current sort settings. */
17
- const headerRenderFn = (columns, column, sortState, setSortKey, as) => (key, css, content, row, rowStyle, classNames) => {
18
- const [currentKey, direction] = sortState || [];
19
- // If server-side sorting, use the user's key for this column; client-side sorting, use the index.
20
- const ourSortKey = column.serverSideSortKey || columns.indexOf(column);
21
- const context = {
22
- sorted: ourSortKey === currentKey ? direction : undefined,
23
- toggleSort: () => setSortKey(ourSortKey),
24
- };
16
+ const headerRenderFn = (column, as) => (key, css, content, row, rowStyle, classNames) => {
25
17
  const Cell = as === "table" ? "th" : "div";
26
- return ((0, jsx_runtime_1.jsx)(GridSortContext_1.GridSortContext.Provider, Object.assign({ value: context }, { children: (0, jsx_runtime_1.jsx)(Cell, Object.assign({ css: { ...css, ...(0, TableStyles_1.tableRowStyles)(as, column) }, className: classNames }, { children: content }), void 0) }), key));
18
+ return ((0, jsx_runtime_1.jsx)(Cell, Object.assign({ css: { ...css, ...(0, TableStyles_1.tableRowStyles)(as, column) }, className: classNames }, { children: content }), void 0));
27
19
  };
28
20
  exports.headerRenderFn = headerRenderFn;
29
21
  /** Renders a cell element when a row link is in play. */
@@ -1,3 +1,3 @@
1
1
  import { Dispatch, SetStateAction } from "react";
2
2
  import { GridColumn, Kinded } from "../types";
3
- export declare function useColumns<R extends Kinded, S = {}>(tableColumns: GridColumn<R, S>[], maybeStorageKey?: string): [GridColumn<R, S>[], Dispatch<SetStateAction<GridColumn<R, S>[]>>];
3
+ export declare function useColumns<R extends Kinded>(tableColumns: GridColumn<R>[], maybeStorageKey?: string): [GridColumn<R>[], Dispatch<SetStateAction<GridColumn<R>[]>>];
@@ -11,21 +11,17 @@ export { useGridTableApi } from "./GridTableApi";
11
11
  export type { GridTableApi } from "./GridTableApi";
12
12
  export * from "./hooks/useColumns";
13
13
  export * from "./hooks/useSetupColumnSizes";
14
- export * from "./hooks/useSortState";
15
14
  export { cardStyle, condensedStyle, defaultStyle, getTableStyles } from "./TableStyles";
16
15
  export type { GridStyle, RowStyle, RowStyles } from "./TableStyles";
17
16
  export * from "./types";
18
17
  export * from "./utils/columns";
19
18
  export { createRowLookup } from "./utils/GridRowLookup";
20
19
  export type { GridRowLookup } from "./utils/GridRowLookup";
21
- export * from "./utils/GridSortContext";
22
- export { GridSortContext } from "./utils/GridSortContext";
23
- export type { GridSortContextProps } from "./utils/GridSortContext";
24
- export { RowState, RowStateContext } from "./utils/RowState";
25
- export type { SelectedState } from "./utils/RowState";
26
20
  export { simpleDataRows, simpleHeader } from "./utils/simpleHelpers";
27
21
  export type { SimpleHeaderAndData } from "./utils/simpleHelpers";
28
22
  export * from "./utils/sortRows";
23
+ export { TableState, TableStateContext } from "./utils/TableState";
24
+ export type { SelectedState, SortOn, SortState } from "./utils/TableState";
29
25
  export * from "./utils/utils";
30
26
  export * from "./utils/visitor";
31
27
  export { GridTable, setDefaultStyle, setGridTableDefaults } from "./GridTable";
@@ -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.setGridTableDefaults = exports.setDefaultStyle = exports.GridTable = exports.simpleHeader = exports.simpleDataRows = exports.RowStateContext = exports.RowState = exports.GridSortContext = exports.createRowLookup = exports.getTableStyles = exports.defaultStyle = exports.condensedStyle = exports.cardStyle = exports.useGridTableApi = exports.SortHeader = exports.Row = exports.EditColumnsButton = exports.rowLinkRenderFn = exports.rowClickRenderFn = exports.headerRenderFn = exports.defaultRenderFn = void 0;
13
+ exports.setGridTableDefaults = exports.setDefaultStyle = exports.GridTable = exports.TableStateContext = exports.TableState = exports.simpleHeader = exports.simpleDataRows = exports.createRowLookup = exports.getTableStyles = exports.defaultStyle = exports.condensedStyle = exports.cardStyle = exports.useGridTableApi = exports.SortHeader = exports.Row = exports.EditColumnsButton = exports.rowLinkRenderFn = exports.rowClickRenderFn = exports.headerRenderFn = exports.defaultRenderFn = void 0;
14
14
  var cell_1 = require("./components/cell");
15
15
  Object.defineProperty(exports, "defaultRenderFn", { enumerable: true, get: function () { return cell_1.defaultRenderFn; } });
16
16
  Object.defineProperty(exports, "headerRenderFn", { enumerable: true, get: function () { return cell_1.headerRenderFn; } });
@@ -29,7 +29,6 @@ var GridTableApi_1 = require("./GridTableApi");
29
29
  Object.defineProperty(exports, "useGridTableApi", { enumerable: true, get: function () { return GridTableApi_1.useGridTableApi; } });
30
30
  __exportStar(require("./hooks/useColumns"), exports);
31
31
  __exportStar(require("./hooks/useSetupColumnSizes"), exports);
32
- __exportStar(require("./hooks/useSortState"), exports);
33
32
  var TableStyles_1 = require("./TableStyles");
34
33
  Object.defineProperty(exports, "cardStyle", { enumerable: true, get: function () { return TableStyles_1.cardStyle; } });
35
34
  Object.defineProperty(exports, "condensedStyle", { enumerable: true, get: function () { return TableStyles_1.condensedStyle; } });
@@ -39,16 +38,13 @@ __exportStar(require("./types"), exports);
39
38
  __exportStar(require("./utils/columns"), exports);
40
39
  var GridRowLookup_1 = require("./utils/GridRowLookup");
41
40
  Object.defineProperty(exports, "createRowLookup", { enumerable: true, get: function () { return GridRowLookup_1.createRowLookup; } });
42
- __exportStar(require("./utils/GridSortContext"), exports);
43
- var GridSortContext_1 = require("./utils/GridSortContext");
44
- Object.defineProperty(exports, "GridSortContext", { enumerable: true, get: function () { return GridSortContext_1.GridSortContext; } });
45
- var RowState_1 = require("./utils/RowState");
46
- Object.defineProperty(exports, "RowState", { enumerable: true, get: function () { return RowState_1.RowState; } });
47
- Object.defineProperty(exports, "RowStateContext", { enumerable: true, get: function () { return RowState_1.RowStateContext; } });
48
41
  var simpleHelpers_1 = require("./utils/simpleHelpers");
49
42
  Object.defineProperty(exports, "simpleDataRows", { enumerable: true, get: function () { return simpleHelpers_1.simpleDataRows; } });
50
43
  Object.defineProperty(exports, "simpleHeader", { enumerable: true, get: function () { return simpleHelpers_1.simpleHeader; } });
51
44
  __exportStar(require("./utils/sortRows"), exports);
45
+ var TableState_1 = require("./utils/TableState");
46
+ Object.defineProperty(exports, "TableState", { enumerable: true, get: function () { return TableState_1.TableState; } });
47
+ Object.defineProperty(exports, "TableStateContext", { enumerable: true, get: function () { return TableState_1.TableStateContext; } });
52
48
  __exportStar(require("./utils/utils"), exports);
53
49
  __exportStar(require("./utils/visitor"), exports);
54
50
  var GridTable_1 = require("./GridTable");
@@ -30,7 +30,7 @@ export declare type DiscriminateUnion<T, K extends keyof T, V extends T[K]> = T
30
30
  * - For client-side sorting, it's type `number`, to represent the current
31
31
  * column being sorted, in which case we use the GridCellContent.value.
32
32
  */
33
- export declare type GridColumn<R extends Kinded, S = {}> = {
33
+ export declare type GridColumn<R extends Kinded> = {
34
34
  [K in R["kind"]]: string | GridCellContent | (DiscriminateUnion<R, "kind", K> extends {
35
35
  data: infer D;
36
36
  } ? (data: D, opts: {
@@ -57,7 +57,7 @@ export declare type GridColumn<R extends Kinded, S = {}> = {
57
57
  /** Whether the column can be sorted (if client-side sorting). Defaults to true if sorting client-side. */
58
58
  clientSideSort?: boolean;
59
59
  /** This column's sort by value (if server-side sorting). */
60
- serverSideSortKey?: S;
60
+ serverSideSortKey?: string;
61
61
  /** Allows the column to stay in place when the user scrolls horizontally */
62
62
  sticky?: "left" | "right";
63
63
  /** Prevent column from supporting RowStyle.onClick/rowLink in order to avoid nested interactivity. Defaults to true */
@@ -71,6 +71,9 @@ export declare type GridColumn<R extends Kinded, S = {}> = {
71
71
  /** Flag that will allow to know which hide-able columns are visible on initial load */
72
72
  initVisible?: boolean;
73
73
  };
74
+ export declare type GridColumnWithId<R extends Kinded> = GridColumn<R> & {
75
+ id: string;
76
+ };
74
77
  export declare const nonKindGridColumnKeys: string[];
75
78
  /**
76
79
  * Used to indicate where to pin the DataRow and if whether it should be filtered or always visible, setting `filter` to `true` will hide this row
@@ -10,7 +10,7 @@ exports.nonKindGridColumnKeys = [
10
10
  "sticky",
11
11
  "wrapAction",
12
12
  "isAction",
13
- "name",
13
+ "id",
14
14
  "canHide",
15
15
  "initVisible",
16
16
  ];
@@ -1,7 +1,7 @@
1
1
  import { MutableRefObject } from "react";
2
2
  import { VirtuosoHandle } from "react-virtuoso";
3
3
  import { GridDataRow } from "../components/Row";
4
- import { DiscriminateUnion, GridColumn, Kinded, RowTuple } from "../types";
4
+ import { DiscriminateUnion, GridColumnWithId, Kinded, RowTuple } from "../types";
5
5
  /**
6
6
  * Allows a caller to ask for the currently shown rows, given the current sorting/filtering.
7
7
  *
@@ -22,6 +22,6 @@ interface NextPrev<R extends Kinded> {
22
22
  next: GridDataRow<R> | undefined;
23
23
  prev: GridDataRow<R> | undefined;
24
24
  }
25
- export declare function createRowLookup<R extends Kinded>(columns: GridColumn<R>[], filteredRows: RowTuple<R>[], virtuosoRef: MutableRefObject<VirtuosoHandle | null>): GridRowLookup<R>;
26
- export declare function getKinds<R extends Kinded>(columns: GridColumn<R>[]): R[];
25
+ export declare function createRowLookup<R extends Kinded>(columns: GridColumnWithId<R>[], filteredRows: RowTuple<R>[], virtuosoRef: MutableRefObject<VirtuosoHandle | null>): GridRowLookup<R>;
26
+ export declare function getKinds<R extends Kinded>(columns: GridColumnWithId<R>[]): R[];
27
27
  export {};
@@ -1,5 +1,7 @@
1
1
  import React from "react";
2
2
  import { GridDataRow } from "../components/Row";
3
+ import { GridSortConfig } from "../GridTable";
4
+ import { Direction, GridColumnWithId } from "../types";
3
5
  export declare type SelectedState = "checked" | "unchecked" | "partial";
4
6
  /**
5
7
  * Stores the collapsed & selected state of rows.
@@ -16,7 +18,7 @@ export declare type SelectedState = "checked" | "unchecked" | "partial";
16
18
  * that need to change their toggle/select on/off in response to parent/child
17
19
  * changes.
18
20
  */
19
- export declare class RowState {
21
+ export declare class TableState {
20
22
  private readonly collapsedRows;
21
23
  private persistCollapse;
22
24
  private readonly selectedRows;
@@ -24,12 +26,19 @@ export declare class RowState {
24
26
  rows: GridDataRow<any>[];
25
27
  activeRowId: string | undefined;
26
28
  activeCellId: string | undefined;
29
+ sortConfig: GridSortConfig | undefined;
30
+ sort: SortState;
31
+ private initialSortState;
32
+ private onSort;
27
33
  /**
28
34
  * Creates the `RowState` for a given `GridTable`.
29
35
  */
30
36
  constructor();
31
37
  loadCollapse(persistCollapse: string | undefined, rows: GridDataRow<any>[]): void;
32
38
  loadSelected(rows: GridDataRow<any>[]): void;
39
+ initSortState(sortConfig: GridSortConfig | undefined, columns: GridColumnWithId<any>[]): void;
40
+ setSortKey(clickedColumnId: string): void;
41
+ get sortState(): SortState | undefined;
33
42
  setRows(rows: GridDataRow<any>[]): void;
34
43
  setMatchedRows(rowIds: string[]): void;
35
44
  get selectedIds(): string[];
@@ -41,7 +50,18 @@ export declare class RowState {
41
50
  private getMatchedChildrenStates;
42
51
  private setNestedSelectedStates;
43
52
  }
44
- /** Provides a context for rows to access their table's `RowState`. */
45
- export declare const RowStateContext: React.Context<{
46
- rowState: RowState;
53
+ /** Provides a context for rows to access their table's `TableState`. */
54
+ export declare const TableStateContext: React.Context<{
55
+ tableState: TableState;
47
56
  }>;
57
+ export declare function deriveSortState(currentSortState: SortState, clickedKey: string, initialSortState: SortState | undefined): SortState | undefined;
58
+ declare type ColumnSort = {
59
+ columnId: string;
60
+ direction: Direction;
61
+ };
62
+ export declare type SortState = {
63
+ current?: ColumnSort;
64
+ persistent?: ColumnSort;
65
+ };
66
+ export declare type SortOn = "client" | "server" | undefined;
67
+ export {};
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.RowStateContext = exports.RowState = void 0;
6
+ exports.deriveSortState = exports.TableStateContext = exports.TableState = void 0;
7
7
  const mobx_1 = require("mobx");
8
8
  const react_1 = __importDefault(require("react"));
9
+ const utils_1 = require("./utils");
9
10
  const visitor_1 = require("./visitor");
10
11
  /**
11
12
  * Stores the collapsed & selected state of rows.
@@ -22,7 +23,7 @@ const visitor_1 = require("./visitor");
22
23
  * that need to change their toggle/select on/off in response to parent/child
23
24
  * changes.
24
25
  */
25
- class RowState {
26
+ class TableState {
26
27
  /**
27
28
  * Creates the `RowState` for a given `GridTable`.
28
29
  */
@@ -38,6 +39,8 @@ class RowState {
38
39
  this.activeRowId = undefined;
39
40
  // Keeps track of the 'active' cell, formatted `${row.kind}_${row.id}_${column.name}`
40
41
  this.activeCellId = undefined;
42
+ // Provide some defaults to get the sort state to properly work.
43
+ this.sort = {};
41
44
  // Make ourselves an observable so that mobx will do caching of .collapseIds so
42
45
  // that it'll be a stable identity for GridTable to useMemo against.
43
46
  (0, mobx_1.makeAutoObservable)(this,
@@ -78,6 +81,58 @@ class RowState {
78
81
  });
79
82
  this.selectedRows.merge(map);
80
83
  }
84
+ initSortState(sortConfig, columns) {
85
+ var _a, _b;
86
+ if (this.sortConfig) {
87
+ return;
88
+ }
89
+ this.sortConfig = sortConfig;
90
+ if ((sortConfig === null || sortConfig === void 0 ? void 0 : sortConfig.on) === "client") {
91
+ const { initial, primary } = sortConfig;
92
+ const primaryKey = primary === null || primary === void 0 ? void 0 : primary[0];
93
+ const persistentSortData = primaryKey
94
+ ? { persistent: { columnId: primaryKey, direction: (_a = primary === null || primary === void 0 ? void 0 : primary[1]) !== null && _a !== void 0 ? _a : utils_1.ASC } }
95
+ : {};
96
+ if (initial === undefined && "initial" in sortConfig) {
97
+ // if explicitly set to `undefined`, then do not sort
98
+ this.initialSortState = undefined;
99
+ }
100
+ else if (initial) {
101
+ this.initialSortState = { current: { columnId: initial[0], direction: initial[1] }, ...persistentSortData };
102
+ }
103
+ else {
104
+ // If no explicit sortState, assume 1st column ascending
105
+ const firstSortableColumn = (_b = columns.find((c) => c.clientSideSort !== false)) === null || _b === void 0 ? void 0 : _b.id;
106
+ this.initialSortState = firstSortableColumn
107
+ ? { current: { columnId: firstSortableColumn, direction: utils_1.ASC }, ...persistentSortData }
108
+ : undefined;
109
+ }
110
+ }
111
+ else {
112
+ this.initialSortState = (sortConfig === null || sortConfig === void 0 ? void 0 : sortConfig.value)
113
+ ? { current: { columnId: sortConfig === null || sortConfig === void 0 ? void 0 : sortConfig.value[0], direction: sortConfig === null || sortConfig === void 0 ? void 0 : sortConfig.value[1] } }
114
+ : undefined;
115
+ }
116
+ // Only change `this.sort` if `initialSortState` is defined.
117
+ if (this.initialSortState) {
118
+ this.sort = this.initialSortState;
119
+ }
120
+ this.onSort = (sortConfig === null || sortConfig === void 0 ? void 0 : sortConfig.on) === "server" ? sortConfig.onSort : undefined;
121
+ }
122
+ setSortKey(clickedColumnId) {
123
+ var _a;
124
+ if (this.sortConfig) {
125
+ const newState = deriveSortState(this.sort, clickedColumnId, this.initialSortState);
126
+ this.sort = newState !== null && newState !== void 0 ? newState : {};
127
+ if (this.onSort) {
128
+ const { columnId, direction } = (_a = newState === null || newState === void 0 ? void 0 : newState.current) !== null && _a !== void 0 ? _a : {};
129
+ this.onSort(columnId, direction);
130
+ }
131
+ }
132
+ }
133
+ get sortState() {
134
+ return this.sort.current ? this.sort : undefined;
135
+ }
81
136
  // Updates the list of rows and regenerates the collapsedRows property if needed.
82
137
  setRows(rows) {
83
138
  // If the set of rows are different
@@ -252,11 +307,11 @@ class RowState {
252
307
  return [];
253
308
  }
254
309
  }
255
- exports.RowState = RowState;
256
- /** Provides a context for rows to access their table's `RowState`. */
257
- exports.RowStateContext = react_1.default.createContext({
258
- get rowState() {
259
- throw new Error("No RowStateContext provider");
310
+ exports.TableState = TableState;
311
+ /** Provides a context for rows to access their table's `TableState`. */
312
+ exports.TableStateContext = react_1.default.createContext({
313
+ get tableState() {
314
+ throw new Error("No TableStateContext provider");
260
315
  },
261
316
  });
262
317
  // Get the rows that are already in the toggled state, so we can keep them toggled
@@ -300,3 +355,32 @@ function flattenRows(rows) {
300
355
  const childRows = rows.flatMap((r) => (r.children ? flattenRows(r.children) : []));
301
356
  return [...rows, ...childRows];
302
357
  }
358
+ // Exported for testing purposes
359
+ function deriveSortState(currentSortState, clickedKey, initialSortState) {
360
+ var _a;
361
+ // If the current sort state is not defined then sort ASC on the clicked key.
362
+ if (!currentSortState.current) {
363
+ return { ...initialSortState, current: { columnId: clickedKey, direction: utils_1.ASC } };
364
+ }
365
+ const { current: { columnId: currentKey, direction: currentDirection }, } = currentSortState;
366
+ // If clicking a new column, then sort ASC on the clicked key
367
+ if (clickedKey !== currentKey) {
368
+ return { ...initialSortState, current: { columnId: clickedKey, direction: utils_1.ASC } };
369
+ }
370
+ // If there is an `initialSortState` and we're clicking on that same key, then flip the sort.
371
+ // Handles cases where the initial sort is DESC so that we can allow for DESC to ASC sorting.
372
+ if (initialSortState && ((_a = initialSortState.current) === null || _a === void 0 ? void 0 : _a.columnId) === clickedKey) {
373
+ return {
374
+ ...initialSortState,
375
+ current: { columnId: clickedKey, direction: currentDirection === utils_1.ASC ? utils_1.DESC : utils_1.ASC },
376
+ };
377
+ }
378
+ // Otherwise when clicking the current column, toggle through sort states
379
+ if (currentDirection === utils_1.ASC) {
380
+ // if ASC -> go to desc
381
+ return { ...initialSortState, current: { columnId: clickedKey, direction: utils_1.DESC } };
382
+ }
383
+ // Else, direction is already DESC, so revert to original sort value.
384
+ return initialSortState;
385
+ }
386
+ exports.deriveSortState = deriveSortState;
@@ -1,13 +1,13 @@
1
- import { GridColumn, Kinded } from "../types";
1
+ import { GridColumn, GridColumnWithId, Kinded } from "../types";
2
2
  /** Provides default styling for a GridColumn representing a Date. */
3
- export declare function column<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
3
+ export declare function column<T extends Kinded>(columnDef: GridColumn<T>): GridColumn<T>;
4
4
  /** Provides default styling for a GridColumn representing a Date. */
5
- export declare function dateColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
5
+ export declare function dateColumn<T extends Kinded>(columnDef: GridColumn<T>): GridColumn<T>;
6
6
  /**
7
7
  * Provides default styling for a GridColumn representing a Numeric value (Price, percentage, PO #, etc.). */
8
- export declare function numericColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
8
+ export declare function numericColumn<T extends Kinded>(columnDef: GridColumn<T>): GridColumn<T>;
9
9
  /** Provides default styling for a GridColumn representing an Action. */
10
- export declare function actionColumn<T extends Kinded, S = {}>(columnDef: GridColumn<T, S>): GridColumn<T, S>;
10
+ export declare function actionColumn<T extends Kinded>(columnDef: GridColumn<T>): GridColumn<T>;
11
11
  /**
12
12
  * Provides default styling for a GridColumn containing a checkbox.
13
13
  *
@@ -15,7 +15,7 @@ export declare function actionColumn<T extends Kinded, S = {}>(columnDef: GridCo
15
15
  * not have a `SelectToggle`, b/c we can provide the default behavior a `SelectToggle` for basically
16
16
  * all rows.
17
17
  */
18
- export declare function selectColumn<T extends Kinded, S = {}>(columnDef?: Partial<GridColumn<T, S>>): GridColumn<T, S>;
18
+ export declare function selectColumn<T extends Kinded>(columnDef?: Partial<GridColumn<T>>): GridColumn<T>;
19
19
  /**
20
20
  * Provides default styling for a GridColumn containing a collapse icon.
21
21
  *
@@ -23,9 +23,12 @@ export declare function selectColumn<T extends Kinded, S = {}>(columnDef?: Parti
23
23
  * not have a `CollapseToggle`, b/c we can provide the default behavior a `CollapseToggle` for basically
24
24
  * all rows.
25
25
  */
26
- export declare function collapseColumn<T extends Kinded, S = {}>(columnDef?: Partial<GridColumn<T, S>>): GridColumn<T, S>;
26
+ export declare function collapseColumn<T extends Kinded>(columnDef?: Partial<GridColumn<T>>): GridColumn<T>;
27
27
  /**
28
28
  * Calculates column widths using a flexible `calc()` definition that allows for consistent column alignment without the use of `<table />`, CSS Grid, etc layouts.
29
29
  * Enforces only fixed-sized units (% and px)
30
30
  */
31
31
  export declare function calcColumnSizes(columns: GridColumn<any>[], tableWidth: number | undefined, tableMinWidthPx?: number): string[];
32
+ /** Assign column ids if missing */
33
+ export declare function assignDefaultColumnIds<T extends Kinded>(columns: GridColumn<T>[]): GridColumnWithId<T>[];
34
+ export declare const generateColumnId: (columnIndex: number) => string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calcColumnSizes = exports.collapseColumn = exports.selectColumn = exports.actionColumn = exports.numericColumn = exports.dateColumn = exports.column = void 0;
3
+ exports.generateColumnId = exports.assignDefaultColumnIds = exports.calcColumnSizes = exports.collapseColumn = exports.selectColumn = exports.actionColumn = exports.numericColumn = exports.dateColumn = exports.column = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const CollapseToggle_1 = require("../components/CollapseToggle");
6
6
  const SelectToggle_1 = require("../components/SelectToggle");
@@ -37,6 +37,7 @@ exports.actionColumn = actionColumn;
37
37
  function selectColumn(columnDef) {
38
38
  const base = {
39
39
  ...nonKindDefaults(),
40
+ id: "beamSelectColumn",
40
41
  clientSideSort: false,
41
42
  align: "center",
42
43
  // Defining `w: 48px` to accommodate for the `16px` wide checkbox and `16px` of padding on either side.
@@ -63,6 +64,7 @@ exports.selectColumn = selectColumn;
63
64
  function collapseColumn(columnDef) {
64
65
  const base = {
65
66
  ...nonKindDefaults(),
67
+ id: "beamCollapseColumn",
66
68
  clientSideSort: false,
67
69
  align: "center",
68
70
  // Defining `w: 38px` based on the designs
@@ -147,3 +149,12 @@ function calcColumnSizes(columns, tableWidth, tableMinWidthPx = 0) {
147
149
  return sizes;
148
150
  }
149
151
  exports.calcColumnSizes = calcColumnSizes;
152
+ /** Assign column ids if missing */
153
+ function assignDefaultColumnIds(columns) {
154
+ // Note: we are not _always_ spreading the `c` property as we need to be able to return the whole proxy object that
155
+ // exists as part of `selectColumn` and `collapseColumn`.
156
+ return columns.map((c, idx) => { var _a; return (c.id ? c : { ...c, id: (_a = c.id) !== null && _a !== void 0 ? _a : (0, exports.generateColumnId)(idx) }); });
157
+ }
158
+ exports.assignDefaultColumnIds = assignDefaultColumnIds;
159
+ const generateColumnId = (columnIndex) => `c${columnIndex}`;
160
+ exports.generateColumnId = generateColumnId;
@@ -1,7 +1,7 @@
1
1
  import { ReactNode } from "react";
2
2
  import { GridCellContent } from "../components/cell";
3
3
  import { GridDataRow } from "../components/Row";
4
- import { SortOn, SortState } from "../hooks/useSortState";
5
- import { GridColumn, Kinded } from "../types";
6
- export declare function sortRows<R extends Kinded>(columns: GridColumn<R>[], rows: GridDataRow<R>[], sortState: SortState<number>, caseSensitive: boolean): GridDataRow<R>[];
4
+ import { GridColumn, GridColumnWithId, Kinded } from "../types";
5
+ import { SortOn, SortState } from "./TableState";
6
+ export declare function sortRows<R extends Kinded>(columns: GridColumnWithId<R>[], rows: GridDataRow<R>[], sortState: SortState, caseSensitive: boolean): GridDataRow<R>[];
7
7
  export declare function ensureClientSideSortValueIsSortable(sortOn: SortOn, isHeader: boolean, column: GridColumn<any>, idx: number, maybeContent: ReactNode | GridCellContent): void;
@@ -16,11 +16,13 @@ function sortRows(columns, rows, sortState, caseSensitive) {
16
16
  exports.sortRows = sortRows;
17
17
  function sortBatch(columns, batch, sortState, caseSensitive) {
18
18
  // When client-side sort, the sort value is the column index
19
- const [value, direction, primaryKey, primaryDirection] = sortState;
20
- const column = columns[value];
19
+ const { current, persistent } = sortState !== null && sortState !== void 0 ? sortState : {};
20
+ const { columnId, direction } = current !== null && current !== void 0 ? current : {};
21
+ const { columnId: persistentSortColumnId, direction: persistentSortDirection } = persistent !== null && persistent !== void 0 ? persistent : {};
22
+ const column = columns.find((c) => c.id === columnId);
21
23
  const invert = direction === "DESC";
22
- const primaryInvert = primaryDirection === "DESC";
23
- const primaryColumn = primaryKey && columns[primaryKey];
24
+ const primaryInvert = persistentSortDirection === "DESC";
25
+ const primaryColumn = persistentSortColumnId && columns.find((c) => c.id === persistentSortColumnId);
24
26
  // Make a shallow copy for sorting to avoid mutating the original list
25
27
  return [...batch].sort((a, b) => {
26
28
  if (a.pin || b.pin) {
@@ -41,7 +43,7 @@ function sortBatch(columns, batch, sortState, caseSensitive) {
41
43
  return primaryCompare;
42
44
  }
43
45
  }
44
- return compare(column, a, b, invert, caseSensitive);
46
+ return column ? compare(column, a, b, invert, caseSensitive) : 0;
45
47
  });
46
48
  }
47
49
  function getPin(pin) {
@@ -3,20 +3,20 @@ import { GridCellContent } from "../components/cell";
3
3
  import { GridDataRow } from "../components/Row";
4
4
  import { GridTableApi } from "../GridTableApi";
5
5
  import { GridStyle, RowStyle } from "../TableStyles";
6
- import { GridCellAlignment, GridColumn, Kinded, RenderAs } from "../types";
6
+ import { GridCellAlignment, GridColumnWithId, Kinded, RenderAs } from "../types";
7
7
  import { Properties } from "../../../Css";
8
8
  /** If a column def return just string text for a given row, apply some default styling. */
9
- export declare function toContent(maybeContent: ReactNode | GridCellContent, isHeader: boolean, canSortColumn: boolean, isClientSideSorting: boolean, style: GridStyle, as: RenderAs, alignment: GridCellAlignment): ReactNode;
9
+ export declare function toContent(maybeContent: ReactNode | GridCellContent, isHeader: boolean, canSortColumn: boolean, isClientSideSorting: boolean, style: GridStyle, as: RenderAs, alignment: GridCellAlignment, column: GridColumnWithId<any>): ReactNode;
10
10
  export declare function isGridCellContent(content: ReactNode | GridCellContent): content is GridCellContent;
11
11
  /** Return the content for a given column def applied to a given row. */
12
- export declare function applyRowFn<R extends Kinded>(column: GridColumn<R>, row: GridDataRow<R>, api: GridTableApi<R>, level: number): ReactNode | GridCellContent;
12
+ export declare function applyRowFn<R extends Kinded>(column: GridColumnWithId<R>, row: GridDataRow<R>, api: GridTableApi<R>, level: number): ReactNode | GridCellContent;
13
13
  export declare const ASC: "ASC";
14
14
  export declare const DESC: "DESC";
15
15
  export declare const emptyCell: GridCellContent;
16
16
  export declare function getIndentationCss<R extends Kinded>(style: GridStyle, rowStyle: RowStyle<R> | undefined, columnIndex: number, maybeContent: ReactNode | GridCellContent): Properties;
17
- export declare function getFirstOrLastCellCss<R extends Kinded>(style: GridStyle, columnIndex: number, columns: GridColumn<R>[]): Properties;
18
- export declare function getAlignment(column: GridColumn<any>, maybeContent: ReactNode | GridCellContent): GridCellAlignment;
19
- export declare function getJustification(column: GridColumn<any>, maybeContent: ReactNode | GridCellContent, as: RenderAs, alignment: GridCellAlignment): {
17
+ export declare function getFirstOrLastCellCss<R extends Kinded>(style: GridStyle, columnIndex: number, columns: GridColumnWithId<R>[]): Properties;
18
+ export declare function getAlignment(column: GridColumnWithId<any>, maybeContent: ReactNode | GridCellContent): GridCellAlignment;
19
+ export declare function getJustification(column: GridColumnWithId<any>, maybeContent: ReactNode | GridCellContent, as: RenderAs, alignment: GridCellAlignment): {
20
20
  textAlign: import("csstype").Property.TextAlign | undefined;
21
21
  };
22
22
  export declare function maybeApplyFunction<T>(row: T, maybeFn: Properties | ((row: T) => Properties) | undefined): Properties | undefined;
@@ -6,7 +6,7 @@ const SortHeader_1 = require("../components/SortHeader");
6
6
  const Css_1 = require("../../../Css");
7
7
  const getInteractiveElement_1 = require("../../../utils/getInteractiveElement");
8
8
  /** If a column def return just string text for a given row, apply some default styling. */
9
- function toContent(maybeContent, isHeader, canSortColumn, isClientSideSorting, style, as, alignment) {
9
+ function toContent(maybeContent, isHeader, canSortColumn, isClientSideSorting, style, as, alignment, column) {
10
10
  var _a, _b;
11
11
  let content = isGridCellContent(maybeContent) ? maybeContent.content : maybeContent;
12
12
  if (typeof content === "function") {
@@ -32,7 +32,7 @@ function toContent(maybeContent, isHeader, canSortColumn, isClientSideSorting, s
32
32
  })
33
33
  : content;
34
34
  if (content && typeof content === "string" && isHeader && canSortColumn) {
35
- return (0, jsx_runtime_1.jsx)(SortHeader_1.SortHeader, { content: content, iconOnLeft: alignment === "right" }, void 0);
35
+ return (0, jsx_runtime_1.jsx)(SortHeader_1.SortHeader, { content: content, iconOnLeft: alignment === "right", column: column }, void 0);
36
36
  }
37
37
  else if (content && ((_b = style === null || style === void 0 ? void 0 : style.presentationSettings) === null || _b === void 0 ? void 0 : _b.wrap) === false && typeof content === "string") {
38
38
  // In order to truncate the text properly, then we need to wrap it in another element
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.198.0",
3
+ "version": "2.199.1",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -1,15 +0,0 @@
1
- import { GridSortConfig } from "../GridTable";
2
- import { Direction, GridColumn, Kinded } from "../types";
3
- /**
4
- * Our internal sorting state.
5
- *
6
- * `S` is, for whatever current column we're sorting by, either it's:
7
- *
8
- * a) `serverSideSortKey` if we're server-side sorting, or
9
- * b) it's index in the `columns` array, if client-side sorting
10
- */
11
- export declare type SortState<S> = readonly [S, Direction, S | undefined, Direction | undefined];
12
- export declare type SortOn = "client" | "server" | undefined;
13
- /** Small custom hook that wraps the "setSortColumn inverts the current sort" logic. */
14
- export declare function useSortState<R extends Kinded, S>(columns: GridColumn<R, S>[], sorting?: GridSortConfig<S>): [SortState<S> | undefined, (value: S) => void, SortOn, boolean];
15
- export declare function deriveSortState<S>(currentSortState: SortState<S> | undefined, clickedKey: S, initialSortState: SortState<S> | undefined): SortState<S> | undefined;
@@ -1,76 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deriveSortState = exports.useSortState = void 0;
4
- const react_1 = require("react");
5
- const utils_1 = require("../utils/utils");
6
- /** Small custom hook that wraps the "setSortColumn inverts the current sort" logic. */
7
- function useSortState(columns, sorting) {
8
- // If we're server-side sorting, use the caller's `sorting.value` prop to initialize our internal
9
- // `useState`. After this, we ignore `sorting.value` because we assume it should match what our
10
- // `setSortState` just changed anyway (in response to the user sorting a column).
11
- const initialSortState = (0, react_1.useMemo)(() => {
12
- if ((sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client") {
13
- const { initial, primary } = sorting;
14
- const primaryKey = primary && (typeof primary[0] === "number" ? primary[0] : columns.indexOf(primary[0]));
15
- if (initial === undefined && "initial" in sorting) {
16
- // if explicitly set to `undefined`, then do not sort
17
- return undefined;
18
- }
19
- else if (initial) {
20
- const key = typeof initial[0] === "number" ? initial[0] : columns.indexOf(initial[0]);
21
- return [key, initial[1], primaryKey, primary === null || primary === void 0 ? void 0 : primary[1]];
22
- }
23
- else {
24
- // If no explicit sorting, assume 1st column ascending
25
- const firstSortableColumn = columns.findIndex((c) => c.clientSideSort !== false);
26
- return [firstSortableColumn, utils_1.ASC, primaryKey, primary === null || primary === void 0 ? void 0 : primary[1]];
27
- }
28
- }
29
- else {
30
- return (sorting === null || sorting === void 0 ? void 0 : sorting.value) ? [sorting === null || sorting === void 0 ? void 0 : sorting.value[0], sorting === null || sorting === void 0 ? void 0 : sorting.value[1], undefined, undefined] : undefined;
31
- }
32
- },
33
- // We want to allow the user to not memoize `GridTableProps.sorting` b/c for the
34
- // initialSortState calc, it's just a bunch of surely hard-coded primitives like
35
- // sort on client/server, which column is initial.
36
- // eslint-disable-next-line react-hooks/exhaustive-deps
37
- [columns]);
38
- const [sortState, setSortState] = (0, react_1.useState)(initialSortState);
39
- // Make a custom setSortKey that is useState-like but contains the ASC->DESC->RESET logic.
40
- const onSort = (sorting === null || sorting === void 0 ? void 0 : sorting.on) === "server" ? sorting.onSort : undefined;
41
- const setSortKey = (0, react_1.useCallback)((clickedKey) => {
42
- const newState = deriveSortState(sortState, clickedKey, initialSortState);
43
- setSortState(newState);
44
- if (onSort) {
45
- const [newKey, newDirection] = newState !== null && newState !== void 0 ? newState : [undefined, undefined];
46
- onSort(newKey, newDirection);
47
- }
48
- },
49
- // Note that sorting.onSort is not listed here, so we bind to whatever the 1st sorting.onSort was
50
- [initialSortState, sortState, onSort]);
51
- // If sorting is done on the client, the by default the sort will NOT be case sensitive
52
- const caseSensitive = (sorting === null || sorting === void 0 ? void 0 : sorting.on) === "client" ? !!sorting.caseSensitive : false;
53
- return [sortState, setSortKey, sorting === null || sorting === void 0 ? void 0 : sorting.on, caseSensitive];
54
- }
55
- exports.useSortState = useSortState;
56
- // Exported for testing purposes
57
- function deriveSortState(currentSortState, clickedKey, initialSortState) {
58
- const [currentKey, currentDirection] = currentSortState || [];
59
- // If the current sort state is not defined, or clicking a new column, then sort ASC on the clicked key
60
- if (!currentSortState || clickedKey !== currentKey) {
61
- return [clickedKey, utils_1.ASC, initialSortState === null || initialSortState === void 0 ? void 0 : initialSortState[2], initialSortState === null || initialSortState === void 0 ? void 0 : initialSortState[3]];
62
- }
63
- // If there is an `initialSortState` and we're clicking on that same key, then flip the sort.
64
- // Handles cases where the initial sort is DESC so that we can allow for DESC to ASC sorting.
65
- if (initialSortState && initialSortState[0] === clickedKey) {
66
- return [clickedKey, currentDirection === utils_1.ASC ? utils_1.DESC : utils_1.ASC, initialSortState === null || initialSortState === void 0 ? void 0 : initialSortState[2], initialSortState === null || initialSortState === void 0 ? void 0 : initialSortState[3]];
67
- }
68
- // Otherwise when clicking the current column, toggle through sort states
69
- if (currentDirection === utils_1.ASC) {
70
- // if ASC -> go to desc
71
- return [clickedKey, utils_1.DESC, initialSortState === null || initialSortState === void 0 ? void 0 : initialSortState[2], initialSortState === null || initialSortState === void 0 ? void 0 : initialSortState[3]];
72
- }
73
- // Else, direction is already DESC, so revert to original sort value.
74
- return initialSortState;
75
- }
76
- exports.deriveSortState = deriveSortState;
@@ -1,13 +0,0 @@
1
- import React from "react";
2
- /**
3
- * Provides the sorting settings to headers.
4
- *
5
- * This is broken out into it's own context (i.e. separate from `GridCollapseContextProps`)
6
- * so that we can have sort changes only re-render the header row, and not trigger a re-render
7
- * of every row in the table.
8
- */
9
- export declare type GridSortContextProps = {
10
- sorted: "ASC" | "DESC" | undefined;
11
- toggleSort(): void;
12
- };
13
- export declare const GridSortContext: React.Context<GridSortContextProps>;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.GridSortContext = void 0;
7
- const react_1 = __importDefault(require("react"));
8
- exports.GridSortContext = react_1.default.createContext({
9
- sorted: undefined,
10
- toggleSort: () => { },
11
- });