@xnetjs/react 2.0.0 → 2.1.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/index.d.ts +16 -1
- package/dist/index.js +58 -35
- package/package.json +10 -10
package/dist/index.d.ts
CHANGED
|
@@ -581,8 +581,15 @@ interface UseGridDatabaseOptions {
|
|
|
581
581
|
viewId?: string;
|
|
582
582
|
/** Quick-find text (full-text search via SQLite FTS) */
|
|
583
583
|
search?: string;
|
|
584
|
-
/**
|
|
584
|
+
/** Rows fetched per window grow (default 500) */
|
|
585
585
|
pageSize?: number;
|
|
586
|
+
/**
|
|
587
|
+
* Ceiling on the live row window (default 2000). The window grows by
|
|
588
|
+
* `pageSize` via `fetchMoreRows` until this bound; beyond it further
|
|
589
|
+
* fetches are no-ops so the overfetch buffer and live snapshot stay
|
|
590
|
+
* bounded (exploration 0340).
|
|
591
|
+
*/
|
|
592
|
+
maxLoaded?: number;
|
|
586
593
|
}
|
|
587
594
|
interface UseGridDatabaseResult {
|
|
588
595
|
/** Database node (flattened) */
|
|
@@ -601,6 +608,14 @@ interface UseGridDatabaseResult {
|
|
|
601
608
|
/** Rows: view filters + sorts applied to the fetched window */
|
|
602
609
|
rows: GridRowModel[];
|
|
603
610
|
loading: boolean;
|
|
611
|
+
/** Exact matching row count for the whole database (null while unknown). */
|
|
612
|
+
totalRowCount: number | null;
|
|
613
|
+
/** Whether the row window can grow further (more rows exist past it). */
|
|
614
|
+
hasMoreRows: boolean;
|
|
615
|
+
/** Whether a window grow is awaiting the larger read. */
|
|
616
|
+
isFetchingMoreRows: boolean;
|
|
617
|
+
/** Grow the row window by `pageSize` (bounded by `maxLoaded`). */
|
|
618
|
+
fetchMoreRows: () => Promise<void>;
|
|
604
619
|
updateCell: (rowId: string, fieldId: string, value: CellValue) => Promise<void>;
|
|
605
620
|
clearCells: (cells: Array<{
|
|
606
621
|
rowId: string;
|
package/dist/index.js
CHANGED
|
@@ -4377,7 +4377,7 @@ function dropSortKey(ordered, movedId, targetIndex) {
|
|
|
4377
4377
|
}
|
|
4378
4378
|
var formulaService = new FormulaService();
|
|
4379
4379
|
function useGridDatabase(databaseId, options = {}) {
|
|
4380
|
-
const { viewId, search, pageSize = 500 } = options;
|
|
4380
|
+
const { viewId, search, pageSize = 500, maxLoaded = 2e3 } = options;
|
|
4381
4381
|
const mutate = useMutate();
|
|
4382
4382
|
const { did } = useIdentity();
|
|
4383
4383
|
const { data: database, status: dbStatus } = useQuery(DatabaseSchema, databaseId);
|
|
@@ -4393,10 +4393,22 @@ function useGridDatabase(databaseId, options = {}) {
|
|
|
4393
4393
|
where: { database: databaseId },
|
|
4394
4394
|
orderBy: { sortKey: "asc" }
|
|
4395
4395
|
});
|
|
4396
|
-
const {
|
|
4396
|
+
const {
|
|
4397
|
+
data: rowNodes,
|
|
4398
|
+
// Masked while a window grow is in flight (previous rows stay visible):
|
|
4399
|
+
// consumers must not fall back to a skeleton mid-grow or scroll position
|
|
4400
|
+
// is lost — `isFetchingMoreRows` reports the in-flight grow instead.
|
|
4401
|
+
loading: rowsLoading,
|
|
4402
|
+
totalCount: totalRowCount,
|
|
4403
|
+
hasMore: hasMoreRows,
|
|
4404
|
+
isFetchingNextPage: isFetchingMoreRows,
|
|
4405
|
+
fetchNextPage: fetchMoreRows
|
|
4406
|
+
} = useInfiniteQuery(DatabaseRowSchema, {
|
|
4397
4407
|
where: { database: databaseId },
|
|
4398
4408
|
orderBy: { sortKey: "asc" },
|
|
4399
|
-
|
|
4409
|
+
pageSize,
|
|
4410
|
+
maxLoaded,
|
|
4411
|
+
page: { count: "exact" },
|
|
4400
4412
|
materializedView: `db:${databaseId}${viewId ? `:view:${viewId}` : ""}`,
|
|
4401
4413
|
...search ? { search } : {}
|
|
4402
4414
|
});
|
|
@@ -4484,11 +4496,22 @@ function useGridDatabase(databaseId, options = {}) {
|
|
|
4484
4496
|
cancelled = true;
|
|
4485
4497
|
};
|
|
4486
4498
|
}, [rowNodes, fields, store]);
|
|
4499
|
+
const rowModelCacheRef = useRef4(
|
|
4500
|
+
{ deps: [], map: /* @__PURE__ */ new WeakMap() }
|
|
4501
|
+
);
|
|
4487
4502
|
const rows = useMemo5(() => {
|
|
4503
|
+
const cacheDeps = [fields, rollupValues, databaseId];
|
|
4504
|
+
if (cacheDeps.length !== rowModelCacheRef.current.deps.length || cacheDeps.some((d, i) => d !== rowModelCacheRef.current.deps[i])) {
|
|
4505
|
+
rowModelCacheRef.current = { deps: cacheDeps, map: /* @__PURE__ */ new WeakMap() };
|
|
4506
|
+
}
|
|
4507
|
+
const cache = rowModelCacheRef.current.map;
|
|
4488
4508
|
const autoFields = fields.filter(
|
|
4489
4509
|
(f) => ["created", "createdBy", "updated", "updatedBy"].includes(f.type)
|
|
4490
4510
|
);
|
|
4491
|
-
const
|
|
4511
|
+
const formulaFields = fields.filter((f) => f.type === "formula");
|
|
4512
|
+
const rollupFields = fields.filter((f) => f.type === "rollup");
|
|
4513
|
+
const columnDefs = formulaFields.length > 0 || activeView ? fieldsToColumnDefinitions(fields) : [];
|
|
4514
|
+
const buildRow = (node) => {
|
|
4492
4515
|
const cells = fromCellProperties(node);
|
|
4493
4516
|
for (const field of autoFields) {
|
|
4494
4517
|
switch (field.type) {
|
|
@@ -4506,47 +4529,43 @@ function useGridDatabase(databaseId, options = {}) {
|
|
|
4506
4529
|
break;
|
|
4507
4530
|
}
|
|
4508
4531
|
}
|
|
4509
|
-
|
|
4532
|
+
const row = {
|
|
4510
4533
|
id: node.id,
|
|
4511
4534
|
sortKey: node.sortKey ?? "",
|
|
4512
4535
|
cells
|
|
4513
4536
|
};
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
columnDef,
|
|
4526
|
-
columnDefs
|
|
4527
|
-
);
|
|
4528
|
-
} catch {
|
|
4529
|
-
row.cells[field.id] = null;
|
|
4530
|
-
}
|
|
4537
|
+
for (const field of formulaFields) {
|
|
4538
|
+
const columnDef = columnDefs.find((c) => c.id === field.id);
|
|
4539
|
+
if (!columnDef) continue;
|
|
4540
|
+
try {
|
|
4541
|
+
row.cells[field.id] = formulaService.compute(
|
|
4542
|
+
{ id: row.id, databaseId, cells: row.cells },
|
|
4543
|
+
columnDef,
|
|
4544
|
+
columnDefs
|
|
4545
|
+
);
|
|
4546
|
+
} catch {
|
|
4547
|
+
row.cells[field.id] = null;
|
|
4531
4548
|
}
|
|
4532
4549
|
}
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
for (const field of fields) {
|
|
4537
|
-
if (field.type !== "rollup") continue;
|
|
4538
|
-
const computed = rollupValues.get(`${row.id}:${field.id}`);
|
|
4539
|
-
if (computed !== void 0) row.cells[field.id] = computed;
|
|
4540
|
-
}
|
|
4550
|
+
for (const field of rollupFields) {
|
|
4551
|
+
const computed = rollupValues.get(`${row.id}:${field.id}`);
|
|
4552
|
+
if (computed !== void 0) row.cells[field.id] = computed;
|
|
4541
4553
|
}
|
|
4542
|
-
|
|
4554
|
+
return row;
|
|
4555
|
+
};
|
|
4556
|
+
const base = (rowNodes ?? []).map((node) => {
|
|
4557
|
+
const hit = cache.get(node);
|
|
4558
|
+
if (hit) return hit;
|
|
4559
|
+
const row = buildRow(node);
|
|
4560
|
+
cache.set(node, row);
|
|
4561
|
+
return row;
|
|
4562
|
+
});
|
|
4543
4563
|
base.sort((a, b) => compareSortKeys(a.sortKey, b.sortKey));
|
|
4544
4564
|
if (!activeView) return base;
|
|
4545
|
-
const
|
|
4546
|
-
|
|
4547
|
-
return sortRows(filtered, columns, activeView.sorts);
|
|
4565
|
+
const filtered = filterRows(base, columnDefs, activeView.filters);
|
|
4566
|
+
return sortRows(filtered, columnDefs, activeView.sorts);
|
|
4548
4567
|
}, [rowNodes, activeView, fields, databaseId, rollupValues]);
|
|
4549
|
-
const loading = dbStatus === "loading" || fieldStatus === "loading" || viewStatus === "loading" ||
|
|
4568
|
+
const loading = dbStatus === "loading" || fieldStatus === "loading" || viewStatus === "loading" || rowsLoading;
|
|
4550
4569
|
const rowTailRef = useRef4(void 0);
|
|
4551
4570
|
const fieldTailRef = useRef4(void 0);
|
|
4552
4571
|
const viewTailRef = useRef4(void 0);
|
|
@@ -4899,6 +4918,10 @@ function useGridDatabase(databaseId, options = {}) {
|
|
|
4899
4918
|
activeView,
|
|
4900
4919
|
rows,
|
|
4901
4920
|
loading,
|
|
4921
|
+
totalRowCount,
|
|
4922
|
+
hasMoreRows,
|
|
4923
|
+
isFetchingMoreRows,
|
|
4924
|
+
fetchMoreRows,
|
|
4902
4925
|
updateCell,
|
|
4903
4926
|
clearCells,
|
|
4904
4927
|
addRow,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xnetjs/react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,15 +46,15 @@
|
|
|
46
46
|
"y-protocols": "^1.0.6",
|
|
47
47
|
"yjs": "^13.6.24",
|
|
48
48
|
"@xnetjs/billing": "0.0.2",
|
|
49
|
-
"@xnetjs/core": "2.
|
|
50
|
-
"@xnetjs/crypto": "2.
|
|
51
|
-
"@xnetjs/data": "2.
|
|
52
|
-
"@xnetjs/data-bridge": "2.
|
|
53
|
-
"@xnetjs/history": "2.
|
|
54
|
-
"@xnetjs/identity": "2.
|
|
55
|
-
"@xnetjs/plugins": "2.
|
|
56
|
-
"@xnetjs/runtime": "0.5.
|
|
57
|
-
"@xnetjs/sync": "2.
|
|
49
|
+
"@xnetjs/core": "2.1.0",
|
|
50
|
+
"@xnetjs/crypto": "2.1.0",
|
|
51
|
+
"@xnetjs/data": "2.1.0",
|
|
52
|
+
"@xnetjs/data-bridge": "2.1.0",
|
|
53
|
+
"@xnetjs/history": "2.1.0",
|
|
54
|
+
"@xnetjs/identity": "2.1.0",
|
|
55
|
+
"@xnetjs/plugins": "2.1.0",
|
|
56
|
+
"@xnetjs/runtime": "0.5.1",
|
|
57
|
+
"@xnetjs/sync": "2.1.0"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"react": "^18.0.0 || ^19.0.0"
|