@homebound/beam 2.243.0 → 2.244.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.
@@ -16,6 +16,6 @@ class SingleFilter extends BaseFilter_1.BaseFilter {
16
16
  const options = Array.isArray(maybeOptions)
17
17
  ? [allOption, ...maybeOptions]
18
18
  : { ...maybeOptions, initial: [allOption, ...maybeOptions.initial] };
19
- return ((0, jsx_runtime_1.jsx)(SelectField_1.SelectField, { ...props, options: options, getOptionValue: (o) => (o === allOption ? undefined : getOptionValue(o)), getOptionLabel: (o) => (o === allOption ? "All" : getOptionLabel(o)), compact: !vertical, value: value, label: this.label, labelStyle: inModal ? "hidden" : !inModal && !vertical ? "inline" : "above", sizeToContent: !inModal && !vertical, nothingSelectedText: nothingSelectedText || "All", onSelect: (value) => setValue(value || undefined), ...this.testId(tid) }));
19
+ return ((0, jsx_runtime_1.jsx)(SelectField_1.SelectField, { ...props, options: options, getOptionValue: (o) => (o === allOption ? undefined : getOptionValue(o)), getOptionLabel: (o) => (o === allOption ? nothingSelectedText !== null && nothingSelectedText !== void 0 ? nothingSelectedText : "All" : getOptionLabel(o)), compact: !vertical, value: value, label: this.label, labelStyle: inModal ? "hidden" : !inModal && !vertical ? "inline" : "above", sizeToContent: !inModal && !vertical, nothingSelectedText: nothingSelectedText !== null && nothingSelectedText !== void 0 ? nothingSelectedText : "All", onSelect: (value) => setValue(value || undefined), ...this.testId(tid) }));
20
20
  }
21
21
  }
@@ -51,6 +51,7 @@ export type DateRangeFilter = NonNullable<FilterDefs<ProjectFilter>["dateRange"]
51
51
  export declare const stageFilter: StageFilter;
52
52
  export declare const stageFilterDisabledOptions: StageFilter;
53
53
  export declare const stageSingleFilter: StageSingleFilter;
54
+ export declare const stageFilterWithNothingSelectedText: StageSingleFilter;
54
55
  export declare const taskDueFilter: DateFilter;
55
56
  export declare const taskCompleteFilter: DateRangeFilter;
