nexus-shared 3.1.0 → 4.0.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/CHANGELOG.md +2268 -446
- package/LICENSE +21 -21
- package/README.md +1705 -1084
- package/dist/Client.Index.d.ts +17 -0
- package/dist/Client.Index.js +17 -0
- package/dist/Components/Documents/DocumentFrame.d.ts +50 -0
- package/dist/Components/Documents/DocumentFrame.js +83 -0
- package/dist/Components/Documents/Menu.d.ts +4 -0
- package/dist/Components/Documents/Menu.js +40 -24
- package/dist/Components/Documents/PrintDocument.d.ts +95 -0
- package/dist/Components/Documents/PrintDocument.js +62 -0
- package/dist/Components/Documents/Tabs.d.ts +59 -0
- package/dist/Components/Documents/Tabs.js +70 -0
- package/dist/Components/Forms/ApiForm.js +19 -2
- package/dist/Components/Forms/Crud.d.ts +2 -2
- package/dist/Components/Forms/Crud.js +871 -377
- package/dist/Components/Forms/CrudActions.d.ts +136 -0
- package/dist/Components/Forms/CrudActions.js +184 -0
- package/dist/Components/Forms/CrudHistory.d.ts +66 -0
- package/dist/Components/Forms/CrudHistory.js +140 -0
- package/dist/Components/Forms/CrudNarrowPicker.d.ts +31 -0
- package/dist/Components/Forms/CrudNarrowPicker.js +180 -0
- package/dist/Components/Forms/CrudParts.d.ts +30 -2
- package/dist/Components/Forms/CrudParts.js +56 -5
- package/dist/Components/Forms/CrudRowForms.d.ts +26 -0
- package/dist/Components/Forms/CrudRowForms.js +114 -0
- package/dist/Components/Forms/CrudScopes.d.ts +28 -0
- package/dist/Components/Forms/CrudScopes.js +76 -0
- package/dist/Components/Forms/CrudTree.d.ts +90 -0
- package/dist/Components/Forms/CrudTree.js +363 -0
- package/dist/Components/Forms/CrudWorkspace.d.ts +63 -0
- package/dist/Components/Forms/CrudWorkspace.js +169 -0
- package/dist/Components/Forms/ExcelImport.js +3 -3
- package/dist/Components/Forms/Form.d.ts +4 -4
- package/dist/Components/Forms/Form.js +125 -16
- package/dist/Components/Forms/FormLeaveGuard.d.ts +44 -0
- package/dist/Components/Forms/FormLeaveGuard.js +65 -0
- package/dist/Components/Forms/RecordFlows.d.ts +50 -0
- package/dist/Components/Forms/RecordFlows.js +282 -0
- package/dist/Components/Forms/SubmitForm.d.ts +37 -2
- package/dist/Components/Forms/SubmitForm.js +195 -10
- package/dist/Components/Inputs/CheckBox.js +1 -1
- package/dist/Components/Inputs/ChoiceField.d.ts +21 -1
- package/dist/Components/Inputs/ChoiceField.js +28 -2
- package/dist/Components/Inputs/CodeBox.d.ts +69 -0
- package/dist/Components/Inputs/CodeBox.js +316 -0
- package/dist/Components/Inputs/DatePicker.js +4 -1
- package/dist/Components/Inputs/DateRangePicker.js +4 -1
- package/dist/Components/Inputs/DateTimePicker.js +4 -1
- package/dist/Components/Inputs/Dropdown.d.ts +13 -0
- package/dist/Components/Inputs/Dropdown.js +8 -5
- package/dist/Components/Inputs/DropdownParts.d.ts +3 -1
- package/dist/Components/Inputs/DropdownParts.js +16 -4
- package/dist/Components/Inputs/Field.d.ts +7 -1
- package/dist/Components/Inputs/Field.js +2 -2
- package/dist/Components/Inputs/GroupForm.d.ts +6 -6
- package/dist/Components/Inputs/GroupForm.js +10 -11
- package/dist/Components/Inputs/InputRenderer.d.ts +9 -6
- package/dist/Components/Inputs/InputRenderer.js +39 -31
- package/dist/Components/Inputs/NumberBox.js +4 -2
- package/dist/Components/Inputs/PictureInput.d.ts +41 -0
- package/dist/Components/Inputs/PictureInput.js +70 -0
- package/dist/Components/Inputs/RadioGroup.d.ts +16 -3
- package/dist/Components/Inputs/RadioGroup.js +8 -3
- package/dist/Components/Inputs/RowsInput.d.ts +1 -1
- package/dist/Components/Inputs/RowsInput.js +18 -3
- package/dist/Components/Inputs/TabularForm.d.ts +5 -5
- package/dist/Components/Inputs/TabularForm.js +29 -29
- package/dist/Components/Inputs/TextArea.d.ts +6 -0
- package/dist/Components/Inputs/TextArea.js +14 -2
- package/dist/Components/Inputs/TextBox.js +4 -1
- package/dist/Components/Inputs/TextBoxTypes.d.ts +6 -0
- package/dist/Components/Inputs/TextBoxTypes.js +17 -0
- package/dist/Components/Inputs/TimePicker.js +4 -1
- package/dist/Components/Inputs/TreeView.d.ts +107 -6
- package/dist/Components/Inputs/TreeView.js +513 -30
- package/dist/Components/Layouts/MessageBox.d.ts +15 -2
- package/dist/Components/Layouts/MessageBox.js +56 -7
- package/dist/Components/Layouts/Popup.d.ts +13 -6
- package/dist/Components/Layouts/Popup.js +37 -9
- package/dist/Components/Layouts/PopupDock.d.ts +3 -1
- package/dist/Components/Layouts/PopupDock.js +2 -1
- package/dist/Components/Layouts/PopupHost.js +5 -4
- package/dist/Components/Layouts/ThemePicker.d.ts +3 -2
- package/dist/Components/Layouts/ThemePicker.js +16 -4
- package/dist/Components/Viewers/DataTable.js +205 -61
- package/dist/Components/Viewers/DataTableFilters.d.ts +1 -1
- package/dist/Components/Viewers/DataTableFilters.js +17 -2
- package/dist/Components/Viewers/DataTableParts.d.ts +46 -12
- package/dist/Components/Viewers/DataTableParts.js +62 -21
- package/dist/Components/Viewers/OwnerFiles.d.ts +175 -0
- package/dist/Components/Viewers/OwnerFiles.js +589 -0
- package/dist/Components/Viewers/QrCodeImage.d.ts +22 -0
- package/dist/Components/Viewers/QrCodeImage.js +15 -0
- package/dist/Components/Viewers/RecordCards.d.ts +16 -0
- package/dist/Components/Viewers/RecordCards.js +509 -0
- package/dist/Helpers/ApiModules.d.ts +3 -34
- package/dist/Helpers/ApiModules.js +3 -3
- package/dist/Helpers/ApiRoutes.d.ts +68 -26
- package/dist/Helpers/ApiRoutes.js +31 -27
- package/dist/Helpers/ArrayHelpers.d.ts +0 -0
- package/dist/Helpers/ArrayHelpers.js +2 -0
- package/dist/Helpers/BusyHooks.d.ts +6 -0
- package/dist/Helpers/BusyHooks.js +39 -0
- package/dist/Helpers/CodeHelpers.d.ts +97 -0
- package/dist/Helpers/CodeHelpers.js +332 -0
- package/dist/Helpers/CrudBackend.d.ts +114 -6
- package/dist/Helpers/CrudBackend.js +214 -11
- package/dist/Helpers/CrudColumns.d.ts +98 -0
- package/dist/Helpers/CrudColumns.js +160 -0
- package/dist/Helpers/CrudDetailsTabs.d.ts +58 -0
- package/dist/Helpers/CrudDetailsTabs.js +126 -0
- package/dist/Helpers/CrudHelpers.d.ts +130 -6
- package/dist/Helpers/CrudHelpers.js +304 -12
- package/dist/Helpers/CrudNarrowPick.d.ts +83 -0
- package/dist/Helpers/CrudNarrowPick.js +157 -0
- package/dist/Helpers/CrudRowForms.d.ts +15 -0
- package/dist/Helpers/CrudRowForms.js +43 -0
- package/dist/Helpers/CrudScopes.d.ts +32 -0
- package/dist/Helpers/CrudScopes.js +79 -0
- package/dist/Helpers/DropdownHelpers.d.ts +3 -1
- package/dist/Helpers/DropdownHelpers.js +6 -2
- package/dist/Helpers/ExcelHelpers.d.ts +1 -1
- package/dist/Helpers/ExcelHelpers.js +12 -11
- package/dist/Helpers/FileAdapter.d.ts +78 -0
- package/dist/Helpers/FileAdapter.js +102 -0
- package/dist/Helpers/FilePrimaries.d.ts +48 -0
- package/dist/Helpers/FilePrimaries.js +138 -0
- package/dist/Helpers/FormConfirm.d.ts +32 -0
- package/dist/Helpers/FormConfirm.js +40 -0
- package/dist/Helpers/FormStore.d.ts +90 -5
- package/dist/Helpers/FormStore.js +318 -22
- package/dist/Helpers/InputConditions.d.ts +50 -0
- package/dist/Helpers/InputConditions.js +168 -0
- package/dist/Helpers/InputMemory.d.ts +106 -0
- package/dist/Helpers/InputMemory.js +385 -0
- package/dist/Helpers/InputNarrowing.d.ts +18 -0
- package/dist/Helpers/InputNarrowing.js +67 -0
- package/dist/Helpers/InputParamsHelpers.d.ts +44 -1
- package/dist/Helpers/InputParamsHelpers.js +162 -71
- package/dist/Helpers/MessageBuilder.js +2 -0
- package/dist/Helpers/NexusDriveAdapter.d.ts +55 -0
- package/dist/Helpers/NexusDriveAdapter.js +207 -0
- package/dist/Helpers/NexusHelpers.d.ts +0 -0
- package/dist/Helpers/NexusHelpers.js +1 -0
- package/dist/Helpers/NumberHelpers.d.ts +95 -0
- package/dist/Helpers/NumberHelpers.js +126 -0
- package/dist/Helpers/Permissions.js +2 -1
- package/dist/Helpers/QrCode.d.ts +26 -0
- package/dist/Helpers/QrCode.js +463 -0
- package/dist/Helpers/RecordCards.d.ts +205 -0
- package/dist/Helpers/RecordCards.js +378 -0
- package/dist/Helpers/RequestCache.d.ts +47 -0
- package/dist/Helpers/RequestCache.js +132 -0
- package/dist/Helpers/RowsStore.d.ts +37 -2
- package/dist/Helpers/RowsStore.js +128 -10
- package/dist/Helpers/ServerPreview.d.ts +69 -0
- package/dist/Helpers/ServerPreview.js +99 -0
- package/dist/Helpers/TableColumns.js +4 -3
- package/dist/Helpers/TableExport.d.ts +7 -1
- package/dist/Helpers/TableExport.js +21 -15
- package/dist/Helpers/TableFilters.d.ts +1 -1
- package/dist/Helpers/TableFilters.js +24 -23
- package/dist/Helpers/TableHelpers.d.ts +24 -3
- package/dist/Helpers/TableHelpers.js +58 -12
- package/dist/Helpers/TableJoins.d.ts +83 -0
- package/dist/Helpers/TableJoins.js +284 -0
- package/dist/Helpers/TableStore.d.ts +26 -1
- package/dist/Helpers/TableStore.js +73 -7
- package/dist/Helpers/TreeStore.d.ts +306 -11
- package/dist/Helpers/TreeStore.js +1048 -90
- package/dist/Helpers/UserPreferences.d.ts +8 -0
- package/dist/Helpers/UserPreferences.js +17 -0
- package/dist/Interfaces/CrudInterfaces.d.ts +512 -14
- package/dist/Interfaces/FileInterfaces.d.ts +162 -0
- package/dist/Interfaces/FileInterfaces.js +4 -0
- package/dist/Interfaces/FormInterfaces.d.ts +393 -29
- package/dist/Interfaces/FormInterfaces.js +79 -1
- package/dist/Interfaces/InputInterfaces.d.ts +39 -3
- package/dist/Interfaces/MessageInterfaces.d.ts +1 -1
- package/dist/Interfaces/PreferenceInterfaces.d.ts +8 -0
- package/dist/Interfaces/PreferenceInterfaces.js +2 -5
- package/dist/Interfaces/RecordInterfaces.d.ts +367 -0
- package/dist/Interfaces/RecordInterfaces.js +1 -0
- package/dist/Interfaces/TableInterfaces.d.ts +160 -5
- package/dist/Services/ApiProxy.d.ts +36 -1
- package/dist/Services/ApiProxy.js +182 -52
- package/dist/Services/ApiProxyRules.d.ts +203 -0
- package/dist/Services/ApiProxyRules.js +426 -0
- package/dist/Services/ExcelApi.js +5 -0
- package/dist/Services/FileApi.d.ts +13 -0
- package/dist/Services/FileApi.js +29 -0
- package/dist/Services/ImageEditorLoader.d.ts +14 -0
- package/dist/Services/ImageEditorLoader.js +51 -0
- package/dist/Services/JoinSources.d.ts +80 -0
- package/dist/Services/JoinSources.js +150 -0
- package/dist/Services/ModuleImport.d.ts +7 -0
- package/dist/Services/ModuleImport.js +22 -0
- package/dist/Services/ServerApi.d.ts +13 -2
- package/dist/Services/ServerApi.js +8 -3
- package/dist/Shared.Index.d.ts +20 -0
- package/dist/Shared.Index.js +20 -0
- package/package.json +92 -85
- package/src/Styles/Nexus.Avatar.css +80 -79
- package/src/Styles/Nexus.Base.css +117 -117
- package/src/Styles/Nexus.Button.css +186 -180
- package/src/Styles/Nexus.Calendar.css +273 -273
- package/src/Styles/Nexus.Chat.css +1443 -1443
- package/src/Styles/Nexus.Choice.css +359 -343
- package/src/Styles/Nexus.Crud.css +542 -168
- package/src/Styles/Nexus.DateTime.css +81 -81
- package/src/Styles/Nexus.Dropdown.css +733 -725
- package/src/Styles/Nexus.Editor.css +295 -295
- package/src/Styles/Nexus.Excel.css +389 -389
- package/src/Styles/Nexus.Files.css +410 -0
- package/src/Styles/Nexus.Form.css +282 -279
- package/src/Styles/Nexus.Index.css +41 -37
- package/src/Styles/Nexus.Input.css +238 -4
- package/src/Styles/Nexus.Markdown.css +237 -237
- package/src/Styles/Nexus.Menu.css +246 -237
- package/src/Styles/Nexus.Popup.css +800 -724
- package/src/Styles/Nexus.Print.css +288 -0
- package/src/Styles/Nexus.QrCode.css +12 -0
- package/src/Styles/Nexus.Record.css +430 -0
- package/src/Styles/Nexus.Rows.css +637 -637
- package/src/Styles/Nexus.Slider.css +276 -276
- package/src/Styles/Nexus.Tab.Buttons.css +497 -432
- package/src/Styles/Nexus.Table.css +98 -35
- package/src/Styles/Nexus.Theme.Picker.css +59 -3
- package/src/Styles/Nexus.Themes.css +200 -194
- package/src/Styles/Nexus.Time.css +144 -144
- package/src/Styles/Nexus.Toast.css +263 -263
- package/src/Styles/Nexus.Tokens.css +94 -89
- package/src/Styles/Nexus.Tree.css +530 -431
|
@@ -19,6 +19,7 @@ function initialState(pageSize) {
|
|
|
19
19
|
matches: 0,
|
|
20
20
|
query: { search: "", sort: null, page: 1, pageSize },
|
|
21
21
|
selected: EMPTY_MAP,
|
|
22
|
+
picked: null,
|
|
22
23
|
busy: EMPTY_SET,
|
|
23
24
|
flashed: EMPTY_SET,
|
|
24
25
|
hidden: EMPTY_SET,
|
|
@@ -103,13 +104,18 @@ export class TableStore {
|
|
|
103
104
|
if (changes.selected && changes.selected !== previous.selected)
|
|
104
105
|
this.options.onSelectionChange?.(this.getSelected());
|
|
105
106
|
}
|
|
106
|
-
/**
|
|
107
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Puts back what was saved on this device (page size, sort, columns): before the first load, telling nobody, or, with
|
|
109
|
+
* `notify`, over a table already shown (another key's settings), its rows shown again in them on the first page.
|
|
110
|
+
*/
|
|
111
|
+
restore(saved, options = {}) {
|
|
108
112
|
const query = { ...this.state.query };
|
|
109
113
|
if (saved.pageSize && saved.pageSize > 0)
|
|
110
114
|
query.pageSize = saved.pageSize;
|
|
111
115
|
if (saved.sort !== undefined)
|
|
112
116
|
query.sort = saved.sort;
|
|
117
|
+
if (options.notify)
|
|
118
|
+
query.page = 1;
|
|
113
119
|
this.state = {
|
|
114
120
|
...this.state,
|
|
115
121
|
query,
|
|
@@ -118,6 +124,8 @@ export class TableStore {
|
|
|
118
124
|
widths: saved.widths ?? this.state.widths,
|
|
119
125
|
pinned: saved.pinned ?? this.state.pinned,
|
|
120
126
|
};
|
|
127
|
+
if (options.notify)
|
|
128
|
+
this.view();
|
|
121
129
|
}
|
|
122
130
|
/* Rows given by the page */
|
|
123
131
|
/** Shows these rows: every row there is. The table searches, sorts, and pages them. */
|
|
@@ -127,7 +135,9 @@ export class TableStore {
|
|
|
127
135
|
this.given = rows;
|
|
128
136
|
this.all = [...rows];
|
|
129
137
|
this.dropMissingSelection();
|
|
130
|
-
|
|
138
|
+
const picked = this.state.picked;
|
|
139
|
+
this.view({ status: "ready", error: null, refreshing: false, picked: this.followPicked(this.all, true) });
|
|
140
|
+
this.pickedChanged(picked);
|
|
131
141
|
}
|
|
132
142
|
/* Loading */
|
|
133
143
|
/**
|
|
@@ -151,6 +161,9 @@ export class TableStore {
|
|
|
151
161
|
this.state = { ...this.state, query: { ...this.state.query, search: "", page: 1 } };
|
|
152
162
|
if (this.state.selected.size)
|
|
153
163
|
this.set({ selected: EMPTY_MAP });
|
|
164
|
+
// Another list: the row picked in the one before is not in it.
|
|
165
|
+
if (this.state.picked)
|
|
166
|
+
this.pick(null);
|
|
154
167
|
}
|
|
155
168
|
const keepRows = quiet ?? (this.state.status === "ready" && !reset);
|
|
156
169
|
const query = this.state.query;
|
|
@@ -197,6 +210,7 @@ export class TableStore {
|
|
|
197
210
|
void this.reload({ quiet: true });
|
|
198
211
|
return;
|
|
199
212
|
}
|
|
213
|
+
const picked = this.state.picked;
|
|
200
214
|
this.set({
|
|
201
215
|
status: "ready",
|
|
202
216
|
refreshing: false,
|
|
@@ -207,13 +221,17 @@ export class TableStore {
|
|
|
207
221
|
offset: (query.page - 1) * query.pageSize,
|
|
208
222
|
query,
|
|
209
223
|
selected: this.refreshSelected(page.rows),
|
|
224
|
+
picked: this.followPicked(page.rows, false),
|
|
210
225
|
});
|
|
226
|
+
this.pickedChanged(picked);
|
|
211
227
|
return;
|
|
212
228
|
}
|
|
213
229
|
this.all = page.rows;
|
|
214
230
|
this.given = null;
|
|
215
231
|
this.dropMissingSelection();
|
|
216
|
-
|
|
232
|
+
const picked = this.state.picked;
|
|
233
|
+
this.view({ status: "ready", refreshing: false, error: null, picked: this.followPicked(this.all, true) });
|
|
234
|
+
this.pickedChanged(picked);
|
|
217
235
|
}
|
|
218
236
|
fail(error, seq) {
|
|
219
237
|
if (seq !== this.seq)
|
|
@@ -239,6 +257,15 @@ export class TableStore {
|
|
|
239
257
|
query: page === query.page ? query : { ...query, page },
|
|
240
258
|
});
|
|
241
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* Some columns' values changed while the rows did not: the names a `join` column reads came in. A client table reads
|
|
262
|
+
* its search text again and searches, filters, sorts and pages anew; a server table draws again. Nothing loads.
|
|
263
|
+
*/
|
|
264
|
+
refreshValues() {
|
|
265
|
+
this.texts = new WeakMap();
|
|
266
|
+
if (this.state.status === "ready")
|
|
267
|
+
this.view();
|
|
268
|
+
}
|
|
242
269
|
/** Changes the query: a client table shows it at once, a server table loads it. */
|
|
243
270
|
query(changes) {
|
|
244
271
|
const query = { ...this.state.query, ...changes };
|
|
@@ -292,6 +319,9 @@ export class TableStore {
|
|
|
292
319
|
*/
|
|
293
320
|
upsert(row, { at = "start", flash = true } = {}) {
|
|
294
321
|
const key = this.keyOf(row);
|
|
322
|
+
// The picked record's new copy is the one picked now.
|
|
323
|
+
const before = this.state.picked;
|
|
324
|
+
const picked = before && key && this.keyOf(before) === key ? row : before;
|
|
295
325
|
if (this.options.paging === "server") {
|
|
296
326
|
const index = this.state.rows.findIndex(candidate => this.keyOf(candidate) === key);
|
|
297
327
|
const rows = [...this.state.rows];
|
|
@@ -306,7 +336,7 @@ export class TableStore {
|
|
|
306
336
|
total++;
|
|
307
337
|
matches++;
|
|
308
338
|
}
|
|
309
|
-
this.set({ rows, total, matches, selected: this.replaceSelected(key, row), status: "ready" });
|
|
339
|
+
this.set({ rows, total, matches, selected: this.replaceSelected(key, row), picked, status: "ready" });
|
|
310
340
|
}
|
|
311
341
|
else {
|
|
312
342
|
const index = this.all.findIndex(candidate => this.keyOf(candidate) === key);
|
|
@@ -317,8 +347,9 @@ export class TableStore {
|
|
|
317
347
|
else
|
|
318
348
|
this.all.push(row);
|
|
319
349
|
this.all = [...this.all];
|
|
320
|
-
this.view({ selected: this.replaceSelected(key, row), status: "ready" });
|
|
350
|
+
this.view({ selected: this.replaceSelected(key, row), picked, status: "ready" });
|
|
321
351
|
}
|
|
352
|
+
this.pickedChanged(before);
|
|
322
353
|
if (flash && key)
|
|
323
354
|
this.flash([key]);
|
|
324
355
|
}
|
|
@@ -346,6 +377,9 @@ export class TableStore {
|
|
|
346
377
|
for (const key of gone)
|
|
347
378
|
selected.delete(key);
|
|
348
379
|
const busy = new Set([...this.state.busy].filter(key => !gone.has(key)));
|
|
380
|
+
// A picked record that left the list is no longer picked.
|
|
381
|
+
const before = this.state.picked;
|
|
382
|
+
const picked = before && gone.has(this.keyOf(before)) ? null : before;
|
|
349
383
|
if (this.options.paging === "server") {
|
|
350
384
|
const rows = this.state.rows.filter(row => !gone.has(this.keyOf(row)));
|
|
351
385
|
const removed = this.state.rows.length - rows.length;
|
|
@@ -354,15 +388,18 @@ export class TableStore {
|
|
|
354
388
|
total: Math.max(0, this.state.total - removed),
|
|
355
389
|
matches: Math.max(0, this.state.matches - removed),
|
|
356
390
|
selected: selected.size === this.state.selected.size ? this.state.selected : selected,
|
|
391
|
+
picked,
|
|
357
392
|
busy,
|
|
358
393
|
});
|
|
394
|
+
this.pickedChanged(before);
|
|
359
395
|
// A short wait lets several removals (a mass action's rows) share one load.
|
|
360
396
|
clearTimeout(this.reloadTimer);
|
|
361
397
|
this.reloadTimer = setTimeout(() => void this.reload({ quiet: true }), 60);
|
|
362
398
|
return;
|
|
363
399
|
}
|
|
364
400
|
this.all = this.all.filter(row => !gone.has(this.keyOf(row)));
|
|
365
|
-
this.view({ selected: selected.size === this.state.selected.size ? this.state.selected : selected, busy });
|
|
401
|
+
this.view({ selected: selected.size === this.state.selected.size ? this.state.selected : selected, picked, busy });
|
|
402
|
+
this.pickedChanged(before);
|
|
366
403
|
}
|
|
367
404
|
/* Selection */
|
|
368
405
|
/** Selects or unselects rows, up to `maxSelection`. Returns how many rows it could not select. */
|
|
@@ -431,6 +468,35 @@ export class TableStore {
|
|
|
431
468
|
this.state = { ...this.state, selected: selected.size ? selected : EMPTY_MAP };
|
|
432
469
|
this.options.onSelectionChange?.(this.getSelected());
|
|
433
470
|
}
|
|
471
|
+
/* The picked row */
|
|
472
|
+
/**
|
|
473
|
+
* Picks a row (`DataTable` `onPick`), or none: the one row whose own records the page shows beside the table. It
|
|
474
|
+
* follows the record from then on - its newest copy after an upsert, none once it is removed or gone after a load -
|
|
475
|
+
* and every change is told to `onPickChange`.
|
|
476
|
+
*/
|
|
477
|
+
pick(row) {
|
|
478
|
+
const next = row !== null && this.keyOf(row) !== "" ? row : null;
|
|
479
|
+
if (next === this.state.picked)
|
|
480
|
+
return;
|
|
481
|
+
this.set({ picked: next });
|
|
482
|
+
this.options.onPickChange?.(next);
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* The picked row as these rows hold it: its newest copy, or none when they are every row there is (`whole`, a client
|
|
486
|
+
* table) and it is not among them. A server page without it keeps it, since it may be on another page.
|
|
487
|
+
*/
|
|
488
|
+
followPicked(rows, whole) {
|
|
489
|
+
const picked = this.state.picked;
|
|
490
|
+
if (!picked)
|
|
491
|
+
return null;
|
|
492
|
+
const key = this.keyOf(picked);
|
|
493
|
+
return rows.find(row => this.keyOf(row) === key) ?? (whole ? null : picked);
|
|
494
|
+
}
|
|
495
|
+
/** Tells the page when a change left another copy of the picked row, or none. */
|
|
496
|
+
pickedChanged(before) {
|
|
497
|
+
if (this.state.picked !== before)
|
|
498
|
+
this.options.onPickChange?.(this.state.picked);
|
|
499
|
+
}
|
|
434
500
|
/* Rows with an action running, and rows to highlight */
|
|
435
501
|
setBusy(keys, on) {
|
|
436
502
|
const busy = new Set(this.state.busy);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RequestCache } from "./RequestCache.ts";
|
|
1
2
|
export type TreeValue = string | number;
|
|
2
3
|
/** An item of a tree: any object with a value, a parent value, and a label under the keys the tree is given. */
|
|
3
4
|
export type TreeItem = object;
|
|
@@ -25,9 +26,131 @@ export interface TreeStoreOptions<TItem extends TreeItem = TreeItem> {
|
|
|
25
26
|
cascade?: boolean;
|
|
26
27
|
/** Default `leaves`. Ignored without `cascade`, where the value is every checked item. */
|
|
27
28
|
valueMode?: TreeValueMode;
|
|
29
|
+
/**
|
|
30
|
+
* Children come later, a page at a time: a node with none loaded yet can be expanded, and `rows` shows its loading,
|
|
31
|
+
* failed, or Load more state. A node whose children come in the items counts as loaded. Default false.
|
|
32
|
+
*/
|
|
33
|
+
lazy?: boolean;
|
|
34
|
+
/** With `lazy`: the top level comes from the loader too, and the items given (if any) are only a start. Default false. */
|
|
35
|
+
lazyRoots?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* With `lazy`: the item field saying whether it has children before they are loaded - a boolean, or a count (more
|
|
38
|
+
* than 0). Without it, or when the field is empty, a node counts as having children until its first page answers.
|
|
39
|
+
*/
|
|
40
|
+
hasChildrenKey?: string;
|
|
41
|
+
}
|
|
42
|
+
/** A row that is not an item, under a parent of a lazy tree: its page is on its way, failed (Retry), or more can be loaded. */
|
|
43
|
+
export type TreeStatusKind = "loading" | "error" | "more";
|
|
44
|
+
/** Where a lazy parent's children stand: what was asked of the loader, and what it said. */
|
|
45
|
+
export interface TreeChildPages {
|
|
46
|
+
/** `idle`: nothing asked yet; `loading`: a page is on its way; `failed`: the last page failed; `ready`: answered. */
|
|
47
|
+
status: "idle" | "loading" | "failed" | "ready";
|
|
48
|
+
/** Children the loader gave so far, as it counted them: the next page skips this many. */
|
|
49
|
+
loaded: number;
|
|
50
|
+
/** All of the parent's children on the server, when the loader said. */
|
|
51
|
+
total?: number;
|
|
52
|
+
/** Whether another page follows. */
|
|
53
|
+
hasMore: boolean;
|
|
54
|
+
/** A refresh made the pages old: they are drawn until fresh ones replace them. */
|
|
55
|
+
stale: boolean;
|
|
56
|
+
/** The request now current; an answer to an older one is ignored. */
|
|
57
|
+
request: number;
|
|
58
|
+
}
|
|
59
|
+
/** What a lazy tree's loader is asked for: one page of a parent's children. */
|
|
60
|
+
export interface TreeChildrenRequest<TItem extends TreeItem = TreeItem> {
|
|
61
|
+
/** The item whose children to load, or `null` for the top level. */
|
|
62
|
+
parent: TItem | null;
|
|
63
|
+
/** Its value, or `null` for the top level. */
|
|
64
|
+
parentValue: TreeValue | null;
|
|
65
|
+
/** Children already loaded: the page starts after them (an API's skip count). */
|
|
66
|
+
skip: number;
|
|
67
|
+
/** The most to return: the page size (an API's max count). */
|
|
68
|
+
take: number;
|
|
69
|
+
/** Aborted when the tree unmounts before the answer, unless a `cacheKey` keeps the answer for the next tree. */
|
|
70
|
+
signal: AbortSignal;
|
|
71
|
+
}
|
|
72
|
+
/** One page of children, as the loader answers it. */
|
|
73
|
+
export interface TreeChildrenPage<TItem extends TreeItem = TreeItem> {
|
|
74
|
+
/** The children, in order. Their parent field is not read: they go under the parent that was asked for. */
|
|
75
|
+
items: readonly TItem[];
|
|
76
|
+
/** All of the parent's children on the server: Load more says how many are left. */
|
|
77
|
+
total?: number;
|
|
78
|
+
/** Whether another page follows. Default: `total` says so, or the page was full. */
|
|
79
|
+
hasMore?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A change to one item of a tree's source made somewhere else - a form saved, a record moved to the trash - written into
|
|
83
|
+
* the pages kept for the tree (`writeTreeChanges`) and into every tree on screen that shows them, so nothing is read
|
|
84
|
+
* from the server again for it.
|
|
85
|
+
*/
|
|
86
|
+
export type TreeItemChange<TItem extends TreeItem = TreeItem> = {
|
|
87
|
+
/** Added, changed, or moved: the item as it is now, under the item whose value is `parent` (`null`: the top level). */
|
|
88
|
+
type: "put";
|
|
89
|
+
item: TItem;
|
|
90
|
+
parent: TreeValue | null;
|
|
91
|
+
/**
|
|
92
|
+
* Where it was: its parent's value (`null`: the top level), or `false` when it was not in the tree at all - just
|
|
93
|
+
* added, or back from the trash. Left out when not known: a tree that holds the item knows, and the kept pages are
|
|
94
|
+
* searched; an item found nowhere then changes no count.
|
|
95
|
+
*/
|
|
96
|
+
before?: TreeValue | null | false;
|
|
97
|
+
} | {
|
|
98
|
+
/** Out of the tree - moved to the trash, deleted: the item's value, and its parent's when known. */
|
|
99
|
+
type: "remove";
|
|
100
|
+
value: TreeValue;
|
|
101
|
+
parent?: TreeValue | null;
|
|
102
|
+
};
|
|
103
|
+
/** How a tree reads its items, for changes written from outside it: the same keys the tree is given. */
|
|
104
|
+
export interface TreeChangeRules<TItem extends TreeItem = TreeItem> {
|
|
105
|
+
/** The item field that holds its value: the tree's `valueKey`. Default `id`. */
|
|
106
|
+
valueKey?: string;
|
|
107
|
+
/** The tree's `hasChildrenKey`: a parent's count there goes up and down with its children, and its chevron with it. */
|
|
108
|
+
hasChildrenKey?: string;
|
|
109
|
+
/**
|
|
110
|
+
* The order of siblings, as the server sorts them, so an item added or changed goes where a fresh read would put it.
|
|
111
|
+
* Without it an added item goes after the children loaded, and a changed one stays where it was.
|
|
112
|
+
*/
|
|
113
|
+
compare?: (a: TItem, b: TItem) => number;
|
|
28
114
|
}
|
|
115
|
+
/** Children's pages kept for every lazy tree on the page that names a `cacheKey`, for 5 minutes: see `RequestCache`. */
|
|
116
|
+
export declare const treePages: RequestCache<TreeChildrenPage<object>>;
|
|
117
|
+
/** The start of every key a tree keeps its pages under, or one parent's pages (`null`: the top level). */
|
|
118
|
+
export declare function treePagesKey(cacheKey: string, parent?: TreeValue | null): string;
|
|
119
|
+
/** The key one page is kept under. */
|
|
120
|
+
export declare function treePageKey(cacheKey: string, parent: TreeValue | null, skip: number, take: number): string;
|
|
121
|
+
/**
|
|
122
|
+
* Drops the kept pages of a tree's source - all of them, one parent's (`null`: the top level), or several parents' -
|
|
123
|
+
* after the records behind them changed elsewhere. Returns how many were dropped. A tree on screen keeps what it shows:
|
|
124
|
+
* its `refresh()` loads that again.
|
|
125
|
+
*/
|
|
126
|
+
export declare function expireTreePages(cacheKey: string, parent?: TreeValue | null | readonly (TreeValue | null)[]): number;
|
|
127
|
+
/**
|
|
128
|
+
* Writes changes made elsewhere into the pages kept for a tree's source, and into every tree on screen that keeps its
|
|
129
|
+
* pages under `cacheKey` - so a record saved in a form, moved, or sent to the trash shows in the tree at once, and
|
|
130
|
+
* leaving the page and coming back reads nothing again for it. Items go where the parent's children are known (see
|
|
131
|
+
* `TreeStore.placeItem`); a parent whose children were never loaded only counts one more or one fewer, and its first page
|
|
132
|
+
* comes from the server when it is opened, as it would have anyway.
|
|
133
|
+
*/
|
|
134
|
+
export declare function writeTreeChanges<TItem extends TreeItem>(cacheKey: string, changes: readonly TreeItemChange<TItem>[], rules?: TreeChangeRules<TItem>): void;
|
|
135
|
+
type TreeChangeListener = (changes: readonly TreeItemChange[], rules: TreeChangeRules) => void;
|
|
136
|
+
/** Hears the changes written for `cacheKey`: what a tree on screen does to write them into itself. Returns the way out. */
|
|
137
|
+
export declare function subscribeTreeChanges(cacheKey: string, listener: TreeChangeListener): () => void;
|
|
138
|
+
/**
|
|
139
|
+
* The kept pages under `cacheKey` with the changes written in (what `writeTreeChanges` does to `treePages`). A parent's
|
|
140
|
+
* pages are read as one list from its first child, the changes applied to it, and the list written back in pages of the
|
|
141
|
+
* same size, each with the parent's total - so a tree reading them again, page by page, asks the server for exactly the
|
|
142
|
+
* children it does not have. A page still on its way for a changed parent is dropped: its answer may predate the change.
|
|
143
|
+
*/
|
|
144
|
+
export declare function patchTreePages<TItem extends TreeItem>(cache: RequestCache<TreeChildrenPage>, cacheKey: string, changes: readonly TreeItemChange<TItem>[], rules?: TreeChangeRules<TItem>): void;
|
|
145
|
+
/** A has-children field read as the tree reads it: a boolean, or a count above 0; `undefined` when it says nothing. */
|
|
146
|
+
export declare function treeHasChildren(value: unknown): boolean | undefined;
|
|
147
|
+
/** The key of the status row under a parent (`null`: the top level), as `TreeNode.key` holds it. */
|
|
148
|
+
export declare function treeStatusKey(parentKey: string | null): string;
|
|
29
149
|
export interface TreeNode<TItem extends TreeItem = TreeItem> {
|
|
30
|
-
/**
|
|
150
|
+
/**
|
|
151
|
+
* A number unique to this node in its store for its whole life, for React keys and element ids. Counted per store,
|
|
152
|
+
* so a tree rendered on the server numbers its rows as the browser does.
|
|
153
|
+
*/
|
|
31
154
|
readonly uid: number;
|
|
32
155
|
/** The value as text: the key in maps, so `7` and `"7"` are the same item. */
|
|
33
156
|
key: string;
|
|
@@ -59,6 +182,19 @@ export interface TreeNode<TItem extends TreeItem = TreeItem> {
|
|
|
59
182
|
openChecked: number;
|
|
60
183
|
/** Being created and not saved yet: not part of the value or the items. */
|
|
61
184
|
draft: boolean;
|
|
185
|
+
/** With `lazy`: where its children's pages stand. */
|
|
186
|
+
pages?: TreeChildPages;
|
|
187
|
+
/**
|
|
188
|
+
* With `lazy`: not everything under it is loaded yet - its own pages, or a node's under it. With `cascade` such a node
|
|
189
|
+
* cannot be checked or unchecked as a whole (see `TreeStore.toggle`), and never shows checked unless the value names it.
|
|
190
|
+
*/
|
|
191
|
+
partial: boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Set only on a status row, a row that is not an item: under its `parent` (`null`: the top level) a page is on its
|
|
194
|
+
* way, failed, or more can be loaded. A status row is in `rows` only - never in `children`, the value, or the items -
|
|
195
|
+
* and its `item` is an empty object.
|
|
196
|
+
*/
|
|
197
|
+
status?: TreeStatusKind;
|
|
62
198
|
}
|
|
63
199
|
/** What expanding or collapsing did to the visible rows, for an animation. */
|
|
64
200
|
export interface TreeRowsChange<TItem extends TreeItem = TreeItem> {
|
|
@@ -86,12 +222,31 @@ export declare class TreeStore<TItem extends TreeItem = TreeItem> {
|
|
|
86
222
|
readonly labelKey: string;
|
|
87
223
|
readonly cascade: boolean;
|
|
88
224
|
readonly valueMode: TreeValueMode;
|
|
225
|
+
/** Children come a page at a time from a loader. */
|
|
226
|
+
readonly lazy: boolean;
|
|
227
|
+
private readonly hasChildrenKey;
|
|
89
228
|
private readonly isDisabled;
|
|
90
229
|
private readonly isChecked;
|
|
91
230
|
roots: TreeNode<TItem>[];
|
|
92
|
-
/**
|
|
231
|
+
/**
|
|
232
|
+
* The visible rows in order: top-level items, and the children of every expanded item whose parents are expanded,
|
|
233
|
+
* with a lazy parent's status row after its children. A new array after each change.
|
|
234
|
+
*/
|
|
93
235
|
rows: readonly TreeNode<TItem>[];
|
|
236
|
+
/** With `lazyRoots`: where the top level's pages stand. `null` when the top level comes from the items. */
|
|
237
|
+
rootPages: TreeChildPages | null;
|
|
94
238
|
private byKey;
|
|
239
|
+
/** The status row of each lazy parent that has had one, by the parent's key ("" for the top level). */
|
|
240
|
+
private statusRows;
|
|
241
|
+
/**
|
|
242
|
+
* With `lazy`: checked values whose items are not loaded yet, or not settled (see `settle`). They stay in the value,
|
|
243
|
+
* and check their items when the items come, so a saved value is never lost to a page not opened yet.
|
|
244
|
+
*/
|
|
245
|
+
private pending;
|
|
246
|
+
/** Whether the checks came from a value rather than from the items' own flags; items that come later follow the same rule. */
|
|
247
|
+
private valueGiven;
|
|
248
|
+
private requests;
|
|
249
|
+
private nextUid;
|
|
95
250
|
/** Without `cascade`: checked nodes, nodes that are not locked, and the checked ones among them. */
|
|
96
251
|
private checkedNodes;
|
|
97
252
|
private openNodes;
|
|
@@ -102,33 +257,53 @@ export declare class TreeStore<TItem extends TreeItem = TreeItem> {
|
|
|
102
257
|
get size(): number;
|
|
103
258
|
/** The node of a value. */
|
|
104
259
|
get(value: TreeValue | null | undefined): TreeNode<TItem> | undefined;
|
|
260
|
+
/** The node or status row whose `key` this is: what a view keeps for its focused row. */
|
|
261
|
+
find(key: string): TreeNode<TItem> | undefined;
|
|
262
|
+
/** Where a lazy parent's children stand (`null`: the top level); `undefined` when they do not come from a loader. */
|
|
263
|
+
pagesOf(parent: TreeNode<TItem> | null): TreeChildPages | undefined;
|
|
105
264
|
/**
|
|
106
265
|
* Replaces the items. Expanded items stay expanded. The checked items come from `value` when given, otherwise from
|
|
107
|
-
* the items' own flags.
|
|
266
|
+
* the items' own flags. In a lazy tree, an item whose children were loaded keeps them, unless the items now give it
|
|
267
|
+
* children of their own.
|
|
108
268
|
*/
|
|
109
269
|
setItems(items: readonly TItem[], value?: readonly TreeValue[]): void;
|
|
270
|
+
/** Moves the loaded children (and pages) of a node that is being built again onto its new node. */
|
|
271
|
+
private adoptChildren;
|
|
110
272
|
/** Every item in tree order, without drafts. */
|
|
111
273
|
items(): TItem[];
|
|
112
274
|
/** A node and everything under it, in tree order. */
|
|
113
275
|
subtree(node: TreeNode<TItem>): TreeNode<TItem>[];
|
|
114
276
|
/** The node's parents, the top-level one first. */
|
|
115
277
|
path(node: TreeNode<TItem>): TreeNode<TItem>[];
|
|
116
|
-
/**
|
|
278
|
+
/**
|
|
279
|
+
* The state of a node's box. With `cascade`, a lazy parent whose items are not all loaded is never `checked` - its
|
|
280
|
+
* unloaded items are not in the value - unless the value names it (`valueMode: "checked"`, where it stands for all).
|
|
281
|
+
*/
|
|
117
282
|
state(node: TreeNode<TItem>): TreeCheckState;
|
|
118
283
|
/** Checked boxes and all boxes: leaves with `cascade`, every item without it. Drafts count. */
|
|
119
284
|
counts(): {
|
|
120
285
|
checked: number;
|
|
121
286
|
total: number;
|
|
122
287
|
};
|
|
123
|
-
/**
|
|
288
|
+
/**
|
|
289
|
+
* The checked values, in tree order, following `valueMode`. In a lazy tree, values whose items are not loaded yet
|
|
290
|
+
* (or not settled) follow the others, so a saved value survives until its items come.
|
|
291
|
+
*/
|
|
124
292
|
value(): TreeValue[];
|
|
125
|
-
/** The items of the value, in the same order. */
|
|
293
|
+
/** The items of the value, in the same order. In a lazy tree it holds only the items loaded, so it can be shorter than `value()`. */
|
|
126
294
|
valueItems(): TItem[];
|
|
127
|
-
/**
|
|
295
|
+
/**
|
|
296
|
+
* Checks exactly these values. Locks do not apply: this is the saved state, not a user's change. In a lazy tree a
|
|
297
|
+
* value whose item is not loaded is kept, and checks the item when it comes. Returns whether anything changed.
|
|
298
|
+
*/
|
|
128
299
|
setValue(values: readonly TreeValue[]): boolean;
|
|
129
300
|
/**
|
|
130
301
|
* What a click on the node's box does. With `cascade` it checks every item under the node that is not locked, or
|
|
131
302
|
* unchecks them when they are all checked already. Returns whether anything changed; nothing does on a locked node.
|
|
303
|
+
*
|
|
304
|
+
* In a lazy tree with `cascade`, a node whose items are not all loaded (`partial`) does not change either: a check
|
|
305
|
+
* stands for everything under it, and the value can only hold the items that were loaded, so checking it would
|
|
306
|
+
* silently leave the rest out. The items under it whose own items are all loaded can still be checked one by one.
|
|
132
307
|
*/
|
|
133
308
|
toggle(node: TreeNode<TItem>): boolean;
|
|
134
309
|
/** Checks or unchecks a node; with `cascade`, every item under it that is not locked. Returns whether anything changed. */
|
|
@@ -137,25 +312,65 @@ export declare class TreeStore<TItem extends TreeItem = TreeItem> {
|
|
|
137
312
|
allState(): TreeCheckState | null;
|
|
138
313
|
/** What a click on a "select all" box does: checks every item that is not locked, or unchecks them all when all are checked. */
|
|
139
314
|
toggleAll(): boolean;
|
|
140
|
-
/**
|
|
315
|
+
/**
|
|
316
|
+
* Checks or unchecks every item that is not locked. Returns whether anything changed. In a lazy tree with `cascade`,
|
|
317
|
+
* a node whose items are not all loaded is passed over and the loaded parts under it are changed; values whose
|
|
318
|
+
* items are not loaded stay as they are.
|
|
319
|
+
*/
|
|
141
320
|
checkAll(checked: boolean): boolean;
|
|
142
321
|
/** Whether every parent of the node is expanded, so the node is a row. */
|
|
143
322
|
isVisible(node: TreeNode<TItem>): boolean;
|
|
323
|
+
/** Whether the node can be expanded: it has children, or (lazy) it may have some not loaded yet. */
|
|
324
|
+
canExpand(node: TreeNode<TItem>): boolean;
|
|
144
325
|
/** The node's row index, or -1 when it is not a row. */
|
|
145
326
|
indexOf(node: TreeNode<TItem>): number;
|
|
146
|
-
/** Expands a node. Returns the rows it added, or `null` when no rows changed. */
|
|
327
|
+
/** Expands a node. Returns the rows it added (a lazy node's status row too), or `null` when no rows changed. */
|
|
147
328
|
expand(node: TreeNode<TItem>): TreeRowsChange<TItem> | null;
|
|
148
329
|
/** Collapses a node. Returns the rows it removed, or `null` when no rows changed. */
|
|
149
330
|
collapse(node: TreeNode<TItem>): TreeRowsChange<TItem> | null;
|
|
150
|
-
/**
|
|
331
|
+
/**
|
|
332
|
+
* Expands every item, or only the first `levels` levels (1 expands the top-level items). In a lazy tree it opens the
|
|
333
|
+
* items whose children are loaded, and asks for nothing: a node open on a page still on its way stays open.
|
|
334
|
+
*/
|
|
151
335
|
expandAll(levels?: number): void;
|
|
152
336
|
collapseAll(): void;
|
|
153
|
-
/** Expands these items and their parents, so the items and their children show. */
|
|
337
|
+
/** Expands these items and their parents, so the items and their children show. In a lazy tree, only items whose children are loaded. */
|
|
154
338
|
expandValues(values: readonly TreeValue[]): void;
|
|
155
339
|
/** The values of the expanded items, in tree order. */
|
|
156
340
|
expandedValues(): TreeValue[];
|
|
157
341
|
/** Expands the parents of a node so it becomes a row. Returns whether rows changed. */
|
|
158
342
|
reveal(node: TreeNode<TItem>): boolean;
|
|
343
|
+
/**
|
|
344
|
+
* Marks a parent's next page as on its way (`null`: the top level) and returns the request's number, which the
|
|
345
|
+
* answer is given back with. An earlier request still out is forgotten. Returns 0 when the parent has no pages.
|
|
346
|
+
*/
|
|
347
|
+
beginLoad(parent: TreeNode<TItem> | null): number;
|
|
348
|
+
/**
|
|
349
|
+
* Adds a page of children that `request` asked for, after the ones loaded, and works out what follows: `hasMore`
|
|
350
|
+
* when the page says, else whether `total` is reached, else whether the page was full (`take` items). Their parent
|
|
351
|
+
* field is not read: they go under `parent`. A value already in the tree is passed over, so a page that overlaps
|
|
352
|
+
* the last one adds no row twice. Returns the nodes added and the rows they added (for an animation), or `null` when
|
|
353
|
+
* the answer is to an older request or the parent is gone.
|
|
354
|
+
*/
|
|
355
|
+
receivePage(parent: TreeNode<TItem> | null, request: number, page: TreeChildrenPage<TItem>, take: number): {
|
|
356
|
+
added: TreeNode<TItem>[];
|
|
357
|
+
change: TreeRowsChange<TItem> | null;
|
|
358
|
+
} | null;
|
|
359
|
+
/** The page `request` asked for failed: the parent shows a failed row with Retry. Returns false for an older request. */
|
|
360
|
+
failLoad(parent: TreeNode<TItem> | null, request: number): boolean;
|
|
361
|
+
/**
|
|
362
|
+
* Replaces a parent's children with fresh pages after a refresh (`request` from `beginLoad`): an item still there
|
|
363
|
+
* keeps its node - what is expanded and loaded under it - and takes the fresh item; one no longer there goes, and a
|
|
364
|
+
* value it held waits in the value for its item to come back. Returns false for an older request.
|
|
365
|
+
*/
|
|
366
|
+
replacePages(parent: TreeNode<TItem> | null, request: number, answers: readonly TreeChildrenPage<TItem>[], take: number): boolean;
|
|
367
|
+
/**
|
|
368
|
+
* Marks loaded pages old, for a refresh: every lazy parent (`null`), or a node and everything under it. The view
|
|
369
|
+
* loads again the ones on screen, and the rest load when next expanded; a page on its way is forgotten, and a node
|
|
370
|
+
* that had answered with no children may have some now.
|
|
371
|
+
*/
|
|
372
|
+
markStale(node?: TreeNode<TItem> | null): void;
|
|
373
|
+
private stalePages;
|
|
159
374
|
/**
|
|
160
375
|
* Adds an item under `parent` (at the top level for `null`), as its last child unless `index` is given, and expands
|
|
161
376
|
* the parent. A `draft` is not part of the value or the items until `update` saves it. Throws on a value in use.
|
|
@@ -164,6 +379,12 @@ export declare class TreeStore<TItem extends TreeItem = TreeItem> {
|
|
|
164
379
|
index?: number;
|
|
165
380
|
draft?: boolean;
|
|
166
381
|
}): TreeNode<TItem>;
|
|
382
|
+
/**
|
|
383
|
+
* Adds many items under `parent` (at the top level for `null`) after its children, in one pass: counts are updated
|
|
384
|
+
* along one path, not over the whole tree, so a page of 50 joins a tree of 100,000 in well under a millisecond. A
|
|
385
|
+
* value already in the tree is passed over. The parent is not expanded. Returns the nodes added.
|
|
386
|
+
*/
|
|
387
|
+
insertMany(parent: TreeNode<TItem> | null, items: readonly TItem[]): TreeNode<TItem>[];
|
|
167
388
|
/**
|
|
168
389
|
* Replaces a node's item, e.g. after a rename, or once a draft is saved and the server gave it an id. The value can
|
|
169
390
|
* change; the parent cannot. Throws on a value another item uses.
|
|
@@ -173,12 +394,85 @@ export declare class TreeStore<TItem extends TreeItem = TreeItem> {
|
|
|
173
394
|
}): void;
|
|
174
395
|
/** Removes a node and everything under it. Returns the removed nodes in tree order. */
|
|
175
396
|
remove(node: TreeNode<TItem>): TreeNode<TItem>[];
|
|
397
|
+
/**
|
|
398
|
+
* Writes an item where a change made elsewhere left it (see `TreeItemChange`): in place under the same parent (moved
|
|
399
|
+
* among its siblings by `compare`), under its new parent when it moved - with what is loaded under it - and in for the
|
|
400
|
+
* first time when it is new or back. Only where the parent's children are known: given, loaded, or known to be none.
|
|
401
|
+
* Under a parent never opened it waits for that parent's first page, and one that sorts after the loaded children while
|
|
402
|
+
* more are to come waits for its page. A lazy parent's `loaded` and `total` follow, so its next page skips the right
|
|
403
|
+
* number, and so does the count in `hasChildrenKey` on the parent's own item, which its chevron goes by. Returns the
|
|
404
|
+
* item's node where it is now, or `undefined` when this tree does not show it.
|
|
405
|
+
*/
|
|
406
|
+
placeItem(item: TItem, parentValue: TreeValue | null, options?: {
|
|
407
|
+
before?: TreeValue | null | false;
|
|
408
|
+
compare?: (a: TItem, b: TItem) => number;
|
|
409
|
+
}): TreeNode<TItem> | undefined;
|
|
410
|
+
/**
|
|
411
|
+
* Takes out an item a change made elsewhere took out of the tree - moved to the trash, deleted - with everything under
|
|
412
|
+
* it. Its parent counts one fewer (its pages' `loaded` and `total`, the count on its item) and loses its chevron when
|
|
413
|
+
* none are left. An item not loaded here still lowers its parent's counts when `parentValue` names the parent.
|
|
414
|
+
* Returns the nodes taken out.
|
|
415
|
+
*/
|
|
416
|
+
removeItem(value: TreeValue, parentValue?: TreeValue | null): TreeNode<TItem>[];
|
|
417
|
+
/** Whether a parent's children are known here: given in the items, loaded (all or the first pages), or known to be none. */
|
|
418
|
+
private listsChildren;
|
|
419
|
+
/**
|
|
420
|
+
* One child more or fewer under a parent (`null`: the top level): its pages' total, and the count its own item
|
|
421
|
+
* carries in `hasChildrenKey` - a new copy of the item. A parent never opened reads its children from the new count,
|
|
422
|
+
* so one that has none left loses its chevron; one whose children were loaded knows already.
|
|
423
|
+
*/
|
|
424
|
+
private countChild;
|
|
176
425
|
private createNode;
|
|
426
|
+
/** A lazy node's pages before anything is asked: none to ask for when its item says it has no children. */
|
|
427
|
+
private newPages;
|
|
428
|
+
/** Whether a parent (`null`: the top level) is still in the tree, so an answer for it applies. */
|
|
429
|
+
private owns;
|
|
430
|
+
/** After a parent's pages changed state: its `partial` and counts along its path, and its rows. */
|
|
431
|
+
private changedPages;
|
|
432
|
+
/**
|
|
433
|
+
* Creates nodes for items under a parent, after its children, and updates counts along the parent's path only. A
|
|
434
|
+
* value already in the tree is passed over.
|
|
435
|
+
*/
|
|
436
|
+
private addNodes;
|
|
437
|
+
/** Adds (1) or takes away (-1) nodes' share of the counts kept for a tree without `cascade`. */
|
|
438
|
+
private count;
|
|
439
|
+
/** Whether an item that has just come starts checked: its value is waiting, a parent's value stands for it, or its own flag. */
|
|
440
|
+
private arrivalChecked;
|
|
441
|
+
/**
|
|
442
|
+
* Whether a waiting value is settled now that its item is here, so the tree's own checks say it all:
|
|
443
|
+
* - without `cascade`, at once - the item is its own value, and came checked;
|
|
444
|
+
* - with `cascade`, a parent named in a value of leaves (or of every parent with a checked item) means nothing, as in
|
|
445
|
+
* a tree loaded whole;
|
|
446
|
+
* - with `cascade`, any other waits until everything under its item is loaded: an unloaded item, or a "checked"-mode
|
|
447
|
+
* parent that stands for all of its items, loaded or not.
|
|
448
|
+
*/
|
|
449
|
+
private settle;
|
|
450
|
+
private settleAll;
|
|
451
|
+
private settleAround;
|
|
452
|
+
private dropClaimsAbove;
|
|
453
|
+
/** With `cascade`: the highest nodes whose items are all loaded - the roots, or below a partial node its loaded parts. */
|
|
454
|
+
private settledTops;
|
|
455
|
+
/**
|
|
456
|
+
* Fresh items in place of a parent's children: a node whose value is still there is kept (with what is expanded and
|
|
457
|
+
* loaded under it) and takes the fresh item; one not there goes, unless it is a draft being named.
|
|
458
|
+
*/
|
|
459
|
+
private reconcile;
|
|
460
|
+
/** Rows again for a parent's block (`null`: every row), when it is expanded and a row: its children's rows and its status row. */
|
|
461
|
+
private refreshBlock;
|
|
462
|
+
/** The rows these nodes show - each node, then the rows of its children when it is expanded - and, in a lazy tree, each expanded parent's status row after its children. `parent` owns `nodes`, for its own status row. */
|
|
463
|
+
private visibleRows;
|
|
464
|
+
/** The status row an expanded parent (`null`: the top level) shows after its children, if its pages need one. */
|
|
465
|
+
private statusRowOf;
|
|
177
466
|
private keysOf;
|
|
178
467
|
/** With `valueMode: "checked"`, a parent in the value stands for all of its items. */
|
|
179
468
|
private checkedByParent;
|
|
180
469
|
/** Locks and counts for every node, given in tree order: parents pass locks down, children pass counts up. */
|
|
181
470
|
private recount;
|
|
471
|
+
/**
|
|
472
|
+
* A node's lock, `partial`, and counts, from its own flags and its children's (already worked out): what `recount`
|
|
473
|
+
* does for every node, and what a page of children does for each node on its parent's path.
|
|
474
|
+
*/
|
|
475
|
+
private aggregate;
|
|
182
476
|
/** Sets every open leaf under a node (the node itself for a leaf), updating counts up the path of each leaf that changes. */
|
|
183
477
|
private setLeaves;
|
|
184
478
|
private setNodeChecked;
|
|
@@ -186,3 +480,4 @@ export declare class TreeStore<TItem extends TreeItem = TreeItem> {
|
|
|
186
480
|
}
|
|
187
481
|
/** Nodes in tree order: each node, then its children. No recursion, so even a chain 100,000 levels deep works. */
|
|
188
482
|
export declare function preOrder<TItem extends TreeItem>(nodes: readonly TreeNode<TItem>[]): TreeNode<TItem>[];
|
|
483
|
+
export {};
|