@1771technologies/lytenyte-pro 1.0.9 → 1.0.10
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/+types.d.ts +1 -1
- package/dist/license.d.ts +1 -0
- package/dist/license.js +10 -13
- package/dist/root/root.js +7 -2
- package/dist/row-data-source-server/async-tree/maybe-apply-set-action-items.js +5 -4
- package/dist/row-data-source-server/range-tree/range-tree.d.ts +1 -1
- package/dist/row-data-source-server/server-data.d.ts +48 -0
- package/dist/row-data-source-server/server-data.js +378 -0
- package/dist/row-data-source-server/use-server-data-source.d.ts +1 -1
- package/dist/row-data-source-server/use-server-data-source.js +181 -524
- package/dist/row-data-source-server/utils/get-node-depth.d.ts +1 -1
- package/dist/row-data-source-server/utils/get-node-path.d.ts +1 -1
- package/package.json +7 -7
package/dist/+types.d.ts
CHANGED
|
@@ -5679,7 +5679,7 @@ export interface DataRequestModel<T> {
|
|
|
5679
5679
|
/**
|
|
5680
5680
|
* Group model defining how rows are grouped.
|
|
5681
5681
|
*/
|
|
5682
|
-
readonly
|
|
5682
|
+
readonly groups: RowGroupModelItem<T>[];
|
|
5683
5683
|
/**
|
|
5684
5684
|
* Expansion state of row groups by group key.
|
|
5685
5685
|
*/
|
package/dist/license.d.ts
CHANGED
package/dist/license.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const hashSalt = "faec0f3c45281b1fe12d87e64a6c3271";
|
|
2
|
-
const issueDate = new Date("2025-09-
|
|
2
|
+
const issueDate = new Date("2025-09-11");
|
|
3
3
|
function getHostname() {
|
|
4
4
|
const win = globalThis?.document?.defaultView || (typeof window !== "undefined" ? window : null);
|
|
5
5
|
const loc = win?.location;
|
|
@@ -15,6 +15,7 @@ function isLocalhost() {
|
|
|
15
15
|
return hostname.match(/^(?:127\.0\.0\.1|localhost)$/) !== null;
|
|
16
16
|
}
|
|
17
17
|
export let hasAValidLicense = isWebsiteUrl() || isLocalhost();
|
|
18
|
+
export let licenseState = null;
|
|
18
19
|
export function activateLicense(license) {
|
|
19
20
|
const parts = license.split("|");
|
|
20
21
|
const details = parts[0];
|
|
@@ -23,16 +24,14 @@ export function activateLicense(license) {
|
|
|
23
24
|
if (detailHash !== hash) {
|
|
24
25
|
console.error(`
|
|
25
26
|
********************************************************************************
|
|
26
|
-
|
|
27
|
+
LyteNyte Grid PRO
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
purchased a valid license from 1771 Technologies, please reach out to
|
|
30
|
-
our dedicated support email support@1771technologies.com.
|
|
29
|
+
Invalid license key. Please verify the key and try again.
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
visit https://1771technolgies.com
|
|
31
|
+
Visit https://1771technolgies.com for more information.
|
|
34
32
|
********************************************************************************
|
|
35
33
|
`);
|
|
34
|
+
licenseState = "invalid";
|
|
36
35
|
return false;
|
|
37
36
|
}
|
|
38
37
|
const detailParts = details.split(" ");
|
|
@@ -40,16 +39,14 @@ export function activateLicense(license) {
|
|
|
40
39
|
if (issueDate > endDate) {
|
|
41
40
|
console.error(`
|
|
42
41
|
********************************************************************************
|
|
43
|
-
|
|
42
|
+
LyteNyte Grid PRO
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
current version of LyteNyte Grid being used. Please renew your license or use
|
|
47
|
-
the fallback version valid under your license.
|
|
44
|
+
License key expired. Your license covers earlier versions only.
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
for please visit https://1771technologies.com.
|
|
46
|
+
Visit https://1771technolgies.com for more information.
|
|
51
47
|
********************************************************************************
|
|
52
48
|
`);
|
|
49
|
+
licenseState = "expired";
|
|
53
50
|
return false;
|
|
54
51
|
}
|
|
55
52
|
hasAValidLicense = true;
|
package/dist/root/root.js
CHANGED
|
@@ -5,7 +5,7 @@ import { RootProvider } from "../context.js";
|
|
|
5
5
|
import { DialogDriver } from "./dialog-driver.js";
|
|
6
6
|
import { PopoverDriver } from "./popover-driver.js";
|
|
7
7
|
import { CellSelectionDriver } from "../cell-selection/cell-selection-driver.js";
|
|
8
|
-
import { hasAValidLicense } from "../license.js";
|
|
8
|
+
import { hasAValidLicense, licenseState } from "../license.js";
|
|
9
9
|
export function Root({ grid, children, ...events }) {
|
|
10
10
|
useEffect(() => {
|
|
11
11
|
if (hasAValidLicense)
|
|
@@ -23,7 +23,12 @@ export function Root({ grid, children, ...events }) {
|
|
|
23
23
|
invalidLicenseWatermark.style.fontWeight = "bold";
|
|
24
24
|
invalidLicenseWatermark.style.border = "1px solid black";
|
|
25
25
|
invalidLicenseWatermark.style.padding = "16px";
|
|
26
|
-
|
|
26
|
+
if (licenseState === "expired")
|
|
27
|
+
invalidLicenseWatermark.innerHTML = `LyteNyte Grid: License key expired. Your license covers earlier versions only.`;
|
|
28
|
+
else if (licenseState === "invalid")
|
|
29
|
+
invalidLicenseWatermark.innerHTML = `LyteNyte Grid: Invalid license key. Please verify the key and try again.`;
|
|
30
|
+
else
|
|
31
|
+
invalidLicenseWatermark.innerHTML = `LyteNyte Grid PRO is being used for evaluation.
|
|
27
32
|
<a href="https://1771Technologies.com/pricing">Click here</a> to secure your license.`;
|
|
28
33
|
document.body.appendChild(invalidLicenseWatermark);
|
|
29
34
|
return () => invalidLicenseWatermark.remove();
|
|
@@ -12,11 +12,12 @@ export function maybeApplySetActionItems(p, pathNode) {
|
|
|
12
12
|
pathNode.byPath.delete(existingIndex.path);
|
|
13
13
|
pathNode.byIndex.delete(item.relIndex);
|
|
14
14
|
}
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
17
|
-
pathNode.byPath.delete(
|
|
18
|
-
pathNode.byIndex.delete(
|
|
15
|
+
const existingByPath = pathNode.byPath.get(path);
|
|
16
|
+
if (existingByPath) {
|
|
17
|
+
pathNode.byPath.delete(existingByPath.path);
|
|
18
|
+
pathNode.byIndex.delete(existingByPath.relIndex);
|
|
19
19
|
}
|
|
20
|
+
const existing = existingByPath ?? existingIndex;
|
|
20
21
|
// We always replace when making a leaf
|
|
21
22
|
if (item.kind === "leaf") {
|
|
22
23
|
const node = { ...item, parent: pathNode, path: path, asOf };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DataRequest, DataResponse, DataResponsePinned, RowGroup, RowLeaf, RowNode } from "../+types.js";
|
|
2
|
+
import type { LeafOrParent, TreeRootAndApi } from "./async-tree/+types.async-tree.js";
|
|
3
|
+
import { RangeTree } from "./range-tree/range-tree.js";
|
|
4
|
+
type DataFetcher = (req: DataRequest[], expansions: Record<string, boolean | undefined>, pivotExpansions: Record<string, boolean | undefined>) => Promise<(DataResponse | DataResponsePinned)[]>;
|
|
5
|
+
export interface FlatView {
|
|
6
|
+
readonly tree: TreeRootAndApi<RowGroup, RowLeaf>;
|
|
7
|
+
readonly top: number;
|
|
8
|
+
readonly center: number;
|
|
9
|
+
readonly bottom: number;
|
|
10
|
+
readonly rangeTree: RangeTree;
|
|
11
|
+
readonly rowIndexToRow: Map<number, RowNode<any>>;
|
|
12
|
+
readonly rowIdToRow: Map<string, RowNode<any>>;
|
|
13
|
+
readonly rowIdToRowIndex: Map<string, number>;
|
|
14
|
+
readonly rowIdToTreeNode: Map<string, LeafOrParent<RowGroup, RowLeaf>>;
|
|
15
|
+
readonly loading: Set<number>;
|
|
16
|
+
readonly errored: Map<number, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export interface ServerDataConstructorParams {
|
|
19
|
+
readonly blocksize: number;
|
|
20
|
+
readonly pivotMode: boolean;
|
|
21
|
+
readonly expansions: Record<string, boolean | undefined>;
|
|
22
|
+
readonly pivotExpansions: Record<string, boolean | undefined>;
|
|
23
|
+
readonly onResetLoadBegin: () => void;
|
|
24
|
+
readonly onResetLoadError: (error: unknown) => void;
|
|
25
|
+
readonly onResetLoadEnd: () => void;
|
|
26
|
+
readonly onFlatten: (r: FlatView) => void;
|
|
27
|
+
readonly defaultExpansion: boolean | number;
|
|
28
|
+
}
|
|
29
|
+
export declare class ServerData {
|
|
30
|
+
#private;
|
|
31
|
+
constructor({ blocksize, pivotMode, pivotExpansions, expansions, onResetLoadBegin, onResetLoadEnd, onResetLoadError, onFlatten, defaultExpansion, }: ServerDataConstructorParams);
|
|
32
|
+
set dataFetcher(d: DataFetcher);
|
|
33
|
+
set pivotMode(b: boolean);
|
|
34
|
+
set expansions(d: Record<string, boolean | undefined>);
|
|
35
|
+
set pivotExpansions(d: Record<string, boolean | undefined>);
|
|
36
|
+
set defaultExpansion(d: boolean | number);
|
|
37
|
+
set rowViewBounds(viewBounds: [start: number, end: number]);
|
|
38
|
+
reset: () => Promise<void>;
|
|
39
|
+
handleRequests: (requests: DataRequest[], opts?: {
|
|
40
|
+
onError?: (e: unknown) => void;
|
|
41
|
+
onSuccess?: () => void;
|
|
42
|
+
skipState?: boolean;
|
|
43
|
+
}) => Promise<void>;
|
|
44
|
+
handleResponses: (data: (DataResponse | DataResponsePinned)[], beforeOnFlat?: () => void) => void;
|
|
45
|
+
handleViewBoundsChange(): Promise<void>;
|
|
46
|
+
updateRow(id: string, data: any): void;
|
|
47
|
+
}
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { equal } from "@1771technologies/lytenyte-js-utils";
|
|
2
|
+
import { makeAsyncTree } from "./async-tree/make-async-tree.js";
|
|
3
|
+
import { RangeTree } from "./range-tree/range-tree.js";
|
|
4
|
+
import { getRequestId } from "./utils/get-request-id.js";
|
|
5
|
+
import { getNodePath } from "./utils/get-node-path.js";
|
|
6
|
+
import { getNodeDepth } from "./utils/get-node-depth.js";
|
|
7
|
+
const noopFetcher = async () => [];
|
|
8
|
+
export class ServerData {
|
|
9
|
+
#tree;
|
|
10
|
+
#top = { asOf: 0, rows: [] };
|
|
11
|
+
#bottom = { asOf: 0, rows: [] };
|
|
12
|
+
#blocksize;
|
|
13
|
+
#flat;
|
|
14
|
+
#dataFetcher = noopFetcher;
|
|
15
|
+
#pivotMode;
|
|
16
|
+
#expansions;
|
|
17
|
+
#pivotExpansions;
|
|
18
|
+
#onResetLoadBegin;
|
|
19
|
+
#onResetLoadError;
|
|
20
|
+
#onResetLoadEnd;
|
|
21
|
+
#onFlatten;
|
|
22
|
+
#rowViewBounds = [0, 0];
|
|
23
|
+
#prevRequests = [];
|
|
24
|
+
#loadingRows = new Set();
|
|
25
|
+
#rowsWithError = new Map();
|
|
26
|
+
#controllers = new Set();
|
|
27
|
+
#defaultExpansion;
|
|
28
|
+
constructor({ blocksize, pivotMode, pivotExpansions, expansions, onResetLoadBegin, onResetLoadEnd, onResetLoadError, onFlatten, defaultExpansion, }) {
|
|
29
|
+
this.#tree = makeAsyncTree();
|
|
30
|
+
this.#blocksize = blocksize;
|
|
31
|
+
this.#pivotMode = pivotMode;
|
|
32
|
+
this.#expansions = expansions;
|
|
33
|
+
this.#pivotExpansions = pivotExpansions;
|
|
34
|
+
this.#defaultExpansion = defaultExpansion;
|
|
35
|
+
this.#onResetLoadBegin = onResetLoadBegin;
|
|
36
|
+
this.#onResetLoadEnd = onResetLoadEnd;
|
|
37
|
+
this.#onResetLoadError = onResetLoadError;
|
|
38
|
+
this.#onFlatten = onFlatten;
|
|
39
|
+
}
|
|
40
|
+
// Properties
|
|
41
|
+
set dataFetcher(d) {
|
|
42
|
+
if (this.#dataFetcher === d)
|
|
43
|
+
return;
|
|
44
|
+
this.#dataFetcher = d;
|
|
45
|
+
this.reset();
|
|
46
|
+
}
|
|
47
|
+
set pivotMode(b) {
|
|
48
|
+
if (b === this.#pivotMode)
|
|
49
|
+
return;
|
|
50
|
+
this.#pivotMode = b;
|
|
51
|
+
this.reset();
|
|
52
|
+
}
|
|
53
|
+
set expansions(d) {
|
|
54
|
+
this.#expansions = d;
|
|
55
|
+
if (this.#pivotMode)
|
|
56
|
+
return;
|
|
57
|
+
this.#flatten();
|
|
58
|
+
}
|
|
59
|
+
set pivotExpansions(d) {
|
|
60
|
+
this.#pivotExpansions = d;
|
|
61
|
+
if (!this.#pivotMode)
|
|
62
|
+
return;
|
|
63
|
+
this.#flatten();
|
|
64
|
+
}
|
|
65
|
+
set defaultExpansion(d) {
|
|
66
|
+
this.#defaultExpansion = d;
|
|
67
|
+
}
|
|
68
|
+
set rowViewBounds(viewBounds) {
|
|
69
|
+
if (equal(viewBounds, this.#rowViewBounds))
|
|
70
|
+
return;
|
|
71
|
+
this.#rowViewBounds = viewBounds;
|
|
72
|
+
this.handleViewBoundsChange();
|
|
73
|
+
}
|
|
74
|
+
// Methods
|
|
75
|
+
reset = async () => {
|
|
76
|
+
// Abort all the existing requests in flight.
|
|
77
|
+
this.#controllers.forEach((c) => c.abort());
|
|
78
|
+
this.#tree = makeAsyncTree();
|
|
79
|
+
this.#flatten();
|
|
80
|
+
try {
|
|
81
|
+
this.#onResetLoadBegin();
|
|
82
|
+
this.#prevRequests = [
|
|
83
|
+
{
|
|
84
|
+
rowStartIndex: 0,
|
|
85
|
+
rowEndIndex: this.#blocksize,
|
|
86
|
+
id: getRequestId([], 0, this.#blocksize),
|
|
87
|
+
path: [],
|
|
88
|
+
start: 0,
|
|
89
|
+
end: this.#blocksize,
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
const res = await this.#dataFetcher(this.#prevRequests, this.#expansions, this.#pivotExpansions);
|
|
93
|
+
this.handleResponses(res);
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
console.log(e);
|
|
97
|
+
this.#onResetLoadError(e);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
this.#onResetLoadEnd();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
handleRequests = async (requests, opts = {}) => {
|
|
104
|
+
const controller = new AbortController();
|
|
105
|
+
this.#controllers.add(controller);
|
|
106
|
+
const skip = opts.skipState ?? false;
|
|
107
|
+
// We need to request our new data now. There are a few scenarios to be aware. Once we are requesting rows,
|
|
108
|
+
// we should mark the rows loading. This means we mark the row indices as loading (maybe by range)?
|
|
109
|
+
// The load may fail, in which case we should mark the request as an error.
|
|
110
|
+
try {
|
|
111
|
+
// Mark these rows as loading
|
|
112
|
+
requests.forEach((req) => {
|
|
113
|
+
if (!skip)
|
|
114
|
+
for (let i = req.rowStartIndex; i < req.rowEndIndex; i++)
|
|
115
|
+
this.#loadingRows.add(i);
|
|
116
|
+
});
|
|
117
|
+
const responses = await this.#dataFetcher(requests, this.#expansions, this.#pivotExpansions);
|
|
118
|
+
// The request was aborted, so we can ignore it from this point
|
|
119
|
+
if (controller.signal.aborted)
|
|
120
|
+
return;
|
|
121
|
+
this.handleResponses(responses, () => {
|
|
122
|
+
if (!skip)
|
|
123
|
+
requests.forEach((req) => {
|
|
124
|
+
for (let i = req.rowStartIndex; i < req.rowEndIndex; i++)
|
|
125
|
+
this.#rowsWithError.delete(i);
|
|
126
|
+
for (let i = req.rowStartIndex; i < req.rowEndIndex; i++)
|
|
127
|
+
this.#loadingRows.delete(i);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
opts?.onSuccess?.();
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
if (controller.signal.aborted)
|
|
134
|
+
return;
|
|
135
|
+
opts?.onError?.(e);
|
|
136
|
+
if (!skip)
|
|
137
|
+
requests.forEach((req) => {
|
|
138
|
+
for (let i = req.rowStartIndex; i < req.rowEndIndex; i++)
|
|
139
|
+
this.#rowsWithError.set(i, e);
|
|
140
|
+
for (let i = req.rowStartIndex; i < req.rowEndIndex; i++)
|
|
141
|
+
this.#loadingRows.delete(i);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
this.#controllers.delete(controller);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
handleResponses = (data, beforeOnFlat) => {
|
|
149
|
+
const pinned = data.filter((c) => c.kind === "top" || c.kind === "bottom");
|
|
150
|
+
const center = data.filter((c) => c.kind !== "top" && c.kind !== "bottom");
|
|
151
|
+
// handle pinned
|
|
152
|
+
for (let i = 0; i < pinned.length; i++) {
|
|
153
|
+
const r = pinned[i];
|
|
154
|
+
if (r.kind === "top" && r.asOfTime > this.#top.asOf) {
|
|
155
|
+
this.#top = {
|
|
156
|
+
asOf: r.asOfTime,
|
|
157
|
+
rows: r.data.map((c) => ({ id: c.id, data: c.data, kind: "leaf" })),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
else if (r.kind === "bottom" && r.asOfTime > this.#bottom.asOf) {
|
|
161
|
+
this.#bottom = {
|
|
162
|
+
asOf: r.asOfTime,
|
|
163
|
+
rows: r.data.map((c) => ({ id: c.id, data: c.data, kind: "leaf" })),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
center.sort((l, r) => l.path.length - r.path.length);
|
|
168
|
+
for (let i = 0; i < center.length; i++) {
|
|
169
|
+
const r = center[i];
|
|
170
|
+
this.#tree.set({
|
|
171
|
+
path: r.path,
|
|
172
|
+
items: r.data.map((c, i) => {
|
|
173
|
+
if (c.kind === "leaf") {
|
|
174
|
+
return {
|
|
175
|
+
kind: "leaf",
|
|
176
|
+
data: {
|
|
177
|
+
kind: "leaf",
|
|
178
|
+
data: c.data,
|
|
179
|
+
id: c.id,
|
|
180
|
+
},
|
|
181
|
+
relIndex: r.start + i,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return {
|
|
186
|
+
kind: "parent",
|
|
187
|
+
data: {
|
|
188
|
+
kind: "branch",
|
|
189
|
+
data: c.data,
|
|
190
|
+
depth: r.path.length,
|
|
191
|
+
id: c.id,
|
|
192
|
+
key: c.key,
|
|
193
|
+
},
|
|
194
|
+
path: c.key,
|
|
195
|
+
relIndex: r.start + i,
|
|
196
|
+
size: c.childCount,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}),
|
|
200
|
+
size: r.size,
|
|
201
|
+
asOf: r.asOfTime,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Re-flatten our tree once everything has been re-updated.
|
|
205
|
+
this.#flatten(beforeOnFlat);
|
|
206
|
+
};
|
|
207
|
+
async handleViewBoundsChange() {
|
|
208
|
+
const [start, end] = this.#rowViewBounds;
|
|
209
|
+
const seen = new Set();
|
|
210
|
+
const requests = [];
|
|
211
|
+
for (let i = start; i < end; i++) {
|
|
212
|
+
const ranges = this.#flat.rangeTree.findRangesForRowIndex(i);
|
|
213
|
+
ranges.forEach((c) => {
|
|
214
|
+
if (c.parent.kind === "root") {
|
|
215
|
+
const blockIndex = Math.floor(i / this.#blocksize);
|
|
216
|
+
const start = blockIndex * this.#blocksize;
|
|
217
|
+
const end = Math.min(start + this.#blocksize, c.parent.size);
|
|
218
|
+
const path = [];
|
|
219
|
+
const reqId = getRequestId(path, start, start + this.#blocksize);
|
|
220
|
+
if (seen.has(reqId))
|
|
221
|
+
return;
|
|
222
|
+
seen.add(reqId);
|
|
223
|
+
const size = start + this.#blocksize > c.parent.size ? c.parent.size - start : this.#blocksize;
|
|
224
|
+
requests.push({ id: reqId, path, start, end, rowStartIndex: i, rowEndIndex: i + size });
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
const blockIndex = Math.floor((i - c.rowStart) / this.#blocksize);
|
|
228
|
+
const start = blockIndex * this.#blocksize;
|
|
229
|
+
const end = Math.min(start + this.#blocksize, c.parent.size);
|
|
230
|
+
const path = getNodePath(c.parent);
|
|
231
|
+
const reqId = getRequestId(path, start, start + this.#blocksize);
|
|
232
|
+
if (seen.has(reqId))
|
|
233
|
+
return;
|
|
234
|
+
seen.add(reqId);
|
|
235
|
+
const size = start + this.#blocksize > c.parent.size ? c.parent.size - start : this.#blocksize;
|
|
236
|
+
requests.push({ id: reqId, path, start, end, rowStartIndex: i, rowEndIndex: i + size });
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const newRequests = requests.filter((c) => !this.#prevRequests.find((prev) => prev.id === c.id));
|
|
241
|
+
// We don't have any new requests to make in our view, so we can return
|
|
242
|
+
if (!newRequests.length)
|
|
243
|
+
return;
|
|
244
|
+
this.#prevRequests = requests;
|
|
245
|
+
await this.handleRequests(newRequests);
|
|
246
|
+
}
|
|
247
|
+
updateRow(id, data) {
|
|
248
|
+
const centerRow = this.#flat.rowIdToTreeNode.get(id);
|
|
249
|
+
if (centerRow) {
|
|
250
|
+
centerRow.data = { ...centerRow.data, data };
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
// Maybe its a pinned row?
|
|
254
|
+
const topIndex = this.#top.rows.findIndex((c) => c.id === id);
|
|
255
|
+
if (topIndex != -1) {
|
|
256
|
+
this.#top.rows[topIndex] = { ...this.#top.rows[topIndex], data };
|
|
257
|
+
}
|
|
258
|
+
const botIndex = this.#bottom.rows.findIndex((c) => c.id === id);
|
|
259
|
+
if (botIndex != -1) {
|
|
260
|
+
this.#top.rows[botIndex] = { ...this.#top.rows[botIndex], data };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
#flatten = (beforeOnFlat) => {
|
|
264
|
+
const mode = this.#pivotMode;
|
|
265
|
+
const expansions = mode ? this.#pivotExpansions : this.#expansions;
|
|
266
|
+
const t = this.#tree;
|
|
267
|
+
const rowIdToRow = new Map();
|
|
268
|
+
const rowIndexToRow = new Map();
|
|
269
|
+
const rowIdToRowIndex = new Map();
|
|
270
|
+
const rowIdToTreeNode = new Map();
|
|
271
|
+
const ranges = [];
|
|
272
|
+
const blocksize = this.#blocksize;
|
|
273
|
+
const previousRequests = this.#prevRequests;
|
|
274
|
+
const withError = this.#rowsWithError;
|
|
275
|
+
const withLoading = this.#loadingRows;
|
|
276
|
+
const handleRequests = this.handleRequests;
|
|
277
|
+
const defaultExpansion = this.#defaultExpansion;
|
|
278
|
+
const postFlatRequests = [];
|
|
279
|
+
function processParent(node, start) {
|
|
280
|
+
const rows = [...node.byIndex.values()].sort((l, r) => l.relIndex - r.relIndex);
|
|
281
|
+
let offset = 0;
|
|
282
|
+
for (let i = 0; i < rows.length; i++) {
|
|
283
|
+
const row = rows[i];
|
|
284
|
+
const rowIndex = row.relIndex + start + offset;
|
|
285
|
+
rowIndexToRow.set(rowIndex, row.data);
|
|
286
|
+
rowIdToRowIndex.set(row.data.id, rowIndex);
|
|
287
|
+
rowIdToRow.set(row.data.id, row.data);
|
|
288
|
+
rowIdToTreeNode.set(row.data.id, row);
|
|
289
|
+
if (row.kind === "parent") {
|
|
290
|
+
const expanded = expansions[row.data.id] ??
|
|
291
|
+
(typeof defaultExpansion === "number"
|
|
292
|
+
? getNodeDepth(row) <= defaultExpansion
|
|
293
|
+
: defaultExpansion);
|
|
294
|
+
if (expanded && !row.byIndex.size) {
|
|
295
|
+
const path = getNodePath(row);
|
|
296
|
+
const start = 0;
|
|
297
|
+
const end = Math.min(start + blocksize, row.size);
|
|
298
|
+
const reqSize = end - start;
|
|
299
|
+
const req = {
|
|
300
|
+
path,
|
|
301
|
+
start: start,
|
|
302
|
+
end: end,
|
|
303
|
+
id: getRequestId(path, 0, blocksize),
|
|
304
|
+
rowStartIndex: rowIndex + 1,
|
|
305
|
+
rowEndIndex: rowIndex + 1 + reqSize,
|
|
306
|
+
};
|
|
307
|
+
// If we haven't already requested this node
|
|
308
|
+
if (!previousRequests.find((c) => c.id === req.id)) {
|
|
309
|
+
postFlatRequests.push([rowIndex, req]);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else if (expanded) {
|
|
313
|
+
offset += processParent(row, rowIndex + 1);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
ranges.push({
|
|
318
|
+
rowStart: start,
|
|
319
|
+
rowEnd: offset + node.size + start,
|
|
320
|
+
parent: node,
|
|
321
|
+
});
|
|
322
|
+
return offset + node.size;
|
|
323
|
+
}
|
|
324
|
+
const topCount = this.#top.rows.length;
|
|
325
|
+
const bottomCount = this.#bottom.rows.length;
|
|
326
|
+
for (let i = 0; i < topCount; i++) {
|
|
327
|
+
const row = this.#top.rows[i];
|
|
328
|
+
rowIndexToRow.set(i, row);
|
|
329
|
+
rowIdToRow.set(row.id, row);
|
|
330
|
+
rowIdToRowIndex.set(row.id, i);
|
|
331
|
+
}
|
|
332
|
+
const size = processParent(t, topCount);
|
|
333
|
+
for (let i = 0; i < bottomCount; i++) {
|
|
334
|
+
const row = this.#bottom.rows[i];
|
|
335
|
+
const rowIndex = i + size;
|
|
336
|
+
rowIndexToRow.set(rowIndex, row);
|
|
337
|
+
rowIdToRow.set(row.id, row);
|
|
338
|
+
rowIdToRowIndex.set(row.id, rowIndex);
|
|
339
|
+
}
|
|
340
|
+
const rangeTree = new RangeTree(ranges);
|
|
341
|
+
if (postFlatRequests.length > 0) {
|
|
342
|
+
postFlatRequests.forEach((c) => {
|
|
343
|
+
withLoading.add(c[0]);
|
|
344
|
+
previousRequests.push(c[1]);
|
|
345
|
+
});
|
|
346
|
+
const reqs = postFlatRequests.map((c) => c[1]);
|
|
347
|
+
handleRequests(reqs, {
|
|
348
|
+
skipState: true,
|
|
349
|
+
onError: (e) => {
|
|
350
|
+
postFlatRequests.forEach((c) => {
|
|
351
|
+
withLoading.delete(c[0]);
|
|
352
|
+
withError.set(c[0], e);
|
|
353
|
+
});
|
|
354
|
+
},
|
|
355
|
+
onSuccess: () => {
|
|
356
|
+
postFlatRequests.forEach((c) => {
|
|
357
|
+
withLoading.delete(c[0]);
|
|
358
|
+
});
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
this.#flat = {
|
|
363
|
+
tree: t,
|
|
364
|
+
top: topCount,
|
|
365
|
+
center: size - topCount,
|
|
366
|
+
bottom: bottomCount,
|
|
367
|
+
rangeTree,
|
|
368
|
+
rowIndexToRow,
|
|
369
|
+
rowIdToRow,
|
|
370
|
+
rowIdToRowIndex,
|
|
371
|
+
rowIdToTreeNode,
|
|
372
|
+
errored: this.#rowsWithError,
|
|
373
|
+
loading: this.#loadingRows,
|
|
374
|
+
};
|
|
375
|
+
beforeOnFlat?.();
|
|
376
|
+
this.#onFlatten(this.#flat);
|
|
377
|
+
};
|
|
378
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { RowDataSourceServer, RowDataSourceServerParams } from "../+types.js";
|
|
2
|
-
export declare function makeServerDataSource<T>({ dataFetcher,
|
|
2
|
+
export declare function makeServerDataSource<T>({ dataFetcher, dataInFilterItemFetcher, dataColumnPivotFetcher, cellUpdateHandler, cellUpdateOptimistically, blockSize, }: RowDataSourceServerParams<T>): RowDataSourceServer<T>;
|
|
3
3
|
export declare function useServerDataSource<T>(p: RowDataSourceServerParams<T>): RowDataSourceServer<T>;
|