@homebound/beam 2.304.1 → 2.305.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
- import { GridDataRow, SelectedState } from "../../..";
1
+ import { GridDataRow } from "../components/Row";
2
2
  import { RowStates } from "./RowStates";
3
+ import { SelectedState } from "./TableState";
3
4
  /**
4
5
  * A reactive/observable state of each GridDataRow's current behavior.
5
6
  *
@@ -7,6 +8,7 @@ import { RowStates } from "./RowStates";
7
8
  * that uses parent/children easier to write, i.e. selected-ness and collapsed-ness.
8
9
  */
9
10
  export declare class RowState {
11
+ private states;
10
12
  /** Our row, only ref observed, so we don't crawl into GraphQL fragments. */
11
13
  row: GridDataRow<any>;
12
14
  /** Our children row states, as of the latest `props.rows`, without any filtering applied. */
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RowState = void 0;
4
4
  const mobx_1 = require("mobx");
5
- const src_1 = require("../../..");
5
+ const utils_1 = require("./utils");
6
6
  /**
7
7
  * A reactive/observable state of each GridDataRow's current behavior.
8
8
  *
@@ -15,6 +15,7 @@ class RowState {
15
15
  // isEffectiveMatched = isDirectlyMatched || hasMatchedChildren
16
16
  constructor(states, row) {
17
17
  var _a;
18
+ this.states = states;
18
19
  /** Our children row states, as of the latest `props.rows`, without any filtering applied. */
19
20
  this.children = undefined;
20
21
  /** Whether we match a client-side filter; true if no filter is in place. */
@@ -108,21 +109,19 @@ class RowState {
108
109
  * child of a selected parent row.
109
110
  */
110
111
  select(selected) {
111
- if (this.row.selectable === false)
112
- return;
113
- this.selected = selected;
112
+ if (this.row.selectable !== false) {
113
+ this.selected = selected;
114
+ }
114
115
  // We don't check inferSelectedState here, b/c even if the parent is considered selectable
115
116
  // on its own, we still push down selected-ness to our visible children.
116
- if (this.children) {
117
- for (const child of this.visibleChildren) {
118
- child.select(selected);
119
- }
117
+ for (const child of this.visibleChildren) {
118
+ child.select(selected);
120
119
  }
121
120
  }
122
121
  /** Marks the row as removed from `props.rows`, to potentially become kept. */
123
122
  markRemoved() {
124
123
  // The kept group is never in `props.rows`, so ignore asks to delete it
125
- if (this.row.kind === src_1.KEPT_GROUP)
124
+ if (this.row.kind === utils_1.KEPT_GROUP)
126
125
  return;
127
126
  this.removed = this.selected && this.removed !== "hard" ? "soft" : "hard";
128
127
  }
@@ -136,7 +135,7 @@ class RowState {
136
135
  // - or it has (probably) been server-side filtered
137
136
  return (this.selected &&
138
137
  // Headers, totals, etc., do not need keeping
139
- !src_1.reservedRowKinds.includes(this.row.kind) &&
138
+ !utils_1.reservedRowKinds.includes(this.row.kind) &&
140
139
  !this.isParent &&
141
140
  (!this.isMatched || this.removed === "soft"));
142
141
  }
@@ -144,15 +143,15 @@ class RowState {
144
143
  return this.row.inferSelectedState !== false;
145
144
  }
146
145
  get visibleChildren() {
147
- var _a, _b, _c;
148
- // The keptGroup should treat all of its children as visible, as this makes select/unselect all work.
149
- if (this.row.kind === src_1.KEPT_GROUP)
150
- return (_a = this.children) !== null && _a !== void 0 ? _a : [];
146
+ var _a, _b;
147
+ // The keptGroup is special and its children are the dynamically kept rows
148
+ if (this.row.kind === utils_1.KEPT_GROUP)
149
+ return this.states.keptRows;
151
150
  // Ignore hard-deleted rows, i.e. from `api.deleteRows`; in theory any hard-deleted
152
151
  // rows should be removed from `this.children` anyway, by a change to `props.rows`,
153
152
  // but just in case the user calls _only_ `api.deleteRows`, and expects the row to
154
153
  // go away, go ahead and filter them out here.
155
- return (_c = (_b = this.children) === null || _b === void 0 ? void 0 : _b.filter((c) => c.isMatched === true && c.removed !== "hard")) !== null && _c !== void 0 ? _c : [];
154
+ return (_b = (_a = this.children) === null || _a === void 0 ? void 0 : _a.filter((c) => c.isMatched === true && c.removed !== "hard")) !== null && _b !== void 0 ? _b : [];
156
155
  }
157
156
  /**
158
157
  * Returns whether this row should act like a parent.
@@ -31,5 +31,5 @@ export declare class RowStates {
31
31
  get keptRows(): RowState[];
32
32
  get collapsedRows(): RowState[];
33
33
  /** Create our synthetic "group row" for kept rows, that users never pass in, but we self-inject as needed. */
34
- private creatKeptGroupRow;
34
+ private createKeptGroupRow;
35
35
  }
@@ -14,7 +14,7 @@ class RowStates {
14
14
  this.map = new mobx_1.ObservableMap();
15
15
  this.storage = new RowStorage_1.RowStorage(this);
16
16
  // Pre-create our keptGroupRow for if/when we need it.
17
- this.keptGroupRow = this.creatKeptGroupRow();
17
+ this.keptGroupRow = this.createKeptGroupRow();
18
18
  this.header = undefined;
19
19
  /** The first level of rows, i.e. not the header (or kept group), but the totals + top-level children. */
20
20
  this.topRows = [];
@@ -65,22 +65,16 @@ class RowStates {
65
65
  this.topRows = rows.filter((row) => row !== headerRow).map((row) => addRowAndChildren(row));
66
66
  // And attach them to the header for select-all/etc. to work
67
67
  if (this.header) {
68
- this.header.children = this.topRows.filter((rs) => !utils_1.reservedRowKinds.includes(rs.row.kind));
68
+ this.header.children = [
69
+ // Always add the keptGroupRow, and we'll use keptGroupRow.isMatched=true/false to keep it
70
+ // from messing up "header is all selected" if its hidden/when there are no kept rows.
71
+ this.keptGroupRow,
72
+ ...this.topRows.filter((rs) => !utils_1.reservedRowKinds.includes(rs.row.kind)),
73
+ ];
69
74
  }
70
75
  // Then mark any remaining as removed
71
76
  for (const state of existing)
72
77
  state.markRemoved();
73
- const keptRows = this.keptRows;
74
- if (keptRows.length > 0) {
75
- // Stitch the current keptRows into the placeholder keptGroupRow
76
- this.keptGroupRow.children = keptRows;
77
- this.keptGroupRow.row.children = keptRows.map((rs) => rs.row);
78
- // And then stitch the keptGroupRow itself into the root header, so that the kept rows
79
- // are treated as just another child for the header's select/unselect all to work.
80
- if (this.header) {
81
- this.header.children.unshift(this.keptGroupRow);
82
- }
83
- }
84
78
  // After the first load of real data, we detach collapse state, to respect
85
79
  // any incoming initCollapsed.
86
80
  if (this.topRows.some((rs) => !utils_1.reservedRowKinds.includes(rs.row.kind))) {
@@ -134,6 +128,11 @@ class RowStates {
134
128
  rs.isMatched = ids.includes(rs.row.id);
135
129
  }
136
130
  }
131
+ // We cheat a little and pretend the "kept group matches the filter" not based on it itself
132
+ // literally matching the filter, or its children matching the filter (which is typically
133
+ // how the filter logic works), but if it just has any child rows at all (which actually means
134
+ // its children did _not_ match the filter, but are kept).
135
+ this.keptGroupRow.isMatched = this.keptRows.length > 0;
137
136
  }
138
137
  /** Returns kept rows, i.e. those that were user-selected but then client-side or server-side filtered. */
139
138
  get keptRows() {
@@ -143,10 +142,20 @@ class RowStates {
143
142
  return this.allStates.filter((rs) => rs.collapsed);
144
143
  }
145
144
  /** Create our synthetic "group row" for kept rows, that users never pass in, but we self-inject as needed. */
146
- creatKeptGroupRow() {
145
+ createKeptGroupRow() {
147
146
  // The "group row" for selected rows that are hidden by filters and add the children
148
- const keptGroupRow = { id: utils_1.KEPT_GROUP, kind: utils_1.KEPT_GROUP, initCollapsed: true, data: undefined };
149
- return new RowState_1.RowState(this, keptGroupRow);
147
+ const keptGroupRow = {
148
+ id: utils_1.KEPT_GROUP,
149
+ kind: utils_1.KEPT_GROUP,
150
+ initCollapsed: true,
151
+ selectable: false,
152
+ data: undefined,
153
+ children: [],
154
+ };
155
+ const rs = new RowState_1.RowState(this, keptGroupRow);
156
+ // Make the RowState behave like a parent, even though we calc its visibleChildren.
157
+ rs.children = [];
158
+ return rs;
150
159
  }
151
160
  }
152
161
  exports.RowStates = RowStates;
@@ -45,12 +45,8 @@ class TableState {
45
45
  // Make ourselves an observable so that mobx will do caching of .collapseIds so
46
46
  // that it'll be a stable identity for GridTable to useMemo against.
47
47
  (0, mobx_1.makeAutoObservable)(this, {
48
- // We only shallow observe rows so that:
49
- // a) we don't deeply/needlessly proxy-ize a large Apollo fragment cache, but
50
- // b) if rows changes, we re-run computeds like getSelectedRows that may need to see the
51
- // updated _contents_ of a given row, even if our other selected/matched row states don't change.
52
- // (as any b/c rows is private, so the mapped type doesn't see it)
53
- rows: mobx_1.observable.shallow,
48
+ // We use `ref`s so that observables can watch the immutable data change w/o deeply proxy-ifying Apollo fragments
49
+ rows: mobx_1.observable.ref,
54
50
  columns: mobx_1.observable.ref,
55
51
  });
56
52
  // If the kept rows went from empty to not empty, then introduce the SELECTED_GROUP row as collapsed
@@ -119,10 +115,6 @@ class TableState {
119
115
  }
120
116
  // Updates the list of rows and regenerates the collapsedRows property if needed.
121
117
  setRows(rows) {
122
- // Note that because of using `rows: observable.shallow` above, this is always
123
- // false, and this logic runs on every render. We can eventually fix this, but it
124
- // is convenient b/c it puts no-longer-kept rows back into the right spot in their
125
- // parents.
126
118
  if (rows !== this.rows) {
127
119
  this.rowStates.setRows(rows);
128
120
  this.rows = rows;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.304.1",
3
+ "version": "2.305.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",