@1771technologies/lytenyte-pro 1.0.1 → 1.0.3
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 +1 -6
- package/dist/+types.d.ts +24 -4
- package/dist/cell-selection/cell-selection-driver.js +2 -1
- package/dist/cell-selection/cell-style-row.d.ts +2 -2
- package/dist/cell-selection/cell-style-row.js +1 -1
- package/dist/cell-selection/get-root-cell.js +3 -83
- package/dist/cell-selection/index.d.ts +0 -1
- package/dist/cell-selection/index.js +0 -1
- package/dist/cell-selection/split-cell-selection-rect.d.ts +8 -1
- package/dist/cell-selection/split-cell-selection-rect.js +13 -4
- package/dist/cell-selection/split-on-pivot.d.ts +3 -0
- package/dist/cell-selection/split-on-pivot.js +50 -0
- package/dist/cells/cell-editor.js +1 -1
- package/dist/cells/cell-spacer.d.ts +3 -0
- package/dist/cells/cell-spacer.js +37 -0
- package/dist/cells/cell.d.ts +1 -3
- package/dist/cells/cell.js +11 -9
- package/dist/column-manager/branch.js +1 -1
- package/dist/column-manager/leaf.js +1 -1
- package/dist/column-manager/move-handle.d.ts +0 -7
- package/dist/column-manager/move-handle.js +23 -6
- package/dist/filter-tree/leaf.js +3 -1
- package/dist/grid-box/+types.d.ts +2 -2
- package/dist/grid-box/item.js +3 -3
- package/dist/grid-box/use-aggregation-box-items.js +1 -2
- package/dist/grid-box/use-column-box-items.d.ts +2 -3
- package/dist/grid-box/use-column-box-items.js +3 -3
- package/dist/grid-box/use-row-group-box-items.d.ts +3 -3
- package/dist/grid-box/use-row-group-box-items.js +41 -5
- package/dist/grid.d.ts +1 -1
- package/dist/header/resize-handler.js +21 -15
- package/dist/license.js +1 -1
- package/dist/row-data-source-client/use-client-data-source-paginated.js +154 -164
- package/dist/row-data-source-client/use-client-data-source.js +144 -177
- package/dist/row-data-source-client/use-client-tree-data-source.js +119 -152
- package/dist/row-data-source-server/use-server-data-source.js +102 -120
- package/dist/rows/row/row.d.ts +1 -1
- package/dist/rows/row/row.js +11 -4
- package/dist/rows/rows-sections.js +1 -1
- package/dist/sort-manager/+types.d.ts +2 -0
- package/dist/sort-manager/hooks/use-sort-row-item.js +6 -6
- package/dist/sort-manager/utils/sort-item-to-sort-model.js +5 -0
- package/dist/sort-manager/utils/sort-model-to-sort-items.js +2 -1
- package/dist/state/+types.d.ts +8 -10
- package/dist/state/api/cell-root.d.ts +5 -0
- package/dist/state/api/cell-root.js +64 -0
- package/dist/state/api/edit-begin.js +5 -9
- package/dist/state/api/edit-is-cell-active.d.ts +1 -1
- package/dist/state/api/edit-is-cell-active.js +2 -7
- package/dist/state/api/focus-cell.js +2 -2
- package/dist/state/helpers/column-layout.d.ts +3 -3
- package/dist/state/helpers/column-layout.js +9 -15
- package/dist/state/helpers/get-full-width-callback.d.ts +1 -1
- package/dist/state/helpers/get-full-width-callback.js +2 -0
- package/dist/state/helpers/get-span-callback.d.ts +1 -1
- package/dist/state/helpers/get-span-callback.js +2 -0
- package/dist/state/helpers/row-layout/row-layout.d.ts +5 -4
- package/dist/state/helpers/row-layout/row-layout.js +112 -346
- package/dist/state/use-lytenyte.js +398 -334
- package/dist/viewport/viewport.js +3 -2
- package/main.css +27 -3
- package/package.json +7 -7
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
import { atom, createStore } from "@1771technologies/atom";
|
|
2
1
|
import { useRef } from "react";
|
|
3
2
|
import { makeAsyncTree } from "./async-tree/make-async-tree.js";
|
|
4
|
-
import { makeGridAtom } from "@1771technologies/lytenyte-shared";
|
|
5
3
|
import { getNodeDepth } from "./utils/get-node-depth.js";
|
|
6
4
|
import { getRequestId } from "./utils/get-request-id.js";
|
|
7
5
|
import { RangeTree } from "./range-tree/range-tree.js";
|
|
8
6
|
import { getNodePath } from "./utils/get-node-path.js";
|
|
9
7
|
import { equal } from "@1771technologies/lytenyte-js-utils";
|
|
8
|
+
import { computed, effect, makeAtom, peek, signal } from "@1771technologies/lytenyte-shared";
|
|
10
9
|
export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, dataInFilterItemFetcher, cellUpdateHandler, cellUpdateOptimistically = true, blockSize = 200, }) {
|
|
11
10
|
let grid = null;
|
|
12
|
-
const snapshot$ =
|
|
13
|
-
const
|
|
14
|
-
const tree
|
|
15
|
-
const
|
|
16
|
-
const isLoading
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const model$ = atom({
|
|
11
|
+
const snapshot$ = signal(Date.now());
|
|
12
|
+
const tree$ = signal(makeAsyncTree());
|
|
13
|
+
const tree = makeAtom(tree$);
|
|
14
|
+
const isLoading$ = signal(false);
|
|
15
|
+
const isLoading = makeAtom(isLoading$);
|
|
16
|
+
const error$ = signal(null);
|
|
17
|
+
const loadError = makeAtom(error$);
|
|
18
|
+
const nodesWithError = signal(new Map());
|
|
19
|
+
const initialized = signal(false);
|
|
20
|
+
const model$ = signal({
|
|
23
21
|
sorts: [],
|
|
24
22
|
filters: {},
|
|
25
23
|
filtersIn: {},
|
|
@@ -38,12 +36,12 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
38
36
|
values: [],
|
|
39
37
|
},
|
|
40
38
|
});
|
|
41
|
-
const model =
|
|
42
|
-
const pivotGroupExpansions =
|
|
43
|
-
const rowGroupExpansions =
|
|
44
|
-
const pivotMode =
|
|
45
|
-
const topData =
|
|
46
|
-
const botData =
|
|
39
|
+
const model = makeAtom(model$);
|
|
40
|
+
const pivotGroupExpansions = computed(() => model$().pivotGroupExpansions);
|
|
41
|
+
const rowGroupExpansions = computed(() => model$().groupExpansions);
|
|
42
|
+
const pivotMode = computed(() => model$().pivotMode);
|
|
43
|
+
const topData = signal([]);
|
|
44
|
+
const botData = signal([]);
|
|
47
45
|
const seenRequests = new Set();
|
|
48
46
|
const dataResponseHandler = (res) => {
|
|
49
47
|
const t = tree.get();
|
|
@@ -56,10 +54,10 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
56
54
|
});
|
|
57
55
|
pinResponses.forEach((p) => {
|
|
58
56
|
if (p.kind === "top") {
|
|
59
|
-
|
|
57
|
+
topData.set(p.data);
|
|
60
58
|
}
|
|
61
59
|
else {
|
|
62
|
-
|
|
60
|
+
botData.set(p.data);
|
|
63
61
|
}
|
|
64
62
|
});
|
|
65
63
|
dataResponses.forEach((r) => {
|
|
@@ -96,7 +94,7 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
96
94
|
onSuccess?.();
|
|
97
95
|
return;
|
|
98
96
|
}
|
|
99
|
-
|
|
97
|
+
nodesWithError.set((prev) => {
|
|
100
98
|
const next = new Map(prev);
|
|
101
99
|
p.forEach((r) => {
|
|
102
100
|
for (let i = r.rowStartIndex; i < r.rowEndIndex; i++) {
|
|
@@ -122,7 +120,7 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
122
120
|
console.error(e);
|
|
123
121
|
}
|
|
124
122
|
finally {
|
|
125
|
-
|
|
123
|
+
snapshot$.set(Date.now());
|
|
126
124
|
grid.state.rowDataStore.rowClearCache();
|
|
127
125
|
}
|
|
128
126
|
};
|
|
@@ -177,7 +175,7 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
177
175
|
});
|
|
178
176
|
}
|
|
179
177
|
dataRequestHandler(requests, false, () => { }, (e) => {
|
|
180
|
-
|
|
178
|
+
nodesWithError.set((prev) => {
|
|
181
179
|
const next = new Map(prev);
|
|
182
180
|
requests.forEach((r) => {
|
|
183
181
|
for (let i = r.rowStartIndex; i < r.rowEndIndex; i++) {
|
|
@@ -191,7 +189,7 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
191
189
|
const resetRequest = async () => {
|
|
192
190
|
seenRequests.clear();
|
|
193
191
|
tree.set(makeAsyncTree());
|
|
194
|
-
|
|
192
|
+
nodesWithError.set(new Map());
|
|
195
193
|
// Initialize the grid.
|
|
196
194
|
const initialDataRequest = {
|
|
197
195
|
path: [],
|
|
@@ -208,11 +206,11 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
208
206
|
});
|
|
209
207
|
isLoading.set(false);
|
|
210
208
|
};
|
|
211
|
-
const flat$ =
|
|
212
|
-
|
|
213
|
-
const mode =
|
|
214
|
-
const expansions = mode ?
|
|
215
|
-
const t =
|
|
209
|
+
const flat$ = computed(() => {
|
|
210
|
+
snapshot$();
|
|
211
|
+
const mode = pivotMode();
|
|
212
|
+
const expansions = mode ? pivotGroupExpansions() : rowGroupExpansions();
|
|
213
|
+
const t = tree$();
|
|
216
214
|
const rowIdToRow = new Map();
|
|
217
215
|
const rowIndexToRow = new Map();
|
|
218
216
|
const rowIdToRowIndex = new Map();
|
|
@@ -244,7 +242,10 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
244
242
|
rangeTree,
|
|
245
243
|
};
|
|
246
244
|
});
|
|
247
|
-
const flat =
|
|
245
|
+
const flat = makeAtom(flat$);
|
|
246
|
+
const topLength = computed(() => topData().length);
|
|
247
|
+
const botLength = computed(() => botData().length);
|
|
248
|
+
const flatLength = computed(() => flat.$().size);
|
|
248
249
|
const cleanup = [];
|
|
249
250
|
const init = (g) => {
|
|
250
251
|
grid = g;
|
|
@@ -258,7 +259,7 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
258
259
|
const pivotMode = g.state.columnPivotMode.get();
|
|
259
260
|
const pivotModel = g.state.columnPivotModel.get();
|
|
260
261
|
const pivotGroupExpansions = g.state.columnPivotRowGroupExpansions.get();
|
|
261
|
-
|
|
262
|
+
model$.set({
|
|
262
263
|
sorts,
|
|
263
264
|
filters,
|
|
264
265
|
filtersIn,
|
|
@@ -270,25 +271,24 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
270
271
|
pivotModel,
|
|
271
272
|
pivotGroupExpansions,
|
|
272
273
|
});
|
|
273
|
-
|
|
274
|
+
initialized.set(true);
|
|
274
275
|
// Handle row count changes
|
|
275
276
|
const f = flat.get();
|
|
276
277
|
g.state.rowDataStore.rowCenterCount.set(f.size);
|
|
277
|
-
g.state.rowDataStore.rowBottomCount.set(
|
|
278
|
-
g.state.rowDataStore.rowTopCount.set(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
g.state.rowDataStore.rowCenterCount.set(f.size);
|
|
278
|
+
g.state.rowDataStore.rowBottomCount.set(peek(botData).length);
|
|
279
|
+
g.state.rowDataStore.rowTopCount.set(peek(topData).length);
|
|
280
|
+
cleanup.push(effect(() => {
|
|
281
|
+
g.state.rowDataStore.rowCenterCount.set(flatLength());
|
|
282
282
|
viewChange();
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
g.state.rowDataStore.rowTopCount.set(
|
|
283
|
+
}));
|
|
284
|
+
cleanup.push(effect(() => {
|
|
285
|
+
g.state.rowDataStore.rowTopCount.set(topLength());
|
|
286
286
|
g.state.rowDataStore.rowClearCache();
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
g.state.rowDataStore.rowBottomCount.set(
|
|
287
|
+
}));
|
|
288
|
+
cleanup.push(effect(() => {
|
|
289
|
+
g.state.rowDataStore.rowBottomCount.set(botLength);
|
|
290
290
|
g.state.rowDataStore.rowClearCache();
|
|
291
|
-
});
|
|
291
|
+
}));
|
|
292
292
|
resetRequest();
|
|
293
293
|
// Watch the view bound changes.
|
|
294
294
|
g.state.viewBounds.watch(() => {
|
|
@@ -314,78 +314,60 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
314
314
|
};
|
|
315
315
|
if (pivotMode)
|
|
316
316
|
updatePivotColumns(pivotModel);
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
g.state.
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
317
|
+
let prevModel = peek(model$);
|
|
318
|
+
effect(() => {
|
|
319
|
+
// @ts-expect-error this is fine
|
|
320
|
+
const rowGroupModel = g.state.rowGroupModel.$();
|
|
321
|
+
// @ts-expect-error this is fine
|
|
322
|
+
const rowGroupExpansions = g.state.rowGroupExpansions.$();
|
|
323
|
+
// @ts-expect-error this is fine
|
|
324
|
+
const aggModel = g.state.aggModel.$();
|
|
325
|
+
// @ts-expect-error this is fine
|
|
326
|
+
const filterModelIn = g.state.filterInModel.$();
|
|
327
|
+
// @ts-expect-error this is fine
|
|
328
|
+
const quickSearch = g.state.quickSearch.$();
|
|
329
|
+
// @ts-expect-error this is fine
|
|
330
|
+
const filterModel = g.state.filterModel.$();
|
|
331
|
+
// @ts-expect-error this is fine
|
|
332
|
+
const sortModel = g.state.sortModel.$();
|
|
333
|
+
// @ts-expect-error this is fine
|
|
334
|
+
const columnPivotExpansions = g.state.columnPivotColumnGroupExpansions.$();
|
|
335
|
+
// @ts-expect-error this is fine
|
|
336
|
+
const model = g.state.columnPivotModel.$();
|
|
337
|
+
// @ts-expect-error this is fine
|
|
338
|
+
const mode = g.state.columnPivotMode.$();
|
|
326
339
|
updatePivotColumns(model);
|
|
327
|
-
|
|
328
|
-
|
|
340
|
+
const newModel = {
|
|
341
|
+
aggregations: aggModel,
|
|
342
|
+
filters: filterModel,
|
|
343
|
+
filtersIn: filterModelIn,
|
|
344
|
+
group: rowGroupModel,
|
|
345
|
+
groupExpansions: rowGroupExpansions,
|
|
346
|
+
quickSearch,
|
|
347
|
+
pivotGroupExpansions: columnPivotExpansions,
|
|
348
|
+
pivotMode: mode,
|
|
329
349
|
pivotModel: model,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
columnPivotGroupExpansions: g.state.columnPivotRowGroupExpansions.get(),
|
|
337
|
-
}));
|
|
338
|
-
grid?.state.rowDataStore.rowClearCache();
|
|
339
|
-
});
|
|
340
|
-
// Sort model monitoring
|
|
341
|
-
cleanup.push(g.state.sortModel.watch(() => {
|
|
342
|
-
rdsStore.set(model$, (prev) => ({ ...prev, sorts: g.state.sortModel.get() }));
|
|
343
|
-
resetRequest();
|
|
344
|
-
}));
|
|
345
|
-
// Filter model monitoring
|
|
346
|
-
cleanup.push(g.state.filterModel.watch(() => {
|
|
347
|
-
rdsStore.set(model$, (prev) => ({ ...prev, filters: g.state.filterModel.get() }));
|
|
348
|
-
resetRequest();
|
|
349
|
-
}));
|
|
350
|
-
cleanup.push(g.state.quickSearch.watch(() => {
|
|
351
|
-
rdsStore.set(model$, (prev) => ({ ...prev, quickSearch: g.state.quickSearch.get() }));
|
|
352
|
-
resetRequest();
|
|
353
|
-
}));
|
|
354
|
-
cleanup.push(g.state.filterInModel.watch(() => {
|
|
355
|
-
rdsStore.set(model$, (prev) => ({ ...prev, filtersIn: g.state.filterInModel.get() }));
|
|
356
|
-
resetRequest();
|
|
357
|
-
}));
|
|
358
|
-
// Row group model monitoring
|
|
359
|
-
cleanup.push(g.state.rowGroupModel.watch(() => {
|
|
360
|
-
rdsStore.set(model$, (prev) => ({ ...prev, group: g.state.rowGroupModel.get() }));
|
|
361
|
-
resetRequest();
|
|
362
|
-
}));
|
|
363
|
-
// Row group expansions monitoring
|
|
364
|
-
cleanup.push(g.state.rowGroupExpansions.watch(() => {
|
|
365
|
-
rdsStore.set(model$, (prev) => ({
|
|
366
|
-
...prev,
|
|
367
|
-
groupExpansions: g.state.rowGroupExpansions.get(),
|
|
368
|
-
}));
|
|
369
|
-
grid?.state.rowDataStore.rowClearCache();
|
|
370
|
-
}));
|
|
371
|
-
// Agg model monitoring
|
|
372
|
-
cleanup.push(g.state.aggModel.watch(() => {
|
|
373
|
-
rdsStore.set(model$, (prev) => ({ ...prev, agg: g.state.aggModel.get() }));
|
|
350
|
+
sorts: sortModel,
|
|
351
|
+
};
|
|
352
|
+
if (equal(newModel, prevModel))
|
|
353
|
+
return;
|
|
354
|
+
prevModel = newModel;
|
|
355
|
+
model$.set(newModel);
|
|
374
356
|
resetRequest();
|
|
375
|
-
})
|
|
357
|
+
});
|
|
376
358
|
};
|
|
377
359
|
const rowById = (id) => {
|
|
378
360
|
const f = flat.get();
|
|
379
361
|
const node = f.rowIdToRow.get(id);
|
|
380
362
|
if (!node) {
|
|
381
363
|
{
|
|
382
|
-
const top =
|
|
364
|
+
const top = peek(topData);
|
|
383
365
|
const node = top.find((c) => c.id === id);
|
|
384
366
|
if (node)
|
|
385
367
|
return { kind: "leaf", data: node.data, id: node.id };
|
|
386
368
|
}
|
|
387
369
|
{
|
|
388
|
-
const bot =
|
|
370
|
+
const bot = peek(topData);
|
|
389
371
|
const node = bot.find((c) => c.id === id);
|
|
390
372
|
if (node)
|
|
391
373
|
return { kind: "leaf", data: node.data, id: node.id };
|
|
@@ -428,9 +410,9 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
428
410
|
};
|
|
429
411
|
const rowByIndex = (ri) => {
|
|
430
412
|
const f = flat.get();
|
|
431
|
-
const top =
|
|
432
|
-
const bot =
|
|
433
|
-
const errors =
|
|
413
|
+
const top = peek(topData);
|
|
414
|
+
const bot = peek(botData);
|
|
415
|
+
const errors = peek(nodesWithError);
|
|
434
416
|
const error = errors.get(ri);
|
|
435
417
|
if (ri == null || ri < 0 || ri >= f.size + top.length + bot.length)
|
|
436
418
|
return null;
|
|
@@ -453,7 +435,7 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
453
435
|
return { kind: "leaf", data: null, id: `error-${ri}`, loading: false, error };
|
|
454
436
|
if (!node)
|
|
455
437
|
return { kind: "leaf", data: null, id: `loading-${ri}`, loading: true, error: null };
|
|
456
|
-
const isLoading =
|
|
438
|
+
const isLoading = peek(loadingGroups$);
|
|
457
439
|
if (node.kind === "parent") {
|
|
458
440
|
return {
|
|
459
441
|
kind: "branch",
|
|
@@ -472,10 +454,10 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
472
454
|
error,
|
|
473
455
|
};
|
|
474
456
|
};
|
|
475
|
-
const loadingGroups$ =
|
|
457
|
+
const loadingGroups$ = signal(new Set());
|
|
476
458
|
const rowExpand = (p) => {
|
|
477
459
|
const f = flat.get();
|
|
478
|
-
const loadingRows = new Set(
|
|
460
|
+
const loadingRows = new Set(peek(loadingGroups$));
|
|
479
461
|
const rowsForThis = new Set();
|
|
480
462
|
const rowIndices = [];
|
|
481
463
|
const requests = Object.entries(p)
|
|
@@ -503,39 +485,39 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
503
485
|
};
|
|
504
486
|
})
|
|
505
487
|
.filter((c) => !!c);
|
|
506
|
-
const mode =
|
|
488
|
+
const mode = peek(pivotMode);
|
|
507
489
|
// Remove the errors before requesting.
|
|
508
|
-
const errorRows =
|
|
490
|
+
const errorRows = peek(nodesWithError);
|
|
509
491
|
if (rowIndices.some((c) => errorRows.has(c))) {
|
|
510
|
-
|
|
492
|
+
nodesWithError.set((prev) => {
|
|
511
493
|
const n = new Map(prev);
|
|
512
494
|
rowIndices.forEach((c) => n.delete(c));
|
|
513
495
|
return prev;
|
|
514
496
|
});
|
|
515
497
|
}
|
|
516
498
|
// Mark these groups as loading
|
|
517
|
-
|
|
499
|
+
loadingGroups$.set(loadingRows);
|
|
518
500
|
grid?.state.rowDataStore.rowClearCache();
|
|
519
501
|
dataRequestHandler(requests, false, () => {
|
|
520
502
|
if (mode)
|
|
521
503
|
grid?.state.columnPivotColumnGroupExpansions.set((prev) => ({ ...prev, ...p }));
|
|
522
504
|
else
|
|
523
505
|
grid?.state.rowGroupExpansions.set((prev) => ({ ...prev, ...p }));
|
|
524
|
-
const next = new Set(
|
|
506
|
+
const next = new Set(peek(loadingGroups$));
|
|
525
507
|
rowsForThis.forEach((c) => next.delete(c));
|
|
526
|
-
|
|
508
|
+
loadingGroups$.set(next);
|
|
527
509
|
setTimeout(() => {
|
|
528
510
|
grid?.state.rowDataStore.rowClearCache();
|
|
529
511
|
});
|
|
530
512
|
}, (error) => {
|
|
531
|
-
|
|
513
|
+
nodesWithError.set((prev) => {
|
|
532
514
|
const n = new Map(prev);
|
|
533
515
|
rowIndices.forEach((c) => n.set(c, error));
|
|
534
516
|
return prev;
|
|
535
517
|
});
|
|
536
|
-
const next = new Set(
|
|
518
|
+
const next = new Set(peek(loadingGroups$));
|
|
537
519
|
rowsForThis.forEach((c) => next.delete(c));
|
|
538
|
-
|
|
520
|
+
loadingGroups$.set(next);
|
|
539
521
|
setTimeout(() => {
|
|
540
522
|
grid?.state.rowDataStore.rowClearCache();
|
|
541
523
|
});
|
|
@@ -618,8 +600,8 @@ export function makeServerDataSource({ dataFetcher, dataColumnPivotFetcher, data
|
|
|
618
600
|
};
|
|
619
601
|
const rowUpdate = (updates) => {
|
|
620
602
|
const f = flat.get();
|
|
621
|
-
const top =
|
|
622
|
-
const bot =
|
|
603
|
+
const top = peek(topData);
|
|
604
|
+
const bot = peek(botData);
|
|
623
605
|
const firstBot = f.size + top.length;
|
|
624
606
|
const idMap = new Map([...updates.entries()]
|
|
625
607
|
.map(([key, data]) => {
|
package/dist/rows/row/row.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export interface RowProps extends Omit<DropWrapProps, "accepted"> {
|
|
|
4
4
|
readonly row: RowNormalRowLayout<any>;
|
|
5
5
|
readonly accepted?: string[];
|
|
6
6
|
}
|
|
7
|
-
export declare const Row: import("react").
|
|
7
|
+
export declare const Row: import("react").NamedExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "onDrag"> & RowProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
package/dist/rows/row/row.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef } from "react";
|
|
3
|
-
import { fastDeepMemo } from "@1771technologies/lytenyte-react-hooks";
|
|
2
|
+
import { forwardRef, memo } from "react";
|
|
4
3
|
import { useGridRoot } from "../../context";
|
|
5
4
|
import { RowDetailRow } from "../row-detail-row";
|
|
6
5
|
import { RowReact } from "@1771technologies/lytenyte-shared";
|
|
7
6
|
import { useRowContextValue } from "./use-row-context-value";
|
|
8
7
|
import { RowContext } from "./context";
|
|
8
|
+
import { equal } from "@1771technologies/lytenyte-js-utils";
|
|
9
|
+
import { CellSpacerNoPin } from "../../cells/cell-spacer";
|
|
9
10
|
const empty = [];
|
|
10
11
|
const RowImpl = forwardRef(function Rows({ row, ...props }, forwarded) {
|
|
11
12
|
const ctx = useGridRoot().grid;
|
|
12
13
|
const rowMeta = useRowContextValue(ctx, row.row);
|
|
13
14
|
const accepted = props.accepted ?? empty;
|
|
14
|
-
return (_jsx(RowContext.Provider, { value: rowMeta, children: _jsxs(RowReact, { ...props, ref: forwarded, accepted: accepted, gridId: ctx.state.gridId.useValue(), rowIndex: row.rowIndex, rowFirstPinBottom: row.rowFirstPinBottom, rowLastPinTop: row.rowLastPinTop, rowIsFocusRow: row.rowIsFocusRow ?? false, yPositions: ctx.state.yPositions.useValue(), "data-ln-row-selected": rowMeta.selected, children: [props.children, _jsx(RowDetailRow, { layout: row })] }) }));
|
|
15
|
+
return (_jsx(RowContext.Provider, { value: rowMeta, children: _jsxs(RowReact, { ...props, ref: forwarded, accepted: accepted, gridId: ctx.state.gridId.useValue(), rowIndex: row.rowIndex, rowFirstPinBottom: row.rowFirstPinBottom, rowLastPinTop: row.rowLastPinTop, rowIsFocusRow: row.rowIsFocusRow ?? false, yPositions: ctx.state.yPositions.useValue(), "data-ln-row-selected": rowMeta.selected, children: [_jsx(CellSpacerNoPin, {}), props.children, _jsx(RowDetailRow, { layout: row })] }) }));
|
|
16
|
+
});
|
|
17
|
+
export const Row = memo(RowImpl, (prev, next) => {
|
|
18
|
+
const { row: rowP, ...propsP } = prev;
|
|
19
|
+
const { row: rowN, ...propsN } = next;
|
|
20
|
+
const { cells: _, ...rowPropsP } = rowP;
|
|
21
|
+
const { cells: __, ...rowPropsN } = rowN;
|
|
22
|
+
return equal(rowPropsN, rowPropsP) && equal(propsP, propsN);
|
|
15
23
|
});
|
|
16
|
-
export const Row = fastDeepMemo(RowImpl);
|
|
@@ -15,7 +15,7 @@ export const RowsCenter = fastDeepMemo(forwardRef(function RowsCenter({ children
|
|
|
15
15
|
const cx = useGridRoot().grid;
|
|
16
16
|
const view = cx.view.useValue().rows;
|
|
17
17
|
const rowCenterCount = cx.state.rowDataStore.rowCenterCount.useValue();
|
|
18
|
-
return (_jsx(RowsCenterReact, { ...props, ref: forwarded, rowFirst: cx.state.rowDataStore.rowTopCount.useValue(), rowLast: rowCenterCount + cx.state.rowDataStore.rowTopCount.useValue(), height: view.rowCenterTotalHeight, children: _jsxs(NativeScroller, { children: [_jsx(CellSelectionCenter, {}), children] }) }));
|
|
18
|
+
return (_jsx(RowsCenterReact, { ...props, ref: forwarded, rowFirst: cx.state.rowDataStore.rowTopCount.useValue(), rowLast: rowCenterCount + cx.state.rowDataStore.rowTopCount.useValue(), height: view.rowCenterTotalHeight, pinSectionHeights: view.rowBottomTotalHeight + view.rowTopTotalHeight, children: _jsxs(NativeScroller, { children: [_jsx(CellSelectionCenter, {}), children] }) }));
|
|
19
19
|
}));
|
|
20
20
|
export const RowsBottom = fastDeepMemo(forwardRef(function RowsBottom(props, forwarded) {
|
|
21
21
|
const cx = useGridRoot().grid;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { SortModelItem } from "../+types";
|
|
1
2
|
export interface SortItem {
|
|
2
3
|
readonly isCustom: boolean;
|
|
3
4
|
readonly columnId?: string;
|
|
4
5
|
readonly label?: string;
|
|
5
6
|
readonly sortOn?: "values" | "values_absolute" | "values_accented" | "values_nulls_first" | "values_absolute_nulls_first" | "values_accented_nulls_first" | "values_absolute_accented_nulls_first";
|
|
6
7
|
readonly sortDirection: "ascending" | "descending";
|
|
8
|
+
readonly originalSort?: SortModelItem<any>;
|
|
7
9
|
}
|
|
8
10
|
export interface Option {
|
|
9
11
|
readonly label: string;
|
|
@@ -118,11 +118,11 @@ const sortValuesForDateAndDateTime = [
|
|
|
118
118
|
const sortValuesString = [
|
|
119
119
|
{ label: "Values", value: "values" },
|
|
120
120
|
{ label: "Insensitive", value: "values_insensitive" },
|
|
121
|
-
{ label: "Insensitive, Ignore Punctuation", value: "
|
|
122
|
-
{ label: "Insensitive, Trim", value: "
|
|
123
|
-
{ label: "Insensitive, Ignore Punctuation, Trim", value: "
|
|
124
|
-
{ label: "Ignore Punctuation", value: "
|
|
125
|
-
{ label: "Ignore Punctuation, Trim", value: "
|
|
121
|
+
{ label: "Insensitive, Ignore Punctuation", value: "values_insensitive_ignore" },
|
|
122
|
+
{ label: "Insensitive, Trim", value: "values_insensitive_trim" },
|
|
123
|
+
{ label: "Insensitive, Ignore Punctuation, Trim", value: "values_insensitive_ignore_trim" },
|
|
124
|
+
{ label: "Ignore Punctuation", value: "values_ignore" },
|
|
125
|
+
{ label: "Ignore Punctuation, Trim", value: "values_ignore_trim" },
|
|
126
126
|
{ label: "Trim Whitespace", value: "values_trim" },
|
|
127
127
|
{ label: "Nulls First", value: "values_nulls_first" },
|
|
128
128
|
{ label: "Nulls First, Insensitive", value: "values_nulls_first_insensitive" },
|
|
@@ -131,7 +131,7 @@ const sortValuesString = [
|
|
|
131
131
|
{ label: "Nulls First, Insensitive, Trim", value: "values_nulls_first_insensitive_trim" },
|
|
132
132
|
{
|
|
133
133
|
label: "Nulls First, Insensitive, Ignore Punctuation",
|
|
134
|
-
value: "
|
|
134
|
+
value: "values_nulls_first_insensitive_ignore",
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
137
|
label: "Nulls First, Insensitive, Ignore Punctuation, Trim",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export function sortItemsToSortModel(sortItems, lookup) {
|
|
2
2
|
return sortItems
|
|
3
3
|
.filter((c) => {
|
|
4
|
+
if (c.isCustom)
|
|
5
|
+
return true;
|
|
4
6
|
if (!c.columnId)
|
|
5
7
|
return false;
|
|
6
8
|
if (!c.sortOn)
|
|
@@ -11,6 +13,9 @@ export function sortItemsToSortModel(sortItems, lookup) {
|
|
|
11
13
|
})
|
|
12
14
|
.map((c) => {
|
|
13
15
|
const col = lookup.get(c.columnId);
|
|
16
|
+
if (c.isCustom) {
|
|
17
|
+
return c.originalSort;
|
|
18
|
+
}
|
|
14
19
|
if (col.type === "number") {
|
|
15
20
|
return {
|
|
16
21
|
columnId: col.id,
|
|
@@ -8,6 +8,7 @@ export function sortModelToSortItems(items, lookup) {
|
|
|
8
8
|
isCustom: true,
|
|
9
9
|
sortDirection,
|
|
10
10
|
columnId: c.columnId ?? undefined,
|
|
11
|
+
originalSort: c,
|
|
11
12
|
};
|
|
12
13
|
}
|
|
13
14
|
const column = lookup.get(columnId);
|
|
@@ -23,7 +24,7 @@ export function sortModelToSortItems(items, lookup) {
|
|
|
23
24
|
if (opts?.ignorePunctuation)
|
|
24
25
|
value += "_ignore";
|
|
25
26
|
if (opts?.trimWhitespace)
|
|
26
|
-
value += "
|
|
27
|
+
value += "_trim";
|
|
27
28
|
}
|
|
28
29
|
if (c.sort.kind === "number") {
|
|
29
30
|
const opts = c.sort.options;
|
package/dist/state/+types.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Column,
|
|
3
|
-
import type {
|
|
1
|
+
import type { LayoutState, WriteSignal } from "@1771technologies/lytenyte-shared";
|
|
2
|
+
import type { Column, EditActivePosition, GridAtom, GridAtomReadonly, HeaderGroupCellLayout, PositionUnion, VirtualTarget } from "../+types";
|
|
3
|
+
import type { DataRectSplit } from "../cell-selection/split-cell-selection-rect";
|
|
4
4
|
export interface InternalAtoms {
|
|
5
5
|
readonly headerRows: GridAtomReadonly<number>;
|
|
6
6
|
readonly headerCols: GridAtomReadonly<number>;
|
|
7
7
|
readonly headerHeightTotal: GridAtomReadonly<number>;
|
|
8
8
|
readonly xScroll: GridAtom<number>;
|
|
9
9
|
readonly yScroll: GridAtom<number>;
|
|
10
|
-
readonly
|
|
11
|
-
readonly layout: GridAtomReadonly<LayoutMap>;
|
|
10
|
+
readonly layout: LayoutState;
|
|
12
11
|
readonly focusActive: GridAtom<PositionUnion | null>;
|
|
13
12
|
readonly focusPrevColIndex: GridAtom<number | null>;
|
|
14
13
|
readonly focusPrevRowIndex: GridAtom<number | null>;
|
|
@@ -17,7 +16,7 @@ export interface InternalAtoms {
|
|
|
17
16
|
readonly editValidation: GridAtom<Record<string, any> | boolean>;
|
|
18
17
|
readonly rowAutoHeightCache: GridAtom<Record<number, number>>;
|
|
19
18
|
readonly rowDetailAutoHeightCache: GridAtom<Record<number, number>>;
|
|
20
|
-
readonly rowSelectedIds:
|
|
19
|
+
readonly rowSelectedIds: WriteSignal<Set<string>>;
|
|
21
20
|
readonly rowSelectionPivot: GridAtom<string | null>;
|
|
22
21
|
readonly rowSelectionLastWasDeselect: GridAtom<boolean>;
|
|
23
22
|
readonly rowGroupColumnState: GridAtom<Record<string, Partial<Column<any>>>>;
|
|
@@ -27,9 +26,8 @@ export interface InternalAtoms {
|
|
|
27
26
|
target: HTMLElement | VirtualTarget;
|
|
28
27
|
context: any;
|
|
29
28
|
}>>;
|
|
30
|
-
readonly cellSelectionPivot: GridAtom<
|
|
31
|
-
readonly cellSelectionAdditiveRects: GridAtom<
|
|
29
|
+
readonly cellSelectionPivot: GridAtom<DataRectSplit | null>;
|
|
30
|
+
readonly cellSelectionAdditiveRects: GridAtom<DataRectSplit[] | null>;
|
|
32
31
|
readonly cellSelectionIsDeselect: GridAtom<boolean>;
|
|
33
|
-
readonly cellSelectionSplits: GridAtomReadonly<
|
|
34
|
-
readonly store: ReturnType<typeof createStore>;
|
|
32
|
+
readonly cellSelectionSplits: GridAtomReadonly<DataRectSplit[]>;
|
|
35
33
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CONTAINS_DEAD_CELLS, FULL_WIDTH, updateLayout } from "@1771technologies/lytenyte-shared";
|
|
2
|
+
import { getSpanFn } from "../helpers/get-span-callback";
|
|
3
|
+
import { getFullWidthCallback } from "../helpers/get-full-width-callback";
|
|
4
|
+
export const makeCellRoot = (grid) => {
|
|
5
|
+
return (row, column) => {
|
|
6
|
+
const l = grid.internal.layout;
|
|
7
|
+
const meta = grid.state.columnMeta.get();
|
|
8
|
+
const ds = grid.state.rowDataStore;
|
|
9
|
+
// Is this a valid position.
|
|
10
|
+
if (row < 0 || row >= ds.rowCount.get())
|
|
11
|
+
return null;
|
|
12
|
+
if (column < 0 || column >= meta.columnsVisible.length)
|
|
13
|
+
return null;
|
|
14
|
+
const rds = grid.state.rowDataSource.get();
|
|
15
|
+
const columns = meta.columnsVisible;
|
|
16
|
+
const rowFullWidthPredicate = grid.state.rowFullWidthPredicate.get();
|
|
17
|
+
if (!l.computed[row]) {
|
|
18
|
+
updateLayout({
|
|
19
|
+
base: l.base,
|
|
20
|
+
computed: l.computed,
|
|
21
|
+
lookup: l.lookup,
|
|
22
|
+
special: l.special,
|
|
23
|
+
botCount: ds.rowBottomCount.get(),
|
|
24
|
+
topCount: ds.rowTopCount.get(),
|
|
25
|
+
startCount: meta.columnVisibleStartCount,
|
|
26
|
+
centerCount: meta.columnVisibleCenterCount,
|
|
27
|
+
endCount: meta.columnVisibleEndCount,
|
|
28
|
+
computeColSpan: getSpanFn(rds, grid, columns, "col"),
|
|
29
|
+
computeRowSpan: getSpanFn(rds, grid, columns, "row"),
|
|
30
|
+
isFullWidth: getFullWidthCallback(rds, rowFullWidthPredicate.fn, grid),
|
|
31
|
+
isRowCutoff: (r) => {
|
|
32
|
+
const row = rds.rowByIndex(r);
|
|
33
|
+
return !row || row.kind === "branch";
|
|
34
|
+
},
|
|
35
|
+
rowStart: row,
|
|
36
|
+
rowEnd: row + 1,
|
|
37
|
+
rowMax: ds.rowCenterCount.get() + ds.rowTopCount.get(),
|
|
38
|
+
rowScanDistance: grid.state.rowScanDistance.get(),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const status = l.special[row];
|
|
42
|
+
if (status === FULL_WIDTH) {
|
|
43
|
+
return { kind: "full-width", rowIndex: row, colIndex: 0 };
|
|
44
|
+
}
|
|
45
|
+
if (status === CONTAINS_DEAD_CELLS) {
|
|
46
|
+
const spec = l.lookup.get(row);
|
|
47
|
+
// This cell is not covered
|
|
48
|
+
if (!spec || spec[column * 4] !== 0) {
|
|
49
|
+
return { kind: "cell", rowIndex: row, colIndex: column, root: null };
|
|
50
|
+
}
|
|
51
|
+
const rowSpan = spec[column * 4];
|
|
52
|
+
const colSpan = spec[column * 4 + 1];
|
|
53
|
+
const rowIndex = spec[column * 4 + 2];
|
|
54
|
+
const colIndex = spec[column * 4 + 3];
|
|
55
|
+
return {
|
|
56
|
+
kind: "cell",
|
|
57
|
+
rowIndex: row,
|
|
58
|
+
colIndex: column,
|
|
59
|
+
root: { colIndex, colSpan, rowIndex, rowSpan },
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { kind: "cell", rowIndex: row, colIndex: column, root: null };
|
|
63
|
+
};
|
|
64
|
+
};
|