56
57
  export declare enum TaskStatus {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ScheduleTypes = exports.TaskStatus = exports.taskCompleteFilter = exports.taskDueFilter = exports.stageSingleFilter = exports.stageFilterDisabledOptions = exports.stageFilter = exports.Stage = void 0;
3
+ exports.ScheduleTypes = exports.TaskStatus = exports.taskCompleteFilter = exports.taskDueFilter = exports.stageFilterWithNothingSelectedText = exports.stageSingleFilter = exports.stageFilterDisabledOptions = exports.stageFilter = exports.Stage = void 0;
4
4
  const DateFilter_1 = require("./DateFilter");
5
5
  const DateRangeFilter_1 = require("./DateRangeFilter");
6
6
  const MultiFilter_1 = require("./MultiFilter");
@@ -30,6 +30,12 @@ exports.stageSingleFilter = (0, SingleFilter_1.singleFilter)({
30
30
  getOptionValue: (s) => s.code,
31
31
  getOptionLabel: (s) => s.name,
32
32
  });
33
+ exports.stageFilterWithNothingSelectedText = (0, SingleFilter_1.singleFilter)({
34
+ options: stageOptions,
35
+ getOptionValue: (s) => s.code,
36
+ getOptionLabel: (s) => s.name,
37
+ nothingSelectedText: "All Stages",
38
+ });
33
39
  exports.taskDueFilter = (0, DateFilter_1.dateFilter)({
34
40
  operations: [
35
41
  { label: "On", value: "ON" },
@@ -25,9 +25,8 @@ function ExpandableHeader(props) {
25
25
  await tableState.loadExpandedColumns(column);
26
26
  setIsLoading(false);
27
27
  }
28
- else {
29
- tableState.toggleExpandedColumn(column.id);
30
- }
28
+ // manually calling this as loadExpandedColumns does not toggle
29
+ tableState.toggleExpandedColumn(column.id);
31
30
  }, "data-testid": "expandableColumn", children: [(0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.tl.lineClamp2
32
31
  .if(applyStickyStyles)
33
32
  .sticky.leftPx(minStickyLeftOffset + 12)
@@ -47,6 +47,10 @@ export declare class TableState {
47
47
  get sortState(): SortState | undefined;
48
48
  setRows(rows: GridDataRow<any>[]): void;
49
49
  setColumns(columns: GridColumnWithId<any>[], visibleColumnsStorageKey: string | undefined): void;
50
+ /** Determines which columns to expand immediately vs async */
51
+ parseAndUpdateExpandedColumns(columnsToExpand: GridColumnWithId<any>[]): void;
52
+ /** Updates the state of which columns are expanded */
53
+ updateExpandedColumns(newColumns: GridColumnWithId<any>[]): void;
50
54
  loadExpandedColumns(column: GridColumnWithId<any>): Promise<void>;
51
55
  getExpandedColumns(column: GridColumnWithId<any>): GridColumnWithId<any>[];
52
56
  setVisibleColumns(ids: string[]): void;
@@ -166,7 +166,7 @@ class TableState {
166
166
  const flattenedExistingIds = flattenRows(this.rows).map((r) => r.id);
167
167
  const newCollapsedIds = maybeNewCollapsedRowIds.filter((maybeNewRowId) => !flattenedExistingIds.includes(maybeNewRowId) &&
168
168
  // Using `!` on `this.persistCollapse!` as `checkLocalStorage` ensures this.persistCollapse is truthy
169
- (!checkLocalStorage || readLocalCollapseState(this.persistCollapse).includes(maybeNewRowId)));
169
+ (!checkLocalStorage || readCollapsedRowStorage(this.persistCollapse).includes(maybeNewRowId)));
170
170
  // If there are new rows that should be collapsed then update the collapsedRows arrays
171
171
  if (newCollapsedIds.length > 0) {
172
172
  this.collapsedRows.replace(currentCollapsedIds.concat(newCollapsedIds));
@@ -183,32 +183,81 @@ class TableState {
183
183
  setColumns(columns, visibleColumnsStorageKey) {
184
184
  const isInitial = !this.columns || this.columns.length === 0;
185
185
  if (columns !== this.columns) {
186
- this.columns = columns;
187
186
  this.visibleColumnsStorageKey = visibleColumnsStorageKey !== null && visibleColumnsStorageKey !== void 0 ? visibleColumnsStorageKey : (0, change_case_1.camelCase)(columns.map((c) => c.id).join());
188
187
  this.visibleColumns.replace(readOrSetLocalVisibleColumnState(columns, this.visibleColumnsStorageKey));
189
- const expandedColumnIds = columns.filter((c) => c.initExpanded).map((c) => c.id);
190
- if (isInitial)
191
- this.expandedColumns.replace(expandedColumnIds);
188
+ // Figure out which columns need to be expanded when rendering a new set of columns
189
+ const localStorageColumns = this.persistCollapse ? readExpandedColumnsStorage(this.persistCollapse) : [];
190
+ // On initial render the columns we start with is whatever is in local storage.
191
+ // On any subsequent render, we start with an empty array.
192
+ // (We'll add to this after figuring out which columns are new vs existing.)
193
+ const columnIdsToExpand = isInitial ? localStorageColumns : [];
194
+ // Create a list of all existing column ids. (We ignore the `initExpanded` property for existing columns)
195
+ const existingColumnIds = this.columns.map((c) => c.id);
196
+ // Add any columns to our array that are new columns that should be initially expanded.
197
+ columnIdsToExpand.push(...columns.filter((c) => !existingColumnIds.includes(c.id) && c.initExpanded).map((c) => c.id));
198
+ // Send the new array of columns along to be parsed and expanded.
199
+ this.parseAndUpdateExpandedColumns(columns.filter((c) => columnIdsToExpand.includes(c.id)));
200
+ this.columns = columns;
201
+ }
202
+ }
203
+ /** Determines which columns to expand immediately vs async */
204
+ parseAndUpdateExpandedColumns(columnsToExpand) {
205
+ // Separate out which columns need to be loaded async vs which can be loaded immediately.
206
+ const [localColumnsToExpand, asyncColumnsToExpand] = columnsToExpand.reduce((acc, c) => {
207
+ if ((0, utils_2.isFunction)(c.expandColumns)) {
208
+ return [acc[0], acc[1].concat(c)];
209
+ }
210
+ return [acc[0].concat(c), acc[1]];
211
+ }, [[], []]);
212
+ // Handle all async expanding columns using a Promise.all.
213
+ // This will allow the table to render immediately, then cause a rerender with the new columns
214
+ if (asyncColumnsToExpand.length > 0) {
215
+ Promise.all(asyncColumnsToExpand.map(async (c) => await this.loadExpandedColumns(c))).then(() => this.updateExpandedColumns(asyncColumnsToExpand));
216
+ }
217
+ // For local columns, we skip the Promise in order to have the correct state on the initial load.
218
+ if (localColumnsToExpand.length > 0) {
219
+ this.updateExpandedColumns(localColumnsToExpand);
220
+ }
221
+ }
222
+ /** Updates the state of which columns are expanded */
223
+ updateExpandedColumns(newColumns) {
224
+ const newColumnIds = newColumns.map((c) => c.id);
225
+ // If there is a difference between list of current expanded columns vs list we just created, then replace
226
+ const isDifferent = newColumnIds.length !== this.expandedColumnIds.length ||
227
+ !this.expandedColumnIds.every((c) => newColumnIds.includes(c));
228
+ if (isDifferent) {
229
+ // Note: `this.expandedColumns` is a Set, so it will take care of dedupe-ing.
230
+ this.expandedColumns.replace([...this.expandedColumnIds, ...newColumnIds]);
231
+ // Update session storage if necessary.
232
+ if (this.persistCollapse) {
233
+ sessionStorage.setItem(getColumnStorageKey(this.persistCollapse), JSON.stringify([...this.expandedColumns]));
234
+ }
192
235
  }
193
236
  }
194
237
  // load and trigger column to be expanded
195
238
  async loadExpandedColumns(column) {
196
- // if we dont have anything in our cache and our expanded columns are a function
239
+ // if we don't have anything in our cache and our expanded columns are a function
197
240
  if (!this.loadedColumns.has(column.id) && (0, utils_2.isFunction)(column.expandColumns)) {
198
241
  // set our result to the function call of expandColumns
199
242
  const result = await column.expandColumns();
200
243
  // once we have the loaded columns, add result to local cache
201
244
  this.loadedColumns.set(column.id, (0, columns_1.assignDefaultColumnIds)(result));
202
245
  }
203
- // once column is in local cache, then toggle
204
- this.toggleExpandedColumn(column.id);
205
246
  }
206
- // if there is a promise, then load the expandable columns from the cache, if not then return the expandedColumns
247
+ // if there is a promise, then grab the already loaded expandable columns from the cache, if not then return the expandedColumns property
207
248
  getExpandedColumns(column) {
208
249
  var _a, _b;
209
250
  return (0, utils_2.isFunction)(column.expandColumns) ? (_a = this.loadedColumns.get(column.id)) !== null && _a !== void 0 ? _a : [] : (_b = column.expandColumns) !== null && _b !== void 0 ? _b : [];
210
251
  }
211
252
  setVisibleColumns(ids) {
253
+ // If we have a new visible columns, then we need to check if some need to be initially expanded when made visible
254
+ if (ids.length > this.visibleColumnIds.length) {
255
+ // Get a list of columns that are just now being made visible.
256
+ const newlyVisibleIds = ids.filter((id) => !this.visibleColumnIds.includes(id));
257
+ // Figure out if any of these newly visible columns needs to be initially expanded.
258
+ const columnsToExpand = this.columns.filter((c) => newlyVisibleIds.includes(c.id) && c.initExpanded);
259
+ this.parseAndUpdateExpandedColumns(columnsToExpand);
260
+ }
212
261
  sessionStorage.setItem(this.visibleColumnsStorageKey, JSON.stringify(ids));
213
262
  this.visibleColumns.replace(ids);
214
263
  }
@@ -225,6 +274,9 @@ class TableState {
225
274
  else {
226
275
  this.expandedColumns.add(columnId);
227
276
  }
277
+ if (this.persistCollapse) {
278
+ sessionStorage.setItem(getColumnStorageKey(this.persistCollapse), JSON.stringify(this.expandedColumnIds));
279
+ }
228
280
  }
229
281
  setMatchedRows(rowIds) {
230
282
  // ObservableSet doesn't seem to do a `diff` inside `replace` before firing
@@ -385,11 +437,14 @@ exports.TableStateContext = react_1.default.createContext({
385
437
  throw new Error("No TableStateContext provider");
386
438
  },
387
439
  });
388
- // Get the rows that are already in the toggled state, so we can keep them toggled
389
- function readLocalCollapseState(persistCollapse) {
440
+ function readCollapsedRowStorage(persistCollapse) {
390
441
  const collapsedGridRowIds = sessionStorage.getItem(persistCollapse);
391
442
  return collapsedGridRowIds ? JSON.parse(collapsedGridRowIds) : [];
392
443
  }
444
+ function readExpandedColumnsStorage(persistCollapse) {
445
+ const expandedGridColumnIds = sessionStorage.getItem(getColumnStorageKey(persistCollapse));
446
+ return expandedGridColumnIds ? JSON.parse(expandedGridColumnIds) : [];
447
+ }
393
448
  // Get the columns that are already in the visible state so we keep them toggled.
394
449
  function readOrSetLocalVisibleColumnState(columns, storageKey) {
395
450
  const storageValue = sessionStorage.getItem(storageKey);
@@ -436,6 +491,9 @@ function flattenRows(rows) {
436
491
  const childRows = rows.flatMap((r) => (r.children ? flattenRows(r.children) : []));
437
492
  return [...rows, ...childRows];
438
493
  }
494
+ function getColumnStorageKey(storageKey) {
495
+ return `expandedColumn_${storageKey}`;
496
+ }
439
497
  // Exported for testing purposes
440
498
  function deriveSortState(currentSortState, clickedKey, initialSortState) {
441
499
  var _a;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.243.0",
3
+ "version": "2.244.0",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",