zubin-grid 0.4.12 → 0.41.13
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/README.md +147 -5
- package/dist/core/cell.d.ts +8 -8
- package/dist/core/cell.d.ts.map +1 -1
- package/dist/core/cell.js +125 -38
- package/dist/core/cell.js.map +1 -1
- package/dist/core/grid-id.d.ts +7 -0
- package/dist/core/grid-id.d.ts.map +1 -0
- package/dist/core/grid-id.js +51 -0
- package/dist/core/grid-id.js.map +1 -0
- package/dist/core/grid.d.ts +11 -9
- package/dist/core/grid.d.ts.map +1 -1
- package/dist/core/grid.js +597 -80
- package/dist/core/grid.js.map +1 -1
- package/dist/core/head.d.ts +11 -13
- package/dist/core/head.d.ts.map +1 -1
- package/dist/core/head.js +38 -33
- package/dist/core/head.js.map +1 -1
- package/dist/core/helpers.d.ts +4 -4
- package/dist/core/helpers.d.ts.map +1 -1
- package/dist/core/helpers.js +5 -2
- package/dist/core/helpers.js.map +1 -1
- package/dist/core/{gridPersist.d.ts → persist.d.ts} +3 -3
- package/dist/core/persist.d.ts.map +1 -0
- package/dist/core/{gridPersist.js → persist.js} +43 -42
- package/dist/core/persist.js.map +1 -0
- package/dist/core/tail.d.ts +9 -11
- package/dist/core/tail.d.ts.map +1 -1
- package/dist/core/tail.js +17 -19
- package/dist/core/tail.js.map +1 -1
- package/dist/core/types/cell.types.d.ts.map +1 -0
- package/dist/core/{cell.types.js.map → types/cell.types.js.map} +1 -1
- package/dist/core/{grid.types.d.ts → types/grid.types.d.ts} +79 -16
- package/dist/core/types/grid.types.d.ts.map +1 -0
- package/dist/core/{grid.types.js.map → types/grid.types.js.map} +1 -1
- package/dist/core/{head.types.d.ts → types/head.types.d.ts} +7 -6
- package/dist/core/types/head.types.d.ts.map +1 -0
- package/dist/core/{head.types.js.map → types/head.types.js.map} +1 -1
- package/dist/core/{gridPersist.types.d.ts → types/persist.types.d.ts} +1 -1
- package/dist/core/types/persist.types.d.ts.map +1 -0
- package/dist/core/types/persist.types.js +2 -0
- package/dist/core/types/persist.types.js.map +1 -0
- package/dist/core/{tail.types.d.ts → types/tail.types.d.ts} +3 -2
- package/dist/core/types/tail.types.d.ts.map +1 -0
- package/dist/core/{tail.types.js.map → types/tail.types.js.map} +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/core/cell.types.d.ts.map +0 -1
- package/dist/core/grid.types.d.ts.map +0 -1
- package/dist/core/gridPersist.d.ts.map +0 -1
- package/dist/core/gridPersist.js.map +0 -1
- package/dist/core/gridPersist.types.d.ts.map +0 -1
- package/dist/core/gridPersist.types.js +0 -2
- package/dist/core/gridPersist.types.js.map +0 -1
- package/dist/core/head.types.d.ts.map +0 -1
- package/dist/core/tail.types.d.ts.map +0 -1
- /package/dist/core/{cell.types.d.ts → types/cell.types.d.ts} +0 -0
- /package/dist/core/{cell.types.js → types/cell.types.js} +0 -0
- /package/dist/core/{grid.types.js → types/grid.types.js} +0 -0
- /package/dist/core/{head.types.js → types/head.types.js} +0 -0
- /package/dist/core/{tail.types.js → types/tail.types.js} +0 -0
package/dist/core/grid.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
|
|
2
2
|
import { cell } from "./cell.js";
|
|
3
|
-
import {
|
|
3
|
+
import { assertGridId, createGridIdKey, formatGridId } from "./grid-id.js";
|
|
4
|
+
import { createGridPersistController, defaultGridPersistAdapter } from "./persist.js";
|
|
4
5
|
import { assertHeadId, createHeadCellMap, createHeadOrderIndex, getHeadCell, getOrderedHeads, } from "./head.js";
|
|
5
6
|
import { createTailCellMap, getTailCell, setTailCellResult } from "./tail.js";
|
|
6
7
|
export function grid(input, options) {
|
|
@@ -13,6 +14,326 @@ export function grid(input, options) {
|
|
|
13
14
|
const stateAdapter = createSchemaStateAdapter(rowCellKey, columnCellKey);
|
|
14
15
|
return createGridStore(normalizedRowHeads, normalizedColumnHeads, createGridInitialCellsFromState(initialState.cells, stateAdapter), stateAdapter, schemaOptions.persist);
|
|
15
16
|
}
|
|
17
|
+
export function createDimensionGrid(parentGrid, initialCells, dimension, options) {
|
|
18
|
+
const readBoundIds = () => (dimension === "rows"
|
|
19
|
+
? parentGrid.rowHeaders
|
|
20
|
+
: parentGrid.colHeaders);
|
|
21
|
+
const emptyRowHeaders = [];
|
|
22
|
+
const emptyColumnHeaders = [];
|
|
23
|
+
const dimensionSubscribers = new Set();
|
|
24
|
+
const resolvedPersistOption = createDimensionGridPersistOption(parentGrid, dimension, options?.persist);
|
|
25
|
+
let isApplyingState = false;
|
|
26
|
+
let boundIds = [...readBoundIds()];
|
|
27
|
+
const cellsById = new Map(boundIds.map((boundId, index) => [
|
|
28
|
+
createGridIdKey(boundId),
|
|
29
|
+
cell(initialCells[index]),
|
|
30
|
+
]));
|
|
31
|
+
let dimensionGridApi;
|
|
32
|
+
const getCellAtIndex = (index) => {
|
|
33
|
+
if (!Number.isInteger(index) || index < 0 || index >= boundIds.length) {
|
|
34
|
+
throw new Error(`Dimension grid ${dimension} index ${index} is out of bounds.`);
|
|
35
|
+
}
|
|
36
|
+
const boundId = boundIds[index];
|
|
37
|
+
const currentCell = cellsById.get(createGridIdKey(boundId));
|
|
38
|
+
if (!currentCell) {
|
|
39
|
+
throw new Error(`Missing dimension cell for ${dimension} index ${index}.`);
|
|
40
|
+
}
|
|
41
|
+
return currentCell;
|
|
42
|
+
};
|
|
43
|
+
const getState = () => ({
|
|
44
|
+
dimension,
|
|
45
|
+
cells: boundIds.map((boundId) => {
|
|
46
|
+
const currentCell = cellsById.get(createGridIdKey(boundId));
|
|
47
|
+
if (!currentCell) {
|
|
48
|
+
throw new Error(`Missing dimension cell for ${dimension} id "${formatGridId(boundId)}".`);
|
|
49
|
+
}
|
|
50
|
+
return currentCell.get();
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
const applyDimensionCells = (nextCells, mode) => {
|
|
54
|
+
const changedIndices = [];
|
|
55
|
+
const limit = mode === "update" ? Math.min(nextCells.length, boundIds.length) : boundIds.length;
|
|
56
|
+
isApplyingState = true;
|
|
57
|
+
try {
|
|
58
|
+
for (let index = 0; index < limit; index += 1) {
|
|
59
|
+
const currentCell = getCellAtIndex(index);
|
|
60
|
+
const nextValue = nextCells[index];
|
|
61
|
+
if (Object.is(currentCell.get(), nextValue)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
currentCell.set(nextValue);
|
|
65
|
+
changedIndices.push(index);
|
|
66
|
+
}
|
|
67
|
+
if (mode === "replace") {
|
|
68
|
+
for (let index = nextCells.length; index < boundIds.length; index += 1) {
|
|
69
|
+
const currentCell = getCellAtIndex(index);
|
|
70
|
+
if (Object.is(currentCell.get(), undefined)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
currentCell.set(undefined);
|
|
74
|
+
changedIndices.push(index);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
isApplyingState = false;
|
|
80
|
+
}
|
|
81
|
+
return changedIndices;
|
|
82
|
+
};
|
|
83
|
+
const { hydrate, markStateChanged } = createGridPersistController(resolvedPersistOption, {
|
|
84
|
+
getState,
|
|
85
|
+
replaceState: (nextState) => {
|
|
86
|
+
applyDimensionCells(normalizeDimensionGridStateInput(nextState, dimension).cells, "replace");
|
|
87
|
+
},
|
|
88
|
+
isApplyingState: () => isApplyingState,
|
|
89
|
+
});
|
|
90
|
+
const emitDimensionGridUpdate = (diff, persistStateChanged = false) => {
|
|
91
|
+
if (persistStateChanged) {
|
|
92
|
+
markStateChanged();
|
|
93
|
+
}
|
|
94
|
+
[...dimensionSubscribers].forEach((callback) => {
|
|
95
|
+
callback(dimensionGridApi, diff);
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const syncDimensionFromParent = () => {
|
|
99
|
+
const nextBoundIds = [...readBoundIds()];
|
|
100
|
+
if (haveSameItems(boundIds, nextBoundIds)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const nextCellsById = new Map(nextBoundIds.map((boundId) => [
|
|
104
|
+
createGridIdKey(boundId),
|
|
105
|
+
cellsById.get(createGridIdKey(boundId)) ?? cell(undefined),
|
|
106
|
+
]));
|
|
107
|
+
const previousSize = boundIds.length;
|
|
108
|
+
boundIds = nextBoundIds;
|
|
109
|
+
cellsById.clear();
|
|
110
|
+
nextCellsById.forEach((currentCell, boundIdKey) => {
|
|
111
|
+
cellsById.set(boundIdKey, currentCell);
|
|
112
|
+
});
|
|
113
|
+
emitDimensionGridUpdate({
|
|
114
|
+
type: "dimension",
|
|
115
|
+
action: previousSize === nextBoundIds.length ? "update" : "resize",
|
|
116
|
+
source: "parent",
|
|
117
|
+
dimension,
|
|
118
|
+
size: nextBoundIds.length,
|
|
119
|
+
previousSize,
|
|
120
|
+
}, true);
|
|
121
|
+
};
|
|
122
|
+
const setGrid = (nextState, mode = "replace") => {
|
|
123
|
+
const changedIndices = applyDimensionCells(normalizeDimensionGridStateInput(nextState, dimension).cells, mode);
|
|
124
|
+
if (changedIndices.length === 0) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
emitDimensionGridUpdate({
|
|
128
|
+
type: "cells",
|
|
129
|
+
action: mode === "update" ? "update" : "replace",
|
|
130
|
+
source: "setGrid",
|
|
131
|
+
dimension,
|
|
132
|
+
size: boundIds.length,
|
|
133
|
+
indices: changedIndices,
|
|
134
|
+
}, true);
|
|
135
|
+
};
|
|
136
|
+
const clearGrid = () => {
|
|
137
|
+
const changedIndices = applyDimensionCells([], "replace");
|
|
138
|
+
if (changedIndices.length === 0) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
emitDimensionGridUpdate({
|
|
142
|
+
type: "cells",
|
|
143
|
+
action: "clear",
|
|
144
|
+
source: "clearGrid",
|
|
145
|
+
dimension,
|
|
146
|
+
size: boundIds.length,
|
|
147
|
+
indices: changedIndices,
|
|
148
|
+
}, true);
|
|
149
|
+
};
|
|
150
|
+
dimensionGridApi = {
|
|
151
|
+
dimension,
|
|
152
|
+
get size() {
|
|
153
|
+
return boundIds.length;
|
|
154
|
+
},
|
|
155
|
+
get rowHeaders() {
|
|
156
|
+
return dimension === "rows" ? parentGrid.rowHeaders : emptyRowHeaders;
|
|
157
|
+
},
|
|
158
|
+
get colHeaders() {
|
|
159
|
+
return dimension === "columns" ? parentGrid.colHeaders : emptyColumnHeaders;
|
|
160
|
+
},
|
|
161
|
+
getState,
|
|
162
|
+
setGrid,
|
|
163
|
+
getCell: getCellAtIndex,
|
|
164
|
+
getValue: (index) => getCellAtIndex(index).get(),
|
|
165
|
+
hasCell: (index) => Number.isInteger(index) && index >= 0 && index < boundIds.length,
|
|
166
|
+
clearGrid,
|
|
167
|
+
subscribeGrid: (callback) => {
|
|
168
|
+
dimensionSubscribers.add(callback);
|
|
169
|
+
return () => {
|
|
170
|
+
dimensionSubscribers.delete(callback);
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
__setCellValue: (index, newValue) => {
|
|
174
|
+
const currentCell = getCellAtIndex(index);
|
|
175
|
+
if (Object.is(currentCell.get(), newValue)) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
isApplyingState = true;
|
|
179
|
+
try {
|
|
180
|
+
currentCell.set(newValue);
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
isApplyingState = false;
|
|
184
|
+
}
|
|
185
|
+
emitDimensionGridUpdate({
|
|
186
|
+
type: "cells",
|
|
187
|
+
action: "update",
|
|
188
|
+
source: "cell.set",
|
|
189
|
+
dimension,
|
|
190
|
+
size: boundIds.length,
|
|
191
|
+
indices: [index],
|
|
192
|
+
}, true);
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
Object.defineProperty(dimensionGridApi, "__persistOption", {
|
|
196
|
+
value: resolvedPersistOption,
|
|
197
|
+
enumerable: false,
|
|
198
|
+
configurable: true,
|
|
199
|
+
});
|
|
200
|
+
hydrate();
|
|
201
|
+
void parentGrid.subscribeGrid((_currentParentGrid, diff) => {
|
|
202
|
+
if (dimension === "rows") {
|
|
203
|
+
if (diff.type === "rows" ||
|
|
204
|
+
diff.type === "row-head" ||
|
|
205
|
+
(diff.type === "grid" && didGridDiffAffectAxes(diff))) {
|
|
206
|
+
syncDimensionFromParent();
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (diff.type === "columns" ||
|
|
211
|
+
diff.type === "column-head" ||
|
|
212
|
+
(diff.type === "grid" && didGridDiffAffectAxes(diff))) {
|
|
213
|
+
syncDimensionFromParent();
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
return dimensionGridApi;
|
|
217
|
+
}
|
|
218
|
+
export function createSubGrid(parentGrid, initialCells = [], options) {
|
|
219
|
+
const parentState = parentGrid.getState();
|
|
220
|
+
const stateAdapter = createGridStateCellAdapter();
|
|
221
|
+
const resolvedInitialCells = assertGridStateCellsWithinAxes(initialCells, parentState.rows, parentState.columns, "Sub grid cells");
|
|
222
|
+
const subGridStore = createGridStore(parentState.rows, parentState.columns, createGridInitialCellsFromState(resolvedInitialCells, stateAdapter), stateAdapter, createSubGridPersistOption(parentGrid, options?.persist));
|
|
223
|
+
const getSubGridState = () => {
|
|
224
|
+
const nextParentState = parentGrid.getState();
|
|
225
|
+
return createSubGridState(nextParentState.rows, nextParentState.columns, subGridStore.getState().cells);
|
|
226
|
+
};
|
|
227
|
+
const syncAxesFromParent = () => {
|
|
228
|
+
const nextParentState = parentGrid.getState();
|
|
229
|
+
const currentSubGridState = subGridStore.getState();
|
|
230
|
+
const nextCells = filterGridStateCellsToAxes(currentSubGridState.cells, nextParentState.rows, nextParentState.columns);
|
|
231
|
+
if (haveSameHeadSnapshots(currentSubGridState.rows, nextParentState.rows) &&
|
|
232
|
+
haveSameHeadSnapshots(currentSubGridState.columns, nextParentState.columns) &&
|
|
233
|
+
nextCells.length === currentSubGridState.cells.length) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
subGridStore.setGrid({
|
|
237
|
+
rows: nextParentState.rows,
|
|
238
|
+
columns: nextParentState.columns,
|
|
239
|
+
cells: nextCells,
|
|
240
|
+
}, "replace");
|
|
241
|
+
};
|
|
242
|
+
void parentGrid.subscribeGrid((_currentParentGrid, diff) => {
|
|
243
|
+
if (diff.type === "row-head" && diff.rows?.length) {
|
|
244
|
+
diff.rows.forEach((rowHead) => {
|
|
245
|
+
subGridStore.updateRowHead(rowHead.id, rowHead);
|
|
246
|
+
});
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (diff.type === "column-head" && diff.columns?.length) {
|
|
250
|
+
diff.columns.forEach((columnHead) => {
|
|
251
|
+
subGridStore.updateColumnHead(columnHead.id, columnHead);
|
|
252
|
+
});
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (diff.type === "rows" && diff.rows?.length) {
|
|
256
|
+
subGridStore.upsertRows(diff.rows);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (diff.type === "columns" && diff.columns?.length) {
|
|
260
|
+
subGridStore.upsertColumns(diff.columns);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (diff.type === "grid" && didGridDiffAffectAxes(diff)) {
|
|
264
|
+
syncAxesFromParent();
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
const subGridApi = Object.create(subGridStore);
|
|
268
|
+
Object.defineProperties(subGridApi, {
|
|
269
|
+
rowHeaders: {
|
|
270
|
+
enumerable: true,
|
|
271
|
+
configurable: true,
|
|
272
|
+
get: () => parentGrid.rowHeaders,
|
|
273
|
+
},
|
|
274
|
+
colHeaders: {
|
|
275
|
+
enumerable: true,
|
|
276
|
+
configurable: true,
|
|
277
|
+
get: () => parentGrid.colHeaders,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
subGridApi.getState = getSubGridState;
|
|
281
|
+
subGridApi.getRowHead = (rowId) => parentGrid.getRowHead(rowId);
|
|
282
|
+
subGridApi.getColumnHead = (columnId) => parentGrid.getColumnHead(columnId);
|
|
283
|
+
subGridApi.updateRowHead = (rowId, nextRowHead) => {
|
|
284
|
+
parentGrid.updateRowHead(rowId, nextRowHead);
|
|
285
|
+
};
|
|
286
|
+
subGridApi.updateColumnHead = (columnId, nextColumnHead) => {
|
|
287
|
+
parentGrid.updateColumnHead(columnId, nextColumnHead);
|
|
288
|
+
};
|
|
289
|
+
subGridApi.upsertRow = (nextRowHead) => {
|
|
290
|
+
parentGrid.upsertRow(nextRowHead);
|
|
291
|
+
};
|
|
292
|
+
subGridApi.upsertRows = (nextRowHeads) => {
|
|
293
|
+
parentGrid.upsertRows(nextRowHeads);
|
|
294
|
+
};
|
|
295
|
+
subGridApi.upsertColumn = (nextColumnHead) => {
|
|
296
|
+
parentGrid.upsertColumn(nextColumnHead);
|
|
297
|
+
};
|
|
298
|
+
subGridApi.upsertColumns = (nextColumnHeads) => {
|
|
299
|
+
parentGrid.upsertColumns(nextColumnHeads);
|
|
300
|
+
};
|
|
301
|
+
subGridApi.subscribeRowHead = (rowId, callback) => parentGrid.subscribeRowHead(rowId, callback);
|
|
302
|
+
subGridApi.subscribeColumnHead = (columnId, callback) => parentGrid.subscribeColumnHead(columnId, callback);
|
|
303
|
+
subGridApi.setGrid = (nextState, mode = "replace") => {
|
|
304
|
+
const patch = normalizeGridStatePatchInput(nextState);
|
|
305
|
+
const currentParentState = parentGrid.getState();
|
|
306
|
+
if (mode === "update") {
|
|
307
|
+
if (patch.rows?.length) {
|
|
308
|
+
parentGrid.upsertRows(patch.rows);
|
|
309
|
+
}
|
|
310
|
+
if (patch.columns?.length) {
|
|
311
|
+
parentGrid.upsertColumns(patch.columns);
|
|
312
|
+
}
|
|
313
|
+
if (patch.cells?.length) {
|
|
314
|
+
subGridStore.setGrid({
|
|
315
|
+
rows: currentParentState.rows,
|
|
316
|
+
columns: currentParentState.columns,
|
|
317
|
+
cells: assertGridStateCellsWithinAxes(patch.cells, currentParentState.rows, currentParentState.columns, "Sub grid cells"),
|
|
318
|
+
}, "update");
|
|
319
|
+
}
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if ((patch.rows && !haveSameHeadSnapshots(patch.rows, currentParentState.rows)) ||
|
|
323
|
+
(patch.columns && !haveSameHeadSnapshots(patch.columns, currentParentState.columns))) {
|
|
324
|
+
throw new Error("Sub grids inherit rows and columns from their parent. Replace parent dimensions on the parent grid instead.");
|
|
325
|
+
}
|
|
326
|
+
subGridStore.setGrid({
|
|
327
|
+
rows: currentParentState.rows,
|
|
328
|
+
columns: currentParentState.columns,
|
|
329
|
+
cells: assertGridStateCellsWithinAxes(patch.cells ?? [], currentParentState.rows, currentParentState.columns, "Sub grid cells"),
|
|
330
|
+
}, "replace");
|
|
331
|
+
};
|
|
332
|
+
subGridApi.clearGrid = () => {
|
|
333
|
+
subGridStore.clearCells();
|
|
334
|
+
};
|
|
335
|
+
return subGridApi;
|
|
336
|
+
}
|
|
16
337
|
function createGridStore(initialRows, initialColumns, initialCells, stateAdapter, persist) {
|
|
17
338
|
assertUniqueHeadIds(initialRows, "row");
|
|
18
339
|
assertUniqueHeadIds(initialColumns, "column");
|
|
@@ -54,13 +375,13 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
54
375
|
return stateAdapter.deserializeCell(stateAdapter.serializeCell(rowId, columnId, value)).value;
|
|
55
376
|
};
|
|
56
377
|
const recomputeRowTailInternal = (rowId) => {
|
|
57
|
-
const onRowUpdate = rowTailUpdaters.get(rowId);
|
|
378
|
+
const onRowUpdate = rowTailUpdaters.get(createGridIdKey(rowId));
|
|
58
379
|
if (!onRowUpdate)
|
|
59
380
|
return false;
|
|
60
381
|
return setTailCellResult(getTailCell(rowTailCells, rowId, "row"), onRowUpdate(getRowCells(rowId)));
|
|
61
382
|
};
|
|
62
383
|
const recomputeColumnTailInternal = (columnId) => {
|
|
63
|
-
const onColumnUpdate = columnTailUpdaters.get(columnId);
|
|
384
|
+
const onColumnUpdate = columnTailUpdaters.get(createGridIdKey(columnId));
|
|
64
385
|
if (!onColumnUpdate)
|
|
65
386
|
return false;
|
|
66
387
|
return setTailCellResult(getTailCell(columnTailCells, columnId, "column"), onColumnUpdate(getColumnCells(columnId)));
|
|
@@ -89,13 +410,16 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
89
410
|
cellsMap.delete(gridKey);
|
|
90
411
|
};
|
|
91
412
|
const attachCell = (rowId, columnId, currentCell) => {
|
|
92
|
-
if (!rowHeadCells.has(rowId))
|
|
93
|
-
throw new Error(`Missing row header "${rowId}".`);
|
|
94
|
-
|
|
95
|
-
|
|
413
|
+
if (!rowHeadCells.has(createGridIdKey(rowId))) {
|
|
414
|
+
throw new Error(`Missing row header "${formatGridId(rowId)}".`);
|
|
415
|
+
}
|
|
416
|
+
if (!columnHeadCells.has(createGridIdKey(columnId))) {
|
|
417
|
+
throw new Error(`Missing column header "${formatGridId(columnId)}".`);
|
|
418
|
+
}
|
|
96
419
|
const gridKey = createGridKey(rowId, columnId);
|
|
97
|
-
if (cellsMap.has(gridKey))
|
|
98
|
-
throw new Error(`Duplicate cell for row "${rowId}" and column "${columnId}".`);
|
|
420
|
+
if (cellsMap.has(gridKey)) {
|
|
421
|
+
throw new Error(`Duplicate cell for row "${formatGridId(rowId)}" and column "${formatGridId(columnId)}".`);
|
|
422
|
+
}
|
|
99
423
|
cellsMap.set(gridKey, currentCell);
|
|
100
424
|
let previousValue = currentCell.get();
|
|
101
425
|
const unsubscribe = currentCell.subscribe(() => {
|
|
@@ -124,8 +448,9 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
124
448
|
};
|
|
125
449
|
const getCell = (rowId, columnId) => {
|
|
126
450
|
const currentCell = cellsMap.get(createGridKey(rowId, columnId));
|
|
127
|
-
if (!currentCell)
|
|
128
|
-
throw new Error(`Missing cell for row "${rowId}" and column "${columnId}".`);
|
|
451
|
+
if (!currentCell) {
|
|
452
|
+
throw new Error(`Missing cell for row "${formatGridId(rowId)}" and column "${formatGridId(columnId)}".`);
|
|
453
|
+
}
|
|
129
454
|
return currentCell;
|
|
130
455
|
};
|
|
131
456
|
const createAxisCellSnapshot = (rowId, columnId) => {
|
|
@@ -152,15 +477,16 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
152
477
|
assertUniqueHeadIds(nextHeads, axis);
|
|
153
478
|
const nextIds = new Set();
|
|
154
479
|
nextHeads.forEach((nextHead, index) => {
|
|
155
|
-
|
|
156
|
-
|
|
480
|
+
const idKey = createGridIdKey(nextHead.id);
|
|
481
|
+
nextIds.add(idKey);
|
|
482
|
+
const currentHeadCell = headCells.get(idKey);
|
|
157
483
|
if (currentHeadCell)
|
|
158
484
|
currentHeadCell.set(nextHead);
|
|
159
485
|
else
|
|
160
|
-
headCells.set(
|
|
161
|
-
if (!tailCells.has(
|
|
162
|
-
tailCells.set(
|
|
163
|
-
headOrder.set(
|
|
486
|
+
headCells.set(idKey, cell(nextHead));
|
|
487
|
+
if (!tailCells.has(idKey))
|
|
488
|
+
tailCells.set(idKey, cell(createEmptyTailState()));
|
|
489
|
+
headOrder.set(idKey, index);
|
|
164
490
|
});
|
|
165
491
|
[...headCells.keys()].forEach((id) => {
|
|
166
492
|
if (nextIds.has(id))
|
|
@@ -174,24 +500,24 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
174
500
|
const replaceState = (nextState) => {
|
|
175
501
|
isApplyingState = true;
|
|
176
502
|
try {
|
|
177
|
-
syncAxisHeads(nextState.rows, "row", rowHeadCells, rowTailCells, rowHeadOrder, (
|
|
178
|
-
rowTailUpdaters.delete(
|
|
503
|
+
syncAxisHeads(nextState.rows, "row", rowHeadCells, rowTailCells, rowHeadOrder, (idKey) => {
|
|
504
|
+
rowTailUpdaters.delete(idKey);
|
|
179
505
|
});
|
|
180
|
-
syncAxisHeads(nextState.columns, "column", columnHeadCells, columnTailCells, columnHeadOrder, (
|
|
181
|
-
columnTailUpdaters.delete(
|
|
506
|
+
syncAxisHeads(nextState.columns, "column", columnHeadCells, columnTailCells, columnHeadOrder, (idKey) => {
|
|
507
|
+
columnTailUpdaters.delete(idKey);
|
|
182
508
|
});
|
|
183
509
|
const nextCells = new Map();
|
|
184
510
|
nextState.cells.forEach((nextStateCell) => {
|
|
185
511
|
const { rowId, columnId, value } = stateAdapter.deserializeCell(nextStateCell);
|
|
186
|
-
if (!rowHeadCells.has(rowId)) {
|
|
187
|
-
throw new Error(`Missing row header "${rowId}".`);
|
|
512
|
+
if (!rowHeadCells.has(createGridIdKey(rowId))) {
|
|
513
|
+
throw new Error(`Missing row header "${formatGridId(rowId)}".`);
|
|
188
514
|
}
|
|
189
|
-
if (!columnHeadCells.has(columnId)) {
|
|
190
|
-
throw new Error(`Missing column header "${columnId}".`);
|
|
515
|
+
if (!columnHeadCells.has(createGridIdKey(columnId))) {
|
|
516
|
+
throw new Error(`Missing column header "${formatGridId(columnId)}".`);
|
|
191
517
|
}
|
|
192
518
|
const gridKey = createGridKey(rowId, columnId);
|
|
193
519
|
if (nextCells.has(gridKey)) {
|
|
194
|
-
throw new Error(`Duplicate cell for row "${rowId}" and column "${columnId}".`);
|
|
520
|
+
throw new Error(`Duplicate cell for row "${formatGridId(rowId)}" and column "${formatGridId(columnId)}".`);
|
|
195
521
|
}
|
|
196
522
|
nextCells.set(gridKey, {
|
|
197
523
|
rowId,
|
|
@@ -245,8 +571,8 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
245
571
|
if (nextCells.length === 0) {
|
|
246
572
|
return null;
|
|
247
573
|
}
|
|
248
|
-
const touchedRowIds = new
|
|
249
|
-
const touchedColumnIds = new
|
|
574
|
+
const touchedRowIds = new Map();
|
|
575
|
+
const touchedColumnIds = new Map();
|
|
250
576
|
const normalizedCells = [];
|
|
251
577
|
const previousCells = [];
|
|
252
578
|
const cellKeys = [];
|
|
@@ -254,10 +580,12 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
254
580
|
try {
|
|
255
581
|
nextCells.forEach((nextStateCell) => {
|
|
256
582
|
const { rowId, columnId, value } = stateAdapter.deserializeCell(nextStateCell);
|
|
257
|
-
if (!rowHeadCells.has(rowId))
|
|
258
|
-
throw new Error(`Missing row header "${rowId}".`);
|
|
259
|
-
|
|
260
|
-
|
|
583
|
+
if (!rowHeadCells.has(createGridIdKey(rowId))) {
|
|
584
|
+
throw new Error(`Missing row header "${formatGridId(rowId)}".`);
|
|
585
|
+
}
|
|
586
|
+
if (!columnHeadCells.has(createGridIdKey(columnId))) {
|
|
587
|
+
throw new Error(`Missing column header "${formatGridId(columnId)}".`);
|
|
588
|
+
}
|
|
261
589
|
const normalizedValue = normalizeCellValue(rowId, columnId, value);
|
|
262
590
|
const gridKey = createGridKey(rowId, columnId);
|
|
263
591
|
const currentCell = cellsMap.get(gridKey);
|
|
@@ -269,16 +597,16 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
269
597
|
attachCell(rowId, columnId, cell(normalizedValue));
|
|
270
598
|
}
|
|
271
599
|
normalizedCells.push(stateAdapter.serializeCell(rowId, columnId, normalizedValue));
|
|
272
|
-
touchedRowIds.
|
|
273
|
-
touchedColumnIds.
|
|
600
|
+
touchedRowIds.set(createGridIdKey(rowId), rowId);
|
|
601
|
+
touchedColumnIds.set(createGridIdKey(columnId), columnId);
|
|
274
602
|
cellKeys.push(gridKey);
|
|
275
603
|
});
|
|
276
604
|
}
|
|
277
605
|
finally {
|
|
278
606
|
isApplyingState = false;
|
|
279
607
|
}
|
|
280
|
-
const rowIds = [...touchedRowIds];
|
|
281
|
-
const columnIds = [...touchedColumnIds];
|
|
608
|
+
const rowIds = [...touchedRowIds.values()];
|
|
609
|
+
const columnIds = [...touchedColumnIds.values()];
|
|
282
610
|
return {
|
|
283
611
|
rowIds,
|
|
284
612
|
columnIds,
|
|
@@ -311,35 +639,34 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
311
639
|
if (nextRowHeads.length === 0) {
|
|
312
640
|
return null;
|
|
313
641
|
}
|
|
314
|
-
const rowIds = new
|
|
642
|
+
const rowIds = new Map();
|
|
315
643
|
const rows = [];
|
|
316
644
|
const previousRows = [];
|
|
317
645
|
let shouldRecomputeColumns = false;
|
|
318
646
|
nextRowHeads.forEach((nextRowHead) => {
|
|
319
647
|
const rowHeadLike = nextRowHead;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const currentHeadCell = rowHeadCells.get(rowHeadLike.id);
|
|
648
|
+
const rowIdKey = createGridIdKey(rowHeadLike.id);
|
|
649
|
+
assertGridId(rowHeadLike.id, "Row header upserts");
|
|
650
|
+
const currentHeadCell = rowHeadCells.get(rowIdKey);
|
|
324
651
|
const currentHead = currentHeadCell?.get();
|
|
325
652
|
const resolvedHead = normalizeUpsertHead(rowHeadLike, currentHead, nextRowFallbackOrder);
|
|
326
653
|
if (currentHeadCell) {
|
|
327
654
|
currentHeadCell.set(resolvedHead);
|
|
328
655
|
}
|
|
329
656
|
else {
|
|
330
|
-
rowHeadCells.set(
|
|
331
|
-
rowTailCells.set(
|
|
332
|
-
rowHeadOrder.set(
|
|
657
|
+
rowHeadCells.set(rowIdKey, cell(resolvedHead));
|
|
658
|
+
rowTailCells.set(rowIdKey, cell(createEmptyTailState()));
|
|
659
|
+
rowHeadOrder.set(rowIdKey, nextRowFallbackOrder);
|
|
333
660
|
nextRowFallbackOrder += 1;
|
|
334
661
|
}
|
|
335
662
|
rows.push(resolvedHead);
|
|
336
663
|
if (currentHead) {
|
|
337
664
|
previousRows.push(currentHead);
|
|
338
665
|
}
|
|
339
|
-
rowIds.
|
|
666
|
+
rowIds.set(rowIdKey, resolvedHead.id);
|
|
340
667
|
shouldRecomputeColumns ||= !currentHead || currentHead.order !== resolvedHead.order;
|
|
341
668
|
});
|
|
342
|
-
const resolvedRowIds = [...rowIds];
|
|
669
|
+
const resolvedRowIds = [...rowIds.values()];
|
|
343
670
|
return {
|
|
344
671
|
rows,
|
|
345
672
|
previousRows,
|
|
@@ -368,35 +695,34 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
368
695
|
if (nextColumnHeads.length === 0) {
|
|
369
696
|
return null;
|
|
370
697
|
}
|
|
371
|
-
const columnIds = new
|
|
698
|
+
const columnIds = new Map();
|
|
372
699
|
const columns = [];
|
|
373
700
|
const previousColumns = [];
|
|
374
701
|
let shouldRecomputeRows = false;
|
|
375
702
|
nextColumnHeads.forEach((nextColumnHead) => {
|
|
376
703
|
const columnHeadLike = nextColumnHead;
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const currentHeadCell = columnHeadCells.get(columnHeadLike.id);
|
|
704
|
+
const columnIdKey = createGridIdKey(columnHeadLike.id);
|
|
705
|
+
assertGridId(columnHeadLike.id, "Column header upserts");
|
|
706
|
+
const currentHeadCell = columnHeadCells.get(columnIdKey);
|
|
381
707
|
const currentHead = currentHeadCell?.get();
|
|
382
708
|
const resolvedHead = normalizeUpsertHead(columnHeadLike, currentHead, nextColumnFallbackOrder);
|
|
383
709
|
if (currentHeadCell) {
|
|
384
710
|
currentHeadCell.set(resolvedHead);
|
|
385
711
|
}
|
|
386
712
|
else {
|
|
387
|
-
columnHeadCells.set(
|
|
388
|
-
columnTailCells.set(
|
|
389
|
-
columnHeadOrder.set(
|
|
713
|
+
columnHeadCells.set(columnIdKey, cell(resolvedHead));
|
|
714
|
+
columnTailCells.set(columnIdKey, cell(createEmptyTailState()));
|
|
715
|
+
columnHeadOrder.set(columnIdKey, nextColumnFallbackOrder);
|
|
390
716
|
nextColumnFallbackOrder += 1;
|
|
391
717
|
}
|
|
392
718
|
columns.push(resolvedHead);
|
|
393
719
|
if (currentHead) {
|
|
394
720
|
previousColumns.push(currentHead);
|
|
395
721
|
}
|
|
396
|
-
columnIds.
|
|
722
|
+
columnIds.set(columnIdKey, resolvedHead.id);
|
|
397
723
|
shouldRecomputeRows ||= !currentHead || currentHead.order !== resolvedHead.order;
|
|
398
724
|
});
|
|
399
|
-
const resolvedColumnIds = [...columnIds];
|
|
725
|
+
const resolvedColumnIds = [...columnIds.values()];
|
|
400
726
|
return {
|
|
401
727
|
columns,
|
|
402
728
|
previousColumns,
|
|
@@ -524,23 +850,25 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
524
850
|
});
|
|
525
851
|
};
|
|
526
852
|
function registerRowTail(rowId, onRowUpdate) {
|
|
527
|
-
|
|
853
|
+
const rowIdKey = createGridIdKey(rowId);
|
|
854
|
+
rowTailUpdaters.set(rowIdKey, onRowUpdate);
|
|
528
855
|
recomputeRowTailInternal(rowId);
|
|
529
856
|
return () => {
|
|
530
|
-
if (rowTailUpdaters.get(
|
|
857
|
+
if (rowTailUpdaters.get(rowIdKey) !== onRowUpdate) {
|
|
531
858
|
return;
|
|
532
859
|
}
|
|
533
|
-
rowTailUpdaters.delete(
|
|
860
|
+
rowTailUpdaters.delete(rowIdKey);
|
|
534
861
|
};
|
|
535
862
|
}
|
|
536
863
|
function registerColumnTail(columnId, onColumnUpdate) {
|
|
537
|
-
|
|
864
|
+
const columnIdKey = createGridIdKey(columnId);
|
|
865
|
+
columnTailUpdaters.set(columnIdKey, onColumnUpdate);
|
|
538
866
|
recomputeColumnTailInternal(columnId);
|
|
539
867
|
return () => {
|
|
540
|
-
if (columnTailUpdaters.get(
|
|
868
|
+
if (columnTailUpdaters.get(columnIdKey) !== onColumnUpdate) {
|
|
541
869
|
return;
|
|
542
870
|
}
|
|
543
|
-
columnTailUpdaters.delete(
|
|
871
|
+
columnTailUpdaters.delete(columnIdKey);
|
|
544
872
|
};
|
|
545
873
|
}
|
|
546
874
|
const setGrid = (nextState, mode = "replace") => {
|
|
@@ -751,6 +1079,11 @@ function createGridStore(initialRows, initialColumns, initialCells, stateAdapter
|
|
|
751
1079
|
recomputeRowTail,
|
|
752
1080
|
recomputeColumnTail,
|
|
753
1081
|
};
|
|
1082
|
+
Object.defineProperty(gridApi, "__persistOption", {
|
|
1083
|
+
value: persist,
|
|
1084
|
+
enumerable: false,
|
|
1085
|
+
configurable: true,
|
|
1086
|
+
});
|
|
754
1087
|
return gridApi;
|
|
755
1088
|
}
|
|
756
1089
|
function resolveUpdater(nextValue, currentValue) {
|
|
@@ -759,7 +1092,7 @@ function resolveUpdater(nextValue, currentValue) {
|
|
|
759
1092
|
: nextValue;
|
|
760
1093
|
}
|
|
761
1094
|
export function createGridKey(rowId, columnId) {
|
|
762
|
-
return
|
|
1095
|
+
return `row=${createGridIdKey(rowId)}|col=${createGridIdKey(columnId)}`;
|
|
763
1096
|
}
|
|
764
1097
|
export function useGrid(currentGrid, options) {
|
|
765
1098
|
const snapshotRef = useRef({
|
|
@@ -797,7 +1130,7 @@ function toOptionalArray(values) {
|
|
|
797
1130
|
}
|
|
798
1131
|
function haveSameItems(left, right) {
|
|
799
1132
|
return (left.length === right.length &&
|
|
800
|
-
left.every((currentValue, index) =>
|
|
1133
|
+
left.every((currentValue, index) => createGridIdKey(currentValue) === createGridIdKey(right[index])));
|
|
801
1134
|
}
|
|
802
1135
|
function normalizeGridStateInput(value) {
|
|
803
1136
|
if (!value || typeof value !== "object") {
|
|
@@ -849,16 +1182,16 @@ function mergeHeadStates(currentHeads, nextHeads) {
|
|
|
849
1182
|
const currentIds = new Set();
|
|
850
1183
|
const nextHeadsById = new Map();
|
|
851
1184
|
currentHeads.forEach((currentHead) => {
|
|
852
|
-
currentIds.add(currentHead.id);
|
|
1185
|
+
currentIds.add(createGridIdKey(currentHead.id));
|
|
853
1186
|
});
|
|
854
1187
|
nextHeads.forEach((nextHead) => {
|
|
855
|
-
nextHeadsById.set(nextHead.id, nextHead);
|
|
1188
|
+
nextHeadsById.set(createGridIdKey(nextHead.id), nextHead);
|
|
856
1189
|
});
|
|
857
1190
|
const resolvedHeads = currentHeads.map((currentHead) => {
|
|
858
|
-
return nextHeadsById.get(currentHead.id) ?? currentHead;
|
|
1191
|
+
return nextHeadsById.get(createGridIdKey(currentHead.id)) ?? currentHead;
|
|
859
1192
|
});
|
|
860
1193
|
nextHeads.forEach((nextHead) => {
|
|
861
|
-
if (currentIds.has(nextHead.id)) {
|
|
1194
|
+
if (currentIds.has(createGridIdKey(nextHead.id))) {
|
|
862
1195
|
return;
|
|
863
1196
|
}
|
|
864
1197
|
resolvedHeads.push(nextHead);
|
|
@@ -893,7 +1226,7 @@ function normalizeGridState(value) {
|
|
|
893
1226
|
throw new Error("Grid state initializer must return an object.");
|
|
894
1227
|
}
|
|
895
1228
|
if (Array.isArray(value)) {
|
|
896
|
-
throw new Error("
|
|
1229
|
+
throw new Error("Grid state initializer must be a schema object with rows, columns, and cells.");
|
|
897
1230
|
}
|
|
898
1231
|
const partialState = value;
|
|
899
1232
|
const { cells = [], rows = [], columns = [] } = partialState;
|
|
@@ -909,9 +1242,7 @@ function normalizeGridState(value) {
|
|
|
909
1242
|
function normalizeRecordHeads(heads, idKey) {
|
|
910
1243
|
return heads.map((head, index) => {
|
|
911
1244
|
const id = head[idKey];
|
|
912
|
-
|
|
913
|
-
throw new Error(`Grid header key "${String(idKey)}" must resolve to a string id.`);
|
|
914
|
-
}
|
|
1245
|
+
assertGridId(id, `Grid header key "${String(idKey)}"`);
|
|
915
1246
|
return {
|
|
916
1247
|
...head,
|
|
917
1248
|
id,
|
|
@@ -927,7 +1258,7 @@ function createGridInitialCellsFromState(stateCells, stateAdapter) {
|
|
|
927
1258
|
const { rowId, columnId, value } = stateAdapter.deserializeCell(stateCell);
|
|
928
1259
|
const gridKey = createGridKey(rowId, columnId);
|
|
929
1260
|
if (seenKeys.has(gridKey)) {
|
|
930
|
-
throw new Error(`Duplicate cell for row "${rowId}" and column "${columnId}".`);
|
|
1261
|
+
throw new Error(`Duplicate cell for row "${formatGridId(rowId)}" and column "${formatGridId(columnId)}".`);
|
|
931
1262
|
}
|
|
932
1263
|
seenKeys.add(gridKey);
|
|
933
1264
|
initialCells.push({
|
|
@@ -943,9 +1274,8 @@ function createSchemaStateAdapter(rowCellKey, columnCellKey) {
|
|
|
943
1274
|
deserializeCell: (stateCell) => {
|
|
944
1275
|
const rowId = stateCell[rowCellKey];
|
|
945
1276
|
const columnId = stateCell[columnCellKey];
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
}
|
|
1277
|
+
assertGridId(rowId, `Grid cell key "${String(rowCellKey)}"`);
|
|
1278
|
+
assertGridId(columnId, `Grid cell key "${String(columnCellKey)}"`);
|
|
949
1279
|
return {
|
|
950
1280
|
rowId: rowId,
|
|
951
1281
|
columnId: columnId,
|
|
@@ -984,10 +1314,11 @@ function normalizeUpsertHead(nextHead, currentHead, fallbackOrder) {
|
|
|
984
1314
|
function assertUniqueHeadIds(heads, axis) {
|
|
985
1315
|
const seenIds = new Set();
|
|
986
1316
|
heads.forEach((head) => {
|
|
987
|
-
|
|
988
|
-
|
|
1317
|
+
const idKey = createGridIdKey(head.id);
|
|
1318
|
+
if (seenIds.has(idKey)) {
|
|
1319
|
+
throw new Error(`Duplicate ${axis} header "${formatGridId(head.id)}".`);
|
|
989
1320
|
}
|
|
990
|
-
seenIds.add(
|
|
1321
|
+
seenIds.add(idKey);
|
|
991
1322
|
});
|
|
992
1323
|
}
|
|
993
1324
|
function createEmptyTailState() {
|
|
@@ -1005,6 +1336,192 @@ function readGridHeadLabel(head, id) {
|
|
|
1005
1336
|
if (typeof name === "string") {
|
|
1006
1337
|
return name;
|
|
1007
1338
|
}
|
|
1008
|
-
return id;
|
|
1339
|
+
return formatGridId(id);
|
|
1340
|
+
}
|
|
1341
|
+
function createGridStateCellAdapter() {
|
|
1342
|
+
return {
|
|
1343
|
+
deserializeCell: (stateCell) => ({
|
|
1344
|
+
rowId: stateCell.rowId,
|
|
1345
|
+
columnId: stateCell.columnId,
|
|
1346
|
+
value: stateCell.value,
|
|
1347
|
+
}),
|
|
1348
|
+
serializeCell: (rowId, columnId, value) => ({
|
|
1349
|
+
rowId,
|
|
1350
|
+
columnId,
|
|
1351
|
+
value,
|
|
1352
|
+
}),
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
function createSubGridPersistOption(parentGrid, persist) {
|
|
1356
|
+
const resolvedPersist = resolveDependentGridPersistOption(parentGrid, persist, "sub-grid");
|
|
1357
|
+
if (!resolvedPersist) {
|
|
1358
|
+
return undefined;
|
|
1359
|
+
}
|
|
1360
|
+
const [storageKey, adapter] = resolvedPersist;
|
|
1361
|
+
const resolvedAdapter = (adapter ??
|
|
1362
|
+
defaultGridPersistAdapter);
|
|
1363
|
+
return [
|
|
1364
|
+
storageKey,
|
|
1365
|
+
{
|
|
1366
|
+
get: async (nextStorageKey) => {
|
|
1367
|
+
const persistedState = await Promise.resolve(resolvedAdapter.get(nextStorageKey));
|
|
1368
|
+
if (persistedState === null) {
|
|
1369
|
+
return null;
|
|
1370
|
+
}
|
|
1371
|
+
try {
|
|
1372
|
+
const normalizedState = normalizeGridStateInput(persistedState);
|
|
1373
|
+
const parentState = parentGrid.getState();
|
|
1374
|
+
return createSubGridState(parentState.rows, parentState.columns, normalizedState.cells);
|
|
1375
|
+
}
|
|
1376
|
+
catch {
|
|
1377
|
+
return null;
|
|
1378
|
+
}
|
|
1379
|
+
},
|
|
1380
|
+
set: (nextStorageKey, nextState) => {
|
|
1381
|
+
const parentState = parentGrid.getState();
|
|
1382
|
+
return resolvedAdapter.set(nextStorageKey, createSubGridState(parentState.rows, parentState.columns, nextState.cells));
|
|
1383
|
+
},
|
|
1384
|
+
remove: (nextStorageKey) => resolvedAdapter.remove(nextStorageKey),
|
|
1385
|
+
},
|
|
1386
|
+
];
|
|
1387
|
+
}
|
|
1388
|
+
function createDimensionGridPersistOption(parentGrid, dimension, persist) {
|
|
1389
|
+
const resolvedPersist = resolveDependentGridPersistOption(parentGrid, persist, `dimension-grid:${dimension}`);
|
|
1390
|
+
if (!resolvedPersist) {
|
|
1391
|
+
return undefined;
|
|
1392
|
+
}
|
|
1393
|
+
const [storageKey, adapter] = resolvedPersist;
|
|
1394
|
+
const resolvedAdapter = (adapter ?? defaultGridPersistAdapter);
|
|
1395
|
+
return [
|
|
1396
|
+
storageKey,
|
|
1397
|
+
{
|
|
1398
|
+
get: async (nextStorageKey) => {
|
|
1399
|
+
const persistedState = await Promise.resolve(resolvedAdapter.get(nextStorageKey));
|
|
1400
|
+
if (persistedState === null) {
|
|
1401
|
+
return null;
|
|
1402
|
+
}
|
|
1403
|
+
try {
|
|
1404
|
+
return normalizeDimensionGridStateInput(persistedState, dimension);
|
|
1405
|
+
}
|
|
1406
|
+
catch {
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
},
|
|
1410
|
+
set: (nextStorageKey, nextState) => {
|
|
1411
|
+
return resolvedAdapter.set(nextStorageKey, normalizeDimensionGridStateInput(nextState, dimension));
|
|
1412
|
+
},
|
|
1413
|
+
remove: (nextStorageKey) => resolvedAdapter.remove(nextStorageKey),
|
|
1414
|
+
},
|
|
1415
|
+
];
|
|
1416
|
+
}
|
|
1417
|
+
function normalizeDimensionGridStateInput(value, dimension) {
|
|
1418
|
+
if (Array.isArray(value)) {
|
|
1419
|
+
return {
|
|
1420
|
+
dimension,
|
|
1421
|
+
cells: value,
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
if (!value || typeof value !== "object") {
|
|
1425
|
+
throw new Error("Dimension grid state updates must be arrays or objects.");
|
|
1426
|
+
}
|
|
1427
|
+
const nextState = value;
|
|
1428
|
+
if (nextState.dimension !== undefined && nextState.dimension !== dimension) {
|
|
1429
|
+
throw new Error(`Dimension grid state must use the "${dimension}" dimension when updating this grid.`);
|
|
1430
|
+
}
|
|
1431
|
+
if (!Array.isArray(nextState.cells)) {
|
|
1432
|
+
throw new Error("Dimension grid state updates must provide a cells array.");
|
|
1433
|
+
}
|
|
1434
|
+
return {
|
|
1435
|
+
dimension,
|
|
1436
|
+
cells: nextState.cells,
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
function resolveDependentGridPersistOption(parentGrid, persist, suffix) {
|
|
1440
|
+
if (persist === false) {
|
|
1441
|
+
return undefined;
|
|
1442
|
+
}
|
|
1443
|
+
if (persist) {
|
|
1444
|
+
return persist;
|
|
1445
|
+
}
|
|
1446
|
+
const inheritedPersist = parentGrid.__persistOption;
|
|
1447
|
+
if (!inheritedPersist) {
|
|
1448
|
+
return undefined;
|
|
1449
|
+
}
|
|
1450
|
+
return [
|
|
1451
|
+
`${inheritedPersist[0]}:${suffix}`,
|
|
1452
|
+
inheritedPersist[1],
|
|
1453
|
+
];
|
|
1454
|
+
}
|
|
1455
|
+
function createSubGridState(rows, columns, cells) {
|
|
1456
|
+
return {
|
|
1457
|
+
rows,
|
|
1458
|
+
columns,
|
|
1459
|
+
cells: filterGridStateCellsToAxes(cells, rows, columns),
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function assertGridStateCellsWithinAxes(cells, rows, columns, contextLabel) {
|
|
1463
|
+
const rowIds = new Set(rows.map((rowHead) => createGridIdKey(rowHead.id)));
|
|
1464
|
+
const columnIds = new Set(columns.map((columnHead) => createGridIdKey(columnHead.id)));
|
|
1465
|
+
cells.forEach((currentCell) => {
|
|
1466
|
+
if (!rowIds.has(createGridIdKey(currentCell.rowId))) {
|
|
1467
|
+
throw new Error(`${contextLabel} must reference an existing parent row header. Missing row "${formatGridId(currentCell.rowId)}".`);
|
|
1468
|
+
}
|
|
1469
|
+
if (!columnIds.has(createGridIdKey(currentCell.columnId))) {
|
|
1470
|
+
throw new Error(`${contextLabel} must reference an existing parent column header. Missing column "${formatGridId(currentCell.columnId)}".`);
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
return cells;
|
|
1474
|
+
}
|
|
1475
|
+
function filterGridStateCellsToAxes(cells, rows, columns) {
|
|
1476
|
+
const rowIds = new Set(rows.map((rowHead) => createGridIdKey(rowHead.id)));
|
|
1477
|
+
const columnIds = new Set(columns.map((columnHead) => createGridIdKey(columnHead.id)));
|
|
1478
|
+
return cells.filter((currentCell) => rowIds.has(createGridIdKey(currentCell.rowId)) &&
|
|
1479
|
+
columnIds.has(createGridIdKey(currentCell.columnId)));
|
|
1480
|
+
}
|
|
1481
|
+
function didGridDiffAffectAxes(diff) {
|
|
1482
|
+
return (!haveSameHeadSnapshots(diff.rows, diff.previousRows) ||
|
|
1483
|
+
!haveSameHeadSnapshots(diff.columns, diff.previousColumns));
|
|
1484
|
+
}
|
|
1485
|
+
function haveSameHeadSnapshots(leftHeads, rightHeads) {
|
|
1486
|
+
if (leftHeads === rightHeads) {
|
|
1487
|
+
return true;
|
|
1488
|
+
}
|
|
1489
|
+
if (!leftHeads || !rightHeads || leftHeads.length !== rightHeads.length) {
|
|
1490
|
+
return false;
|
|
1491
|
+
}
|
|
1492
|
+
return leftHeads.every((leftHead, index) => {
|
|
1493
|
+
const rightHead = rightHeads[index];
|
|
1494
|
+
if (leftHead === undefined || rightHead === undefined) {
|
|
1495
|
+
return leftHead === rightHead;
|
|
1496
|
+
}
|
|
1497
|
+
return haveSameShallowRecord(leftHead, rightHead);
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
function haveSameShallowRecord(leftRecord, rightRecord) {
|
|
1501
|
+
if (Object.is(leftRecord, rightRecord)) {
|
|
1502
|
+
return true;
|
|
1503
|
+
}
|
|
1504
|
+
const leftKeys = Object.keys(leftRecord);
|
|
1505
|
+
const rightKeys = Object.keys(rightRecord);
|
|
1506
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
1507
|
+
return false;
|
|
1508
|
+
}
|
|
1509
|
+
return leftKeys.every((key) => {
|
|
1510
|
+
if (!(key in rightRecord)) {
|
|
1511
|
+
return false;
|
|
1512
|
+
}
|
|
1513
|
+
const leftValue = leftRecord[key];
|
|
1514
|
+
const rightValue = rightRecord[key];
|
|
1515
|
+
if (isGridIdValue(leftValue) && isGridIdValue(rightValue)) {
|
|
1516
|
+
return createGridIdKey(leftValue) === createGridIdKey(rightValue);
|
|
1517
|
+
}
|
|
1518
|
+
return Object.is(leftValue, rightValue);
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
function isGridIdValue(value) {
|
|
1522
|
+
return (typeof value === "string" ||
|
|
1523
|
+
typeof value === "number" ||
|
|
1524
|
+
typeof value === "boolean" ||
|
|
1525
|
+
value instanceof Date);
|
|
1009
1526
|
}
|
|
1010
1527
|
//# sourceMappingURL=grid.js.map
|