@homebound/beam 2.303.0 → 2.304.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.
- package/dist/components/Table/GridTable.js +11 -6
- package/dist/components/Table/GridTableApi.d.ts +15 -13
- package/dist/components/Table/GridTableApi.js +1 -0
- package/dist/components/Table/components/EditColumnsButton.js +16 -15
- package/dist/components/Table/components/ExpandableHeader.js +1 -1
- package/dist/components/Table/components/Row.js +8 -8
- package/dist/components/Table/types.d.ts +7 -1
- package/dist/components/Table/utils/ColumnState.d.ts +24 -0
- package/dist/components/Table/utils/ColumnState.js +82 -0
- package/dist/components/Table/utils/ColumnStates.d.ts +29 -0
- package/dist/components/Table/utils/ColumnStates.js +79 -0
- package/dist/components/Table/utils/ColumnStorage.d.ts +13 -0
- package/dist/components/Table/utils/ColumnStorage.js +37 -0
- package/dist/components/Table/utils/RowStorage.js +3 -5
- package/dist/components/Table/utils/TableState.d.ts +9 -13
- package/dist/components/Table/utils/TableState.js +31 -127
- package/dist/components/Table/utils/columns.d.ts +1 -1
- package/dist/components/Table/utils/columns.js +9 -4
- package/dist/components/Table/utils/utils.d.ts +2 -0
- package/dist/components/Table/utils/utils.js +7 -1
- package/package.json +1 -1
|
@@ -99,17 +99,21 @@ function GridTable(props) {
|
|
|
99
99
|
api.init(persistCollapse, virtuosoRef, rows);
|
|
100
100
|
api.setActiveRowId(activeRowId);
|
|
101
101
|
api.setActiveCellId(activeCellId);
|
|
102
|
+
// Push the initial columns directly into tableState, b/c that is what
|
|
103
|
+
// makes the tests pass, but then further updates we'll do through useEffect
|
|
104
|
+
// to avoid "Cannot update component during render" errors.
|
|
105
|
+
api.tableState.setColumns(columnsWithIds, visibleColumnsStorageKey);
|
|
102
106
|
return api;
|
|
103
107
|
}, [props.api]);
|
|
104
108
|
const style = (0, TableStyles_1.resolveStyles)(maybeStyle);
|
|
105
109
|
const { tableState } = api;
|
|
106
110
|
tableState.setRows(rows);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
(0, react_1.useEffect)(() => {
|
|
112
|
+
tableState.setColumns(columnsWithIds, visibleColumnsStorageKey);
|
|
113
|
+
}, [tableState, columnsWithIds, visibleColumnsStorageKey]);
|
|
114
|
+
const columns = (0, hooks_1.useComputed)(() => {
|
|
115
|
+
return tableState.visibleColumns;
|
|
116
|
+
}, [tableState]);
|
|
113
117
|
// Initialize the sort state. This will only happen on the first render.
|
|
114
118
|
// Once the `TableState.sort` is defined, it will not re-initialize.
|
|
115
119
|
tableState.initSortState(props.sorting, columns);
|
|
@@ -128,6 +132,7 @@ function GridTable(props) {
|
|
|
128
132
|
// (or us) is resetting component state more than necessary, so we track render counts from
|
|
129
133
|
// here instead.
|
|
130
134
|
const { getCount } = (0, useRenderCount_1.useRenderCount)();
|
|
135
|
+
// Our column sizes use either `w` or `expandedWidth`, so see which columns are currently expanded
|
|
131
136
|
const expandedColumnIds = (0, hooks_1.useComputed)(() => tableState.expandedColumnIds, [tableState]);
|
|
132
137
|
const columnSizes = (0, useSetupColumnSizes_1.useSetupColumnSizes)(style, columns, resizeTarget !== null && resizeTarget !== void 0 ? resizeTarget : resizeRef, expandedColumnIds);
|
|
133
138
|
// Make a single copy of our current collapsed state, so we'll have a single observer.
|
|
@@ -22,28 +22,30 @@ export declare function useGridTableApi<R extends Kinded>(): GridTableApi<R>;
|
|
|
22
22
|
/** Provides an imperative API for an application page to interact with the table. */
|
|
23
23
|
export type GridTableApi<R extends Kinded> = {
|
|
24
24
|
/** Scrolls row `index` into view; only supported with `as=virtual` and after a `useEffect`. */
|
|
25
|
-
scrollToIndex
|
|
25
|
+
scrollToIndex(index: number): void;
|
|
26
26
|
/** Returns the ids of currently-selected rows. */
|
|
27
27
|
getSelectedRowIds(): string[];
|
|
28
28
|
getSelectedRowIds<K extends R["kind"]>(kind: K): string[];
|
|
29
29
|
/** Returns the currently-selected rows. */
|
|
30
30
|
getSelectedRows(): GridDataRow<R>[];
|
|
31
|
+
/** Returns the currently-selected rows of the given `kind`. */
|
|
31
32
|
getSelectedRows<K extends R["kind"]>(kind: K): GridDataRow<DiscriminateUnion<R, "kind", K>>[];
|
|
32
|
-
/**
|
|
33
|
+
/** Set selected state of a row by id. */
|
|
34
|
+
selectRow(id: string, selected?: boolean): void;
|
|
35
|
+
/** De-selects all selected rows. */
|
|
33
36
|
clearSelections(): void;
|
|
37
|
+
/** Whether a row is currently collapsed. */
|
|
38
|
+
isCollapsedRow(id: string): boolean;
|
|
39
|
+
/** Toggle collapse state of a row by id. */
|
|
40
|
+
toggleCollapsedRow(id: string): void;
|
|
34
41
|
/** Sets the internal state of 'activeRowId' */
|
|
35
|
-
setActiveRowId
|
|
42
|
+
setActiveRowId(id: string | undefined): void;
|
|
36
43
|
/** Sets the internal state of 'activeCellId' */
|
|
37
|
-
setActiveCellId
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
/** Toggle collapse state of a row by id */
|
|
43
|
-
toggleCollapsedRow: (id: string) => void;
|
|
44
|
-
isCollapsedRow: (id: string) => boolean;
|
|
45
|
-
setVisibleColumns: (ids: string[]) => void;
|
|
46
|
-
getVisibleColumnIds: () => string[];
|
|
44
|
+
setActiveCellId(id: string | undefined): void;
|
|
45
|
+
/** Deletes a row from the table, i.e. so it's not detected as kept. */
|
|
46
|
+
deleteRows(ids: string[]): void;
|
|
47
|
+
getVisibleColumnIds(): string[];
|
|
48
|
+
setVisibleColumns(ids: string[]): void;
|
|
47
49
|
};
|
|
48
50
|
export declare class GridTableApiImpl<R extends Kinded> implements GridTableApi<R> {
|
|
49
51
|
readonly tableState: TableState;
|
|
@@ -31,6 +31,7 @@ class GridTableApiImpl {
|
|
|
31
31
|
}
|
|
32
32
|
/** Called once by the GridTable when it takes ownership of this api instance. */
|
|
33
33
|
init(persistCollapse, virtuosoRef, rows) {
|
|
34
|
+
// Technically this drives both row-collapse and column-expanded
|
|
34
35
|
if (persistCollapse)
|
|
35
36
|
this.tableState.loadCollapse(persistCollapse);
|
|
36
37
|
this.virtuosoRef = virtuosoRef;
|
|
@@ -24,22 +24,23 @@ function EditColumnsButton(props) {
|
|
|
24
24
|
: (0, OverlayTrigger_1.isIconButton)(trigger)
|
|
25
25
|
? trigger.icon
|
|
26
26
|
: trigger.name);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}, [columns]);
|
|
27
|
+
const options = (0, react_1.useMemo)(() => columns
|
|
28
|
+
// Only include options that can be hidden
|
|
29
|
+
.filter((column) => column.canHide)
|
|
30
|
+
// And have the `name` property defined
|
|
31
|
+
.filter((column) => {
|
|
32
|
+
if (!column.name || column.name.length === 0 || !column.id || column.id.length === 0) {
|
|
33
|
+
console.warn("Column is missing 'name' and/or 'id' property required by the Edit Columns button", column);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
})
|
|
38
|
+
.map((column) => ({ label: column.name, value: column.id })), [columns]);
|
|
40
39
|
const selectedValues = (0, hooks_1.useComputed)(() => api.getVisibleColumnIds(), [api]);
|
|
41
|
-
const setSelectedValues = (0, react_1.useCallback)((
|
|
42
|
-
|
|
40
|
+
const setSelectedValues = (0, react_1.useCallback)((ids) => {
|
|
41
|
+
// Doesn't `options` already filter us to non-hidden/valid-id columns? I.e. could we just do:
|
|
42
|
+
// api.setVisibleColumns(ids);
|
|
43
|
+
api.setVisibleColumns(columns.filter((column) => (column.canHide ? ids.includes(column.id) : true)).map((c) => c.id));
|
|
43
44
|
}, [columns, api]);
|
|
44
45
|
return ((0, jsx_runtime_1.jsx)(OverlayTrigger_1.OverlayTrigger, { ...props, menuTriggerProps: menuTriggerProps, state: state, buttonRef: buttonRef, ...tid, children: (0, jsx_runtime_1.jsxs)("div", { css: {
|
|
45
46
|
...Css_1.Css.bgWhite.py5.px3.maxwPx(380).bshBasic.$,
|
|
@@ -22,7 +22,7 @@ function ExpandableHeader(props) {
|
|
|
22
22
|
return ((0, jsx_runtime_1.jsxs)("button", { ...hoverProps, css: Css_1.Css.df.xsMd.aic.jcsb.gap2.px1.hPx(32).mxPx(-8).w("calc(100% + 16px)").br4.lightBlue700.if(isHovered).bgGray100.$, onClick: async () => {
|
|
23
23
|
if ((0, utils_2.isFunction)(column.expandColumns)) {
|
|
24
24
|
setIsLoading(true);
|
|
25
|
-
await tableState.loadExpandedColumns(column);
|
|
25
|
+
await tableState.loadExpandedColumns(column.id);
|
|
26
26
|
setIsLoading(false);
|
|
27
27
|
}
|
|
28
28
|
// manually calling this as loadExpandedColumns does not toggle
|
|
@@ -78,11 +78,11 @@ function RowImpl(props) {
|
|
|
78
78
|
let minStickyLeftOffset = 0;
|
|
79
79
|
let expandColumnHidden = false;
|
|
80
80
|
return ((0, jsx_runtime_1.jsx)(RowTag, { css: rowCss, ...others, "data-gridrow": true, ...getCount(row.id), children: isKeptGroupRow ? ((0, jsx_runtime_1.jsx)(KeptGroupRow_1.KeptGroupRow, { as: as, style: style, columnSizes: columnSizes, row: row, colSpan: columns.length })) : (columns.map((column, columnIndex) => {
|
|
81
|
-
var _a, _b, _c, _d
|
|
81
|
+
var _a, _b, _c, _d;
|
|
82
82
|
// If the expandable column was hidden, then we need to look at the previous column to format the `expandHeader` and 'header' kinds correctly.
|
|
83
83
|
const maybeExpandedColumn = expandColumnHidden ? columns[columnIndex - 1] : column;
|
|
84
84
|
// Figure out if this column should be considered 'expanded' or not. If the column is hidden on expand, then we need to look at the previous column to see if it's expanded.
|
|
85
|
-
const isExpanded = tableState.
|
|
85
|
+
const isExpanded = tableState.isExpandedColumn(maybeExpandedColumn.id);
|
|
86
86
|
// If the column is hidden on expand, we don't want to render it. We'll flag that it was hidden, so on the next column we can render this column's "expandHeader" property.
|
|
87
87
|
if (column.hideOnExpand && isExpanded) {
|
|
88
88
|
expandColumnHidden = true;
|
|
@@ -90,9 +90,9 @@ function RowImpl(props) {
|
|
|
90
90
|
}
|
|
91
91
|
// Need to keep track of the expanded columns so we can add borders as expected for the header rows
|
|
92
92
|
const numExpandedColumns = isExpanded
|
|
93
|
-
?
|
|
93
|
+
? tableState.numberOfExpandedChildren(maybeExpandedColumn.id)
|
|
94
94
|
? // Subtract 1 if the column is hidden on expand, since we're not rendering it.
|
|
95
|
-
tableState.
|
|
95
|
+
tableState.numberOfExpandedChildren(maybeExpandedColumn.id) - (maybeExpandedColumn.hideOnExpand ? 1 : 0)
|
|
96
96
|
: 0
|
|
97
97
|
: 0;
|
|
98
98
|
// If we're rendering the Expandable Header row, then we might need to render the previous column's `expandHeader` property in the case where the column is hidden on expand.
|
|
@@ -145,7 +145,7 @@ function RowImpl(props) {
|
|
|
145
145
|
column.expandedWidth !== undefined;
|
|
146
146
|
const content = (0, utils_1.toContent)(maybeContent, isHeader, canSortColumn, sortOn === "client", style, as, alignment, column, isExpandableHeader, isExpandable, minStickyLeftOffset, isKeptSelectedRow);
|
|
147
147
|
(0, sortRows_1.ensureClientSideSortValueIsSortable)(sortOn, isHeader || isTotals || isExpandableHeader, column, columnIndex, maybeContent);
|
|
148
|
-
const maybeSticky = (
|
|
148
|
+
const maybeSticky = (_a = (((0, utils_1.isGridCellContent)(maybeContent) && maybeContent.sticky) || column.sticky)) !== null && _a !== void 0 ? _a : undefined;
|
|
149
149
|
const maybeStickyColumnStyles = maybeSticky && columnSizes
|
|
150
150
|
? {
|
|
151
151
|
...Css_1.Css.sticky.z(utils_1.zIndices.stickyColumns).bgWhite.$,
|
|
@@ -199,13 +199,13 @@ function RowImpl(props) {
|
|
|
199
199
|
currentExpandedColumnCount === 0 &&
|
|
200
200
|
Css_1.Css.boxShadow(`inset -1px -1px 0 ${Css_1.Palette.Gray200}`).$),
|
|
201
201
|
// Or level-specific styling
|
|
202
|
-
...(!isHeader && !isTotals && !isExpandableHeader && !!style.levels && ((
|
|
202
|
+
...(!isHeader && !isTotals && !isExpandableHeader && !!style.levels && ((_b = style.levels[level]) === null || _b === void 0 ? void 0 : _b.cellCss)),
|
|
203
203
|
// Level specific styling for the first content column
|
|
204
|
-
...(applyFirstContentColumnStyles && !!style.levels && ((
|
|
204
|
+
...(applyFirstContentColumnStyles && !!style.levels && ((_c = style.levels[level]) === null || _c === void 0 ? void 0 : _c.firstContentColumn)),
|
|
205
205
|
// The specific cell's css (if any from GridCellContent)
|
|
206
206
|
...rowStyleCellCss,
|
|
207
207
|
// Apply active row styling for non-nested card styles.
|
|
208
|
-
...(isActive ? Css_1.Css.bgColor((
|
|
208
|
+
...(isActive ? Css_1.Css.bgColor((_d = style.activeBgColor) !== null && _d !== void 0 ? _d : Css_1.Palette.LightBlue50).$ : {}),
|
|
209
209
|
// Add any cell specific style overrides
|
|
210
210
|
...((0, utils_1.isGridCellContent)(maybeContent) && maybeContent.typeScale ? Css_1.Css[maybeContent.typeScale].$ : {}),
|
|
211
211
|
// And any cell specific css
|
|
@@ -85,6 +85,12 @@ export type GridColumn<R extends Kinded> = {
|
|
|
85
85
|
/** Determines whether this column should be hidden when expanded (only the 'expandColumns' would show) */
|
|
86
86
|
hideOnExpand?: boolean;
|
|
87
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Adds an `id` to `GridColumn`, for use in storage/APIs.
|
|
90
|
+
*
|
|
91
|
+
* Ideally we'd require this on `GridColumn` itself, but that would be
|
|
92
|
+
* a large breaking change for a lot of tables that don't need column ids.
|
|
93
|
+
*/
|
|
88
94
|
export type GridColumnWithId<R extends Kinded> = GridColumn<R> & {
|
|
89
95
|
id: string;
|
|
90
96
|
expandColumns?: GridColumnWithId<R>[] | (() => Promise<GridColumn<R>[]>);
|
|
@@ -102,6 +108,6 @@ export type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
|
|
|
102
108
|
export type InfiniteScroll = {
|
|
103
109
|
/** will be called when the user scrolls to the end of the list with the last item index as an argument. */
|
|
104
110
|
onEndReached: (index: number) => void;
|
|
105
|
-
/** The number of pixels from the bottom of the list to eagerly trigger `onEndReached`. The default is
|
|
111
|
+
/** The number of pixels from the bottom of the list to eagerly trigger `onEndReached`. The default is 500px. */
|
|
106
112
|
endOffsetPx?: number;
|
|
107
113
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { GridColumnWithId } from "../../..";
|
|
2
|
+
import { ColumnStates } from "./ColumnStates";
|
|
3
|
+
import { ColumnStorage } from "./ColumnStorage";
|
|
4
|
+
/**
|
|
5
|
+
* A reactive/observable wrapper around each GridColumn.
|
|
6
|
+
*
|
|
7
|
+
* This is primarily for tracking visible/expanded columns for tables
|
|
8
|
+
* that use the expandable columns feature.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ColumnState {
|
|
11
|
+
private states;
|
|
12
|
+
column: GridColumnWithId<any>;
|
|
13
|
+
children: ColumnState[] | undefined;
|
|
14
|
+
private visible;
|
|
15
|
+
private expanded;
|
|
16
|
+
constructor(states: ColumnStates, storage: ColumnStorage, column: GridColumnWithId<any>);
|
|
17
|
+
setVisible(visible: boolean): void;
|
|
18
|
+
get isExpanded(): boolean;
|
|
19
|
+
toggleExpanded(): void;
|
|
20
|
+
/** Calls the `column.expandColumns` function, if set, and adds the resulting columns. */
|
|
21
|
+
doExpand(force?: boolean): Promise<void>;
|
|
22
|
+
/** Returns this column, if visible, and its children, if expanded. */
|
|
23
|
+
get maybeSelfAndChildren(): ColumnState[];
|
|
24
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ColumnState = void 0;
|
|
4
|
+
const mobx_1 = require("mobx");
|
|
5
|
+
const src_1 = require("../../..");
|
|
6
|
+
const index_1 = require("../../../utils/index");
|
|
7
|
+
/**
|
|
8
|
+
* A reactive/observable wrapper around each GridColumn.
|
|
9
|
+
*
|
|
10
|
+
* This is primarily for tracking visible/expanded columns for tables
|
|
11
|
+
* that use the expandable columns feature.
|
|
12
|
+
*/
|
|
13
|
+
class ColumnState {
|
|
14
|
+
constructor(states, storage, column) {
|
|
15
|
+
var _a, _b, _c;
|
|
16
|
+
this.states = states;
|
|
17
|
+
this.children = undefined;
|
|
18
|
+
this.visible = true;
|
|
19
|
+
this.expanded = false;
|
|
20
|
+
this.column = column;
|
|
21
|
+
// If the user sets `canHide: true`, we default to hidden unless they set `initVisible: true`
|
|
22
|
+
this.visible = (_a = storage.wasVisible(column.id)) !== null && _a !== void 0 ? _a : (column.canHide ? (_b = column.initVisible) !== null && _b !== void 0 ? _b : false : true);
|
|
23
|
+
if (this.visible && ((_c = storage.wasExpanded(column.id)) !== null && _c !== void 0 ? _c : column.initExpanded)) {
|
|
24
|
+
this.expanded = true;
|
|
25
|
+
this.doExpand();
|
|
26
|
+
}
|
|
27
|
+
(0, mobx_1.makeAutoObservable)(this, { column: mobx_1.observable.ref });
|
|
28
|
+
}
|
|
29
|
+
setVisible(visible) {
|
|
30
|
+
const wasVisible = this.visible;
|
|
31
|
+
this.visible = visible;
|
|
32
|
+
// If an expandable header is becoming visible for the 1st time, expand it
|
|
33
|
+
if (!wasVisible && visible && this.column.initExpanded && this.children === undefined) {
|
|
34
|
+
this.expanded = true;
|
|
35
|
+
this.doExpand();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
get isExpanded() {
|
|
39
|
+
return this.expanded;
|
|
40
|
+
}
|
|
41
|
+
toggleExpanded() {
|
|
42
|
+
const wasExpanded = this.expanded;
|
|
43
|
+
this.expanded = !this.expanded;
|
|
44
|
+
// The first time we expand, fetch our children. Note that ExpandableHeader
|
|
45
|
+
// technically pre-loads our children, so it can show a spinner while loading,
|
|
46
|
+
// and only after loading is complete, tell our column to expand.
|
|
47
|
+
if (!wasExpanded)
|
|
48
|
+
this.doExpand();
|
|
49
|
+
}
|
|
50
|
+
/** Calls the `column.expandColumns` function, if set, and adds the resulting columns. */
|
|
51
|
+
async doExpand(force = false) {
|
|
52
|
+
const { expandColumns } = this.column;
|
|
53
|
+
// If we've already got the children, don't re-expand unless forced (i.e. props.columns changed)
|
|
54
|
+
if (this.children !== undefined && !force)
|
|
55
|
+
return;
|
|
56
|
+
if ((0, index_1.isFunction)(expandColumns)) {
|
|
57
|
+
const ecs = await expandColumns();
|
|
58
|
+
this.children = (0, src_1.assignDefaultColumnIds)(ecs).map((ec) => this.states.addColumn(ec));
|
|
59
|
+
}
|
|
60
|
+
else if (expandColumns) {
|
|
61
|
+
this.children = expandColumns.map((ec) => this.states.addColumn(ec));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Returns this column, if visible, and its children, if expanded. */
|
|
65
|
+
get maybeSelfAndChildren() {
|
|
66
|
+
if (!this.visible) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
else if (this.expanded && this.children) {
|
|
70
|
+
// Maybe do the `hideOnExpand` thing here? Seems cute, but the Row rendering still
|
|
71
|
+
// needs to do the "look back to the prior column for the expandableHeader cell" logic.
|
|
72
|
+
// if (this.column.hideOnExpand) {
|
|
73
|
+
// return this.children.flatMap((c) => c.selfAndMaybeChildren);
|
|
74
|
+
// }
|
|
75
|
+
return [this, ...this.children.flatMap((c) => c.maybeSelfAndChildren)];
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return [this];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.ColumnState = ColumnState;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { GridColumnWithId } from "../../..";
|
|
2
|
+
import { ColumnState } from "./ColumnState";
|
|
3
|
+
/** A reactive/observable wrapper around our columns. */
|
|
4
|
+
export declare class ColumnStates {
|
|
5
|
+
private columns;
|
|
6
|
+
private map;
|
|
7
|
+
private storage;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Updates our internal columns states when `props.columns` changes.
|
|
11
|
+
*
|
|
12
|
+
* We handle sessionStorage here b/c we allow the user to either provide their own
|
|
13
|
+
* storage key, or calc the storage key based on the currently-visible columns.
|
|
14
|
+
* So like you expand a column, and new columns show up, but we'll remember they
|
|
15
|
+
* were hidden last time you looked at this specific expansion of columns.
|
|
16
|
+
*/
|
|
17
|
+
setColumns(columns: GridColumnWithId<any>[], visibleColumnsStorageKey: string | undefined): void;
|
|
18
|
+
/** Adds a column to our state, i.e. maybe a dynamically loaded column. */
|
|
19
|
+
addColumn(column: GridColumnWithId<any>): ColumnState;
|
|
20
|
+
/** Returns the `ColumnState` for the given `id`. */
|
|
21
|
+
get(id: string): ColumnState;
|
|
22
|
+
/** Returns all currently-expanded columns. */
|
|
23
|
+
get expandedColumns(): ColumnState[];
|
|
24
|
+
/** Returns a flat list of all visible columns. */
|
|
25
|
+
get allVisibleColumns(): ColumnState[];
|
|
26
|
+
setVisibleColumns(ids: string[]): void;
|
|
27
|
+
loadExpanded(storageKey: string): void;
|
|
28
|
+
loadVisible(storageKey: string): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ColumnStates = void 0;
|
|
4
|
+
const change_case_1 = require("change-case");
|
|
5
|
+
const mobx_1 = require("mobx");
|
|
6
|
+
const ColumnState_1 = require("./ColumnState");
|
|
7
|
+
const ColumnStorage_1 = require("./ColumnStorage");
|
|
8
|
+
/** A reactive/observable wrapper around our columns. */
|
|
9
|
+
class ColumnStates {
|
|
10
|
+
constructor() {
|
|
11
|
+
// The top-level list of columns
|
|
12
|
+
this.columns = [];
|
|
13
|
+
this.map = new Map();
|
|
14
|
+
this.storage = new ColumnStorage_1.ColumnStorage(this);
|
|
15
|
+
(0, mobx_1.makeAutoObservable)(this);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Updates our internal columns states when `props.columns` changes.
|
|
19
|
+
*
|
|
20
|
+
* We handle sessionStorage here b/c we allow the user to either provide their own
|
|
21
|
+
* storage key, or calc the storage key based on the currently-visible columns.
|
|
22
|
+
* So like you expand a column, and new columns show up, but we'll remember they
|
|
23
|
+
* were hidden last time you looked at this specific expansion of columns.
|
|
24
|
+
*/
|
|
25
|
+
setColumns(columns, visibleColumnsStorageKey) {
|
|
26
|
+
if (columns.some((c) => c.canHide)) {
|
|
27
|
+
// We optionally auto-calc visible columns based on the currently-_potentially_-visible columns
|
|
28
|
+
visibleColumnsStorageKey !== null && visibleColumnsStorageKey !== void 0 ? visibleColumnsStorageKey : (visibleColumnsStorageKey = (0, change_case_1.camelCase)(columns.map((c) => c.id).join()));
|
|
29
|
+
this.loadVisible(visibleColumnsStorageKey);
|
|
30
|
+
}
|
|
31
|
+
this.columns = columns.map((c) => this.addColumn(c));
|
|
32
|
+
// After the very first non-zero `setColumns`, we disconnect from sessionStorage
|
|
33
|
+
if (columns.length > 0)
|
|
34
|
+
this.storage.done();
|
|
35
|
+
}
|
|
36
|
+
/** Adds a column to our state, i.e. maybe a dynamically loaded column. */
|
|
37
|
+
addColumn(column) {
|
|
38
|
+
const existing = this.map.get(column.id);
|
|
39
|
+
if (!existing) {
|
|
40
|
+
const cs = new ColumnState_1.ColumnState(this, this.storage, column);
|
|
41
|
+
this.map.set(column.id, cs);
|
|
42
|
+
return cs;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
existing.column = column;
|
|
46
|
+
// Any time a column is re-added (i.e. props.columns changed), re-expand it
|
|
47
|
+
if (existing.isExpanded)
|
|
48
|
+
existing.doExpand(true);
|
|
49
|
+
return existing;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Returns the `ColumnState` for the given `id`. */
|
|
53
|
+
get(id) {
|
|
54
|
+
const cs = this.map.get(id);
|
|
55
|
+
if (!cs)
|
|
56
|
+
throw new Error(`No ColumnState for ${id}`);
|
|
57
|
+
return cs;
|
|
58
|
+
}
|
|
59
|
+
/** Returns all currently-expanded columns. */
|
|
60
|
+
get expandedColumns() {
|
|
61
|
+
return this.columns.filter((cs) => cs.isExpanded);
|
|
62
|
+
}
|
|
63
|
+
/** Returns a flat list of all visible columns. */
|
|
64
|
+
get allVisibleColumns() {
|
|
65
|
+
return this.columns.flatMap((cs) => cs.maybeSelfAndChildren);
|
|
66
|
+
}
|
|
67
|
+
setVisibleColumns(ids) {
|
|
68
|
+
for (const cs of this.map.values()) {
|
|
69
|
+
cs.setVisible(ids.includes(cs.column.id));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
loadExpanded(storageKey) {
|
|
73
|
+
this.storage.loadExpanded(storageKey);
|
|
74
|
+
}
|
|
75
|
+
loadVisible(storageKey) {
|
|
76
|
+
this.storage.loadVisible(storageKey);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.ColumnStates = ColumnStates;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ColumnStates } from "./ColumnStates";
|
|
2
|
+
/** Loads/saves the column state from sessionStorage. */
|
|
3
|
+
export declare class ColumnStorage {
|
|
4
|
+
private states;
|
|
5
|
+
private expandedIds;
|
|
6
|
+
private visibleIds;
|
|
7
|
+
constructor(states: ColumnStates);
|
|
8
|
+
loadExpanded(persistCollapse: string): void;
|
|
9
|
+
loadVisible(storageKey: string): void;
|
|
10
|
+
wasExpanded(id: string): boolean | undefined;
|
|
11
|
+
wasVisible(id: string): boolean | undefined;
|
|
12
|
+
done(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ColumnStorage = void 0;
|
|
4
|
+
const mobx_1 = require("mobx");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
/** Loads/saves the column state from sessionStorage. */
|
|
7
|
+
class ColumnStorage {
|
|
8
|
+
constructor(states) {
|
|
9
|
+
this.states = states;
|
|
10
|
+
}
|
|
11
|
+
loadExpanded(persistCollapse) {
|
|
12
|
+
const key = `expandedColumn_${persistCollapse}`;
|
|
13
|
+
this.expandedIds = (0, utils_1.loadArrayOrUndefined)(key);
|
|
14
|
+
(0, mobx_1.reaction)(() => this.states.expandedColumns.map((cs) => cs.column.id), (columnIds) => sessionStorage.setItem(key, JSON.stringify(columnIds)));
|
|
15
|
+
}
|
|
16
|
+
loadVisible(storageKey) {
|
|
17
|
+
this.visibleIds = (0, utils_1.loadArrayOrUndefined)(storageKey);
|
|
18
|
+
// Unlike the others, where we only store the value on change, we immediately
|
|
19
|
+
// store this value (but I'm not sure why...), hence using `autorun`.
|
|
20
|
+
(0, mobx_1.autorun)(() => {
|
|
21
|
+
const columnIds = this.states.allVisibleColumns.map((cs) => cs.column.id);
|
|
22
|
+
sessionStorage.setItem(storageKey, JSON.stringify(columnIds));
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
wasExpanded(id) {
|
|
26
|
+
var _a;
|
|
27
|
+
return (_a = this.expandedIds) === null || _a === void 0 ? void 0 : _a.includes(id);
|
|
28
|
+
}
|
|
29
|
+
wasVisible(id) {
|
|
30
|
+
var _a;
|
|
31
|
+
return (_a = this.visibleIds) === null || _a === void 0 ? void 0 : _a.includes(id);
|
|
32
|
+
}
|
|
33
|
+
done() {
|
|
34
|
+
this.expandedIds = undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.ColumnStorage = ColumnStorage;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RowStorage = void 0;
|
|
4
4
|
const mobx_1 = require("mobx");
|
|
5
|
+
const src_1 = require("../../..");
|
|
5
6
|
/**
|
|
6
7
|
* Manages loading/saving our currently-collapsed rows to session storage.
|
|
7
8
|
*
|
|
@@ -19,12 +20,9 @@ class RowStorage {
|
|
|
19
20
|
}
|
|
20
21
|
load(persistCollapse) {
|
|
21
22
|
// Load what our previously collapsed rows were
|
|
22
|
-
|
|
23
|
-
if (ids) {
|
|
24
|
-
this.historicalIds = JSON.parse(ids);
|
|
25
|
-
}
|
|
23
|
+
this.historicalIds = (0, src_1.loadArrayOrUndefined)(persistCollapse);
|
|
26
24
|
// And store new collapsed rows going forward
|
|
27
|
-
(0, mobx_1.reaction)(() =>
|
|
25
|
+
(0, mobx_1.reaction)(() => this.states.collapsedRows.map((rs) => rs.row.id), (rowIds) => sessionStorage.setItem(persistCollapse, JSON.stringify(rowIds)));
|
|
28
26
|
}
|
|
29
27
|
/** Once the first real-data load is done, we ignore historical ids so that we prefer any new data's `initCollapsed`. */
|
|
30
28
|
done() {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ObservableSet } from "mobx";
|
|
2
1
|
import React from "react";
|
|
3
2
|
import { GridDataRow } from "../components/Row";
|
|
4
3
|
import { GridSortConfig } from "../GridTable";
|
|
@@ -22,18 +21,15 @@ export type SelectedState = "checked" | "unchecked" | "partial";
|
|
|
22
21
|
export declare class TableState {
|
|
23
22
|
private persistCollapse;
|
|
24
23
|
private rows;
|
|
24
|
+
columns: GridColumnWithId<any>[];
|
|
25
25
|
private readonly rowStates;
|
|
26
|
+
private readonly columnStates;
|
|
26
27
|
activeRowId: string | undefined;
|
|
27
28
|
activeCellId: string | undefined;
|
|
28
29
|
sortConfig: GridSortConfig | undefined;
|
|
29
30
|
sort: SortState;
|
|
30
31
|
private initialSortState;
|
|
31
32
|
private onSort;
|
|
32
|
-
columns: GridColumnWithId<any>[];
|
|
33
|
-
private expandedColumns;
|
|
34
|
-
visibleColumns: ObservableSet<string>;
|
|
35
|
-
private visibleColumnsStorageKey;
|
|
36
|
-
private loadedColumns;
|
|
37
33
|
/**
|
|
38
34
|
* Creates the `RowState` for a given `GridTable`.
|
|
39
35
|
*/
|
|
@@ -44,16 +40,16 @@ export declare class TableState {
|
|
|
44
40
|
get sortState(): SortState | undefined;
|
|
45
41
|
setRows(rows: GridDataRow<any>[]): void;
|
|
46
42
|
setColumns(columns: GridColumnWithId<any>[], visibleColumnsStorageKey: string | undefined): void;
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
updateExpandedColumns(newColumns: GridColumnWithId<any>[]): void;
|
|
51
|
-
loadExpandedColumns(column: GridColumnWithId<any>): Promise<void>;
|
|
52
|
-
getExpandedColumns(column: GridColumnWithId<any>): GridColumnWithId<any>[];
|
|
53
|
-
setVisibleColumns(ids: string[]): void;
|
|
43
|
+
/** Returns visible columns, i.e. those that are visible + any expanded children. */
|
|
44
|
+
get visibleColumns(): GridColumnWithId<any>[];
|
|
45
|
+
/** Implements GridTableApi.visibleColumnIds. */
|
|
54
46
|
get visibleColumnIds(): string[];
|
|
47
|
+
setVisibleColumns(ids: string[]): void;
|
|
55
48
|
get expandedColumnIds(): string[];
|
|
49
|
+
isExpandedColumn(columnId: string): boolean;
|
|
56
50
|
toggleExpandedColumn(columnId: string): void;
|
|
51
|
+
numberOfExpandedChildren(columnId: string): number;
|
|
52
|
+
loadExpandedColumns(columnId: string): Promise<void>;
|
|
57
53
|
/** Called when GridTable has re-calced the rows that pass the client-side filter, or all rows. */
|
|
58
54
|
setMatchedRows(rowIds: string[]): void;
|
|
59
55
|
/** Returns selected data rows (non-header, non-totals, etc.), ignoring rows that have `row.selectable !== false`. */
|
|
@@ -4,13 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.deriveSortState = exports.TableStateContext = exports.TableState = void 0;
|
|
7
|
-
const change_case_1 = require("change-case");
|
|
8
7
|
const mobx_1 = require("mobx");
|
|
9
8
|
const react_1 = __importDefault(require("react"));
|
|
9
|
+
const ColumnStates_1 = require("./ColumnStates");
|
|
10
10
|
const RowStates_1 = require("./RowStates");
|
|
11
11
|
const utils_1 = require("./utils");
|
|
12
|
-
const utils_2 = require("../../../utils");
|
|
13
|
-
const columns_1 = require("./columns");
|
|
14
12
|
/**
|
|
15
13
|
* Stores the collapsed & selected state of rows.
|
|
16
14
|
*
|
|
@@ -33,7 +31,10 @@ class TableState {
|
|
|
33
31
|
constructor() {
|
|
34
32
|
// The current list of rows, basically a useRef.current. Only shallow reactive.
|
|
35
33
|
this.rows = [];
|
|
34
|
+
// The current list of columns, basically a useRef.current. Only ref reactive.
|
|
35
|
+
this.columns = [];
|
|
36
36
|
this.rowStates = new RowStates_1.RowStates();
|
|
37
|
+
this.columnStates = new ColumnStates_1.ColumnStates();
|
|
37
38
|
// Keeps track of the 'active' row, formatted `${row.kind}_${row.id}`
|
|
38
39
|
this.activeRowId = undefined;
|
|
39
40
|
// Keeps track of the 'active' cell, formatted `${row.kind}_${row.id}_${column.name}`
|
|
@@ -41,15 +42,6 @@ class TableState {
|
|
|
41
42
|
// Tracks the active sort column(s), so GridTable or SortHeaders can reactively
|
|
42
43
|
// re-render (for GridTable, only if client-side sorting)
|
|
43
44
|
this.sort = {};
|
|
44
|
-
// Non-reactive list of our columns
|
|
45
|
-
this.columns = [];
|
|
46
|
-
// An observable set of column ids to keep track of which columns are currently expanded
|
|
47
|
-
this.expandedColumns = new mobx_1.ObservableSet();
|
|
48
|
-
// An observable set of column ids to keep track of which columns are visible
|
|
49
|
-
this.visibleColumns = new mobx_1.ObservableSet();
|
|
50
|
-
this.visibleColumnsStorageKey = "";
|
|
51
|
-
// Cache for already loaded expandable columns
|
|
52
|
-
this.loadedColumns = new Map();
|
|
53
45
|
// Make ourselves an observable so that mobx will do caching of .collapseIds so
|
|
54
46
|
// that it'll be a stable identity for GridTable to useMemo against.
|
|
55
47
|
(0, mobx_1.makeAutoObservable)(this, {
|
|
@@ -59,8 +51,7 @@ class TableState {
|
|
|
59
51
|
// updated _contents_ of a given row, even if our other selected/matched row states don't change.
|
|
60
52
|
// (as any b/c rows is private, so the mapped type doesn't see it)
|
|
61
53
|
rows: mobx_1.observable.shallow,
|
|
62
|
-
|
|
63
|
-
columns: false,
|
|
54
|
+
columns: mobx_1.observable.ref,
|
|
64
55
|
});
|
|
65
56
|
// If the kept rows went from empty to not empty, then introduce the SELECTED_GROUP row as collapsed
|
|
66
57
|
(0, mobx_1.reaction)(() => [...this.keptRows.values()], (curr, prev) => {
|
|
@@ -72,6 +63,7 @@ class TableState {
|
|
|
72
63
|
loadCollapse(persistCollapse) {
|
|
73
64
|
this.persistCollapse = persistCollapse;
|
|
74
65
|
this.rowStates.storage.load(persistCollapse);
|
|
66
|
+
this.columnStates.loadExpanded(persistCollapse);
|
|
75
67
|
}
|
|
76
68
|
initSortState(sortConfig, columns) {
|
|
77
69
|
var _a, _b;
|
|
@@ -127,118 +119,48 @@ class TableState {
|
|
|
127
119
|
}
|
|
128
120
|
// Updates the list of rows and regenerates the collapsedRows property if needed.
|
|
129
121
|
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.
|
|
130
126
|
if (rows !== this.rows) {
|
|
131
127
|
this.rowStates.setRows(rows);
|
|
132
128
|
this.rows = rows;
|
|
133
129
|
}
|
|
134
130
|
}
|
|
135
131
|
setColumns(columns, visibleColumnsStorageKey) {
|
|
136
|
-
const isInitial = !this.columns || this.columns.length === 0;
|
|
137
132
|
if (columns !== this.columns) {
|
|
138
|
-
this.
|
|
139
|
-
this.visibleColumns.replace(readOrSetLocalVisibleColumnState(columns, this.visibleColumnsStorageKey));
|
|
140
|
-
// Figure out which columns need to be expanded when rendering a new set of columns
|
|
141
|
-
const localStorageColumns = this.persistCollapse ? readExpandedColumnsStorage(this.persistCollapse) : [];
|
|
142
|
-
// On initial render the columns we start with is whatever is in local storage.
|
|
143
|
-
// On subsequent renders we want to keep the columns that were previously expanded.
|
|
144
|
-
const columnIdsToExpand = isInitial ? localStorageColumns : this.expandedColumnIds;
|
|
145
|
-
// Create a list of all existing column ids. (We ignore the `initExpanded` property for existing columns)
|
|
146
|
-
const existingColumnIds = this.columns.map((c) => c.id);
|
|
147
|
-
// Add any columns to our array that are new columns that should be initially expanded.
|
|
148
|
-
columnIdsToExpand.push(...columns.filter((c) => !existingColumnIds.includes(c.id) && c.initExpanded).map((c) => c.id));
|
|
149
|
-
// Clear the cache to force to re-fetch the expanded columns.
|
|
150
|
-
this.loadedColumns.clear();
|
|
151
|
-
// Send the new array of columns along to be parsed and expanded.
|
|
152
|
-
this.parseAndUpdateExpandedColumns(columns.filter((c) => columnIdsToExpand.includes(c.id)));
|
|
133
|
+
this.columnStates.setColumns(columns, visibleColumnsStorageKey);
|
|
153
134
|
this.columns = columns;
|
|
154
135
|
}
|
|
155
136
|
}
|
|
156
|
-
/**
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const [localColumnsToExpand, asyncColumnsToExpand] = columnsToExpand.reduce((acc, c) => {
|
|
160
|
-
if ((0, utils_2.isFunction)(c.expandColumns)) {
|
|
161
|
-
return [acc[0], acc[1].concat(c)];
|
|
162
|
-
}
|
|
163
|
-
return [acc[0].concat(c), acc[1]];
|
|
164
|
-
}, [[], []]);
|
|
165
|
-
// Handle all async expanding columns using a Promise.all.
|
|
166
|
-
// This will allow the table to render immediately, then cause a rerender with the new columns
|
|
167
|
-
if (asyncColumnsToExpand.length > 0) {
|
|
168
|
-
// Note: Not using a Promise.all because there seems to be a bug in Apollo with applying TypePolicies when using Promise.all.
|
|
169
|
-
// TODO: Update comment with Apollo issue link.
|
|
170
|
-
// Promise.all(asyncColumnsToExpand.map(async (c) => await this.loadExpandedColumns(c))).then(() =>
|
|
171
|
-
// this.updateExpandedColumns(asyncColumnsToExpand),
|
|
172
|
-
// );
|
|
173
|
-
// Instead, doing each async request in sequence for now.
|
|
174
|
-
for await (const column of asyncColumnsToExpand) {
|
|
175
|
-
await this.loadExpandedColumns(column);
|
|
176
|
-
}
|
|
177
|
-
this.updateExpandedColumns(asyncColumnsToExpand);
|
|
178
|
-
}
|
|
179
|
-
// For local columns, we skip the Promise in order to have the correct state on the initial load.
|
|
180
|
-
if (localColumnsToExpand.length > 0) {
|
|
181
|
-
this.updateExpandedColumns(localColumnsToExpand);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
/** Updates the state of which columns are expanded */
|
|
185
|
-
updateExpandedColumns(newColumns) {
|
|
186
|
-
const newColumnIds = newColumns.map((c) => c.id);
|
|
187
|
-
// If there is a difference between list of current expanded columns vs list we just created, then replace
|
|
188
|
-
const isDifferent = newColumnIds.length !== this.expandedColumnIds.length ||
|
|
189
|
-
!this.expandedColumnIds.every((c) => newColumnIds.includes(c));
|
|
190
|
-
if (isDifferent) {
|
|
191
|
-
// Note: `this.expandedColumns` is a Set, so it will take care of dedupe-ing.
|
|
192
|
-
this.expandedColumns.replace([...this.expandedColumnIds, ...newColumnIds]);
|
|
193
|
-
// Update session storage if necessary.
|
|
194
|
-
if (this.persistCollapse) {
|
|
195
|
-
sessionStorage.setItem(getColumnStorageKey(this.persistCollapse), JSON.stringify([...this.expandedColumns]));
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
// load and trigger column to be expanded
|
|
200
|
-
async loadExpandedColumns(column) {
|
|
201
|
-
// if we don't have anything in our cache and our expanded columns are a function
|
|
202
|
-
if (!this.loadedColumns.has(column.id) && (0, utils_2.isFunction)(column.expandColumns)) {
|
|
203
|
-
// set our result to the function call of expandColumns
|
|
204
|
-
const result = await column.expandColumns();
|
|
205
|
-
// once we have the loaded columns, add result to local cache
|
|
206
|
-
this.loadedColumns.set(column.id, (0, columns_1.assignDefaultColumnIds)(result));
|
|
207
|
-
}
|
|
137
|
+
/** Returns visible columns, i.e. those that are visible + any expanded children. */
|
|
138
|
+
get visibleColumns() {
|
|
139
|
+
return this.columnStates.allVisibleColumns.map((cs) => cs.column);
|
|
208
140
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
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 : [];
|
|
141
|
+
/** Implements GridTableApi.visibleColumnIds. */
|
|
142
|
+
get visibleColumnIds() {
|
|
143
|
+
return this.visibleColumns.map((cs) => cs.id);
|
|
213
144
|
}
|
|
214
145
|
setVisibleColumns(ids) {
|
|
215
|
-
|
|
216
|
-
if (ids.length > this.visibleColumnIds.length) {
|
|
217
|
-
// Get a list of columns that are just now being made visible.
|
|
218
|
-
const newlyVisibleIds = ids.filter((id) => !this.visibleColumnIds.includes(id));
|
|
219
|
-
// Figure out if any of these newly visible columns needs to be initially expanded.
|
|
220
|
-
const columnsToExpand = this.columns.filter((c) => newlyVisibleIds.includes(c.id) && c.initExpanded);
|
|
221
|
-
this.parseAndUpdateExpandedColumns(columnsToExpand);
|
|
222
|
-
}
|
|
223
|
-
sessionStorage.setItem(this.visibleColumnsStorageKey, JSON.stringify(ids));
|
|
224
|
-
this.visibleColumns.replace(ids);
|
|
225
|
-
}
|
|
226
|
-
get visibleColumnIds() {
|
|
227
|
-
return [...this.visibleColumns.values()];
|
|
146
|
+
this.columnStates.setVisibleColumns(ids);
|
|
228
147
|
}
|
|
229
148
|
get expandedColumnIds() {
|
|
230
|
-
return
|
|
149
|
+
return this.columnStates.expandedColumns.map((cs) => cs.column.id);
|
|
150
|
+
}
|
|
151
|
+
isExpandedColumn(columnId) {
|
|
152
|
+
return this.columnStates.get(columnId).isExpanded;
|
|
231
153
|
}
|
|
232
154
|
toggleExpandedColumn(columnId) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
155
|
+
this.columnStates.get(columnId).toggleExpanded();
|
|
156
|
+
}
|
|
157
|
+
numberOfExpandedChildren(columnId) {
|
|
158
|
+
var _a, _b;
|
|
159
|
+
// Should this be only _visible_ children?
|
|
160
|
+
return (_b = (_a = this.columnStates.get(columnId).children) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
161
|
+
}
|
|
162
|
+
loadExpandedColumns(columnId) {
|
|
163
|
+
return this.columnStates.get(columnId).doExpand();
|
|
242
164
|
}
|
|
243
165
|
/** Called when GridTable has re-calced the rows that pass the client-side filter, or all rows. */
|
|
244
166
|
setMatchedRows(rowIds) {
|
|
@@ -286,27 +208,9 @@ exports.TableState = TableState;
|
|
|
286
208
|
/** Provides a context for rows to access their table's `TableState`. */
|
|
287
209
|
exports.TableStateContext = react_1.default.createContext({
|
|
288
210
|
get tableState() {
|
|
289
|
-
console.log("wtf?");
|
|
290
211
|
throw new Error("No TableStateContext provider");
|
|
291
212
|
},
|
|
292
213
|
});
|
|
293
|
-
function readExpandedColumnsStorage(persistCollapse) {
|
|
294
|
-
const expandedGridColumnIds = sessionStorage.getItem(getColumnStorageKey(persistCollapse));
|
|
295
|
-
return expandedGridColumnIds ? JSON.parse(expandedGridColumnIds) : [];
|
|
296
|
-
}
|
|
297
|
-
// Get the columns that are already in the visible state so we keep them toggled.
|
|
298
|
-
function readOrSetLocalVisibleColumnState(columns, storageKey) {
|
|
299
|
-
const storageValue = sessionStorage.getItem(storageKey);
|
|
300
|
-
if (storageValue) {
|
|
301
|
-
return JSON.parse(storageValue);
|
|
302
|
-
}
|
|
303
|
-
const visibleColumnIds = columns.filter((c) => c.initVisible || !c.canHide).map((c) => c.id);
|
|
304
|
-
sessionStorage.setItem(storageKey, JSON.stringify(visibleColumnIds));
|
|
305
|
-
return visibleColumnIds;
|
|
306
|
-
}
|
|
307
|
-
function getColumnStorageKey(storageKey) {
|
|
308
|
-
return `expandedColumn_${storageKey}`;
|
|
309
|
-
}
|
|
310
214
|
// Exported for testing purposes
|
|
311
215
|
function deriveSortState(currentSortState, clickedKey, initialSortState) {
|
|
312
216
|
var _a;
|
|
@@ -29,6 +29,6 @@ export declare function collapseColumn<T extends Kinded>(columnDef?: Partial<Gri
|
|
|
29
29
|
* Enforces only fixed-sized units (% and px)
|
|
30
30
|
*/
|
|
31
31
|
export declare function calcColumnSizes(columns: GridColumnWithId<any>[], tableWidth: number | undefined, tableMinWidthPx: number | undefined, expandedColumnIds: string[]): string[];
|
|
32
|
-
/** Assign column ids if missing */
|
|
32
|
+
/** Assign column ids if missing. */
|
|
33
33
|
export declare function assignDefaultColumnIds<T extends Kinded>(columns: GridColumn<T>[]): GridColumnWithId<T>[];
|
|
34
34
|
export declare const generateColumnId: (columnIndex: number) => string;
|
|
@@ -162,13 +162,12 @@ function calcColumnSizes(columns, tableWidth, tableMinWidthPx = 0, expandedColum
|
|
|
162
162
|
return sizes;
|
|
163
163
|
}
|
|
164
164
|
exports.calcColumnSizes = calcColumnSizes;
|
|
165
|
-
/** Assign column ids if missing */
|
|
165
|
+
/** Assign column ids if missing. */
|
|
166
166
|
function assignDefaultColumnIds(columns) {
|
|
167
|
-
// Note: we are not _always_ spreading the `c` property as we need to be able to return the whole proxy object that
|
|
168
|
-
// exists as part of `selectColumn` and `collapseColumn`.
|
|
169
167
|
return columns.map((c, idx) => {
|
|
170
168
|
var _a;
|
|
171
169
|
const { expandColumns } = c;
|
|
170
|
+
// If `expandColumns` is a function, we don't instrument it atm.
|
|
172
171
|
const expandColumnsWithId = (0, utils_2.isFunction)(expandColumns)
|
|
173
172
|
? expandColumns
|
|
174
173
|
: expandColumns === null || expandColumns === void 0 ? void 0 : expandColumns.map((ec, ecIdx) => {
|
|
@@ -182,7 +181,13 @@ function assignDefaultColumnIds(columns) {
|
|
|
182
181
|
expandColumns: undefined,
|
|
183
182
|
});
|
|
184
183
|
});
|
|
185
|
-
|
|
184
|
+
// We use `Object.assign` instead of spreading the `c` property to maintain
|
|
185
|
+
// the proxy objects if the user used selectColumn/collapseColumn, which have
|
|
186
|
+
// method-missing hooks that render empty cells for any non-header rows.
|
|
187
|
+
return Object.assign(c, {
|
|
188
|
+
id: (_a = c.id) !== null && _a !== void 0 ? _a : (0, exports.generateColumnId)(idx),
|
|
189
|
+
expandColumns: expandColumnsWithId,
|
|
190
|
+
});
|
|
186
191
|
});
|
|
187
192
|
}
|
|
188
193
|
exports.assignDefaultColumnIds = assignDefaultColumnIds;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.zIndices = exports.reservedRowKinds = exports.KEPT_GROUP = exports.EXPANDABLE_HEADER = exports.TOTALS = exports.HEADER = exports.matchesFilter = exports.maybeApplyFunction = exports.getJustification = exports.getAlignment = exports.getFirstOrLastCellCss = exports.emptyCell = exports.DESC = exports.ASC = exports.applyRowFn = exports.isGridCellContent = exports.toContent = void 0;
|
|
3
|
+
exports.loadArrayOrUndefined = exports.zIndices = exports.reservedRowKinds = exports.KEPT_GROUP = exports.EXPANDABLE_HEADER = exports.TOTALS = exports.HEADER = exports.matchesFilter = exports.maybeApplyFunction = exports.getJustification = exports.getAlignment = exports.getFirstOrLastCellCss = exports.emptyCell = exports.DESC = exports.ASC = exports.applyRowFn = exports.isGridCellContent = exports.toContent = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
5
5
|
const Icon_1 = require("../../Icon");
|
|
6
6
|
const ExpandableHeader_1 = require("../components/ExpandableHeader");
|
|
@@ -166,3 +166,9 @@ exports.zIndices = {
|
|
|
166
166
|
expandableHeaderTitle: 2,
|
|
167
167
|
expandableHeaderIcon: 1,
|
|
168
168
|
};
|
|
169
|
+
/** Loads an array from sessionStorage, if it exists, or `undefined`. */
|
|
170
|
+
function loadArrayOrUndefined(key) {
|
|
171
|
+
const ids = sessionStorage.getItem(key);
|
|
172
|
+
return ids ? JSON.parse(ids) : undefined;
|
|
173
|
+
}
|
|
174
|
+
exports.loadArrayOrUndefined = loadArrayOrUndefined;
|