@acorex/cdk 22.2.0-next.0 → 22.2.0-next.2
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/fesm2022/acorex-cdk-common.mjs +83 -16
- package/fesm2022/acorex-cdk-common.mjs.map +1 -1
- package/fesm2022/acorex-cdk-drawer.mjs +4 -2
- package/fesm2022/acorex-cdk-drawer.mjs.map +1 -1
- package/fesm2022/acorex-cdk-horizontal-scroll.mjs +11 -5
- package/fesm2022/acorex-cdk-horizontal-scroll.mjs.map +1 -1
- package/fesm2022/acorex-cdk-list-navigation.mjs +11 -0
- package/fesm2022/acorex-cdk-list-navigation.mjs.map +1 -1
- package/fesm2022/acorex-cdk-overlay-scrollbar.mjs +903 -0
- package/fesm2022/acorex-cdk-overlay-scrollbar.mjs.map +1 -0
- package/fesm2022/acorex-cdk-overlay.mjs +35 -4
- package/fesm2022/acorex-cdk-overlay.mjs.map +1 -1
- package/fesm2022/acorex-cdk-text-editor.mjs +942 -0
- package/fesm2022/acorex-cdk-text-editor.mjs.map +1 -0
- package/fesm2022/acorex-cdk-wysiwyg.mjs +5 -0
- package/fesm2022/acorex-cdk-wysiwyg.mjs.map +1 -1
- package/overlay-scrollbar/README.md +54 -0
- package/package.json +12 -2
- package/text-editor/README.md +5 -0
- package/types/acorex-cdk-common.d.ts +10 -0
- package/types/acorex-cdk-list-navigation.d.ts +5 -0
- package/types/acorex-cdk-overlay-scrollbar.d.ts +155 -0
- package/types/acorex-cdk-text-editor.d.ts +156 -0
- package/types/acorex-cdk-wysiwyg.d.ts +3 -0
|
@@ -1168,6 +1168,7 @@ class AXListDataSource extends DataSource {
|
|
|
1168
1168
|
this.config = config;
|
|
1169
1169
|
this.debounceTime = 0;
|
|
1170
1170
|
this.subscription = new Subscription();
|
|
1171
|
+
this.connected = false;
|
|
1171
1172
|
this._range = { start: 0, end: 0 };
|
|
1172
1173
|
this.source = config.source;
|
|
1173
1174
|
if (config.debounceTime)
|
|
@@ -1176,9 +1177,20 @@ class AXListDataSource extends DataSource {
|
|
|
1176
1177
|
this.dataStream = new BehaviorSubject(this.config.source.cachedItems);
|
|
1177
1178
|
this.source.onChanged.subscribe((data) => {
|
|
1178
1179
|
this.dataStream.next(data.cachedItems);
|
|
1180
|
+
// A refresh (e.g. a new search) only reloads page 0. When the rendered range stays the same,
|
|
1181
|
+
// CDK emits no `viewChange`, so the other visible pages would otherwise stay as loading rows.
|
|
1182
|
+
if (this.connected) {
|
|
1183
|
+
this.loadMissingPagesInRange(data.totalCount);
|
|
1184
|
+
}
|
|
1179
1185
|
});
|
|
1180
1186
|
}
|
|
1181
1187
|
connect(collectionViewer) {
|
|
1188
|
+
// The same instance is reconnected when its viewport is destroyed and recreated
|
|
1189
|
+
// (e.g. a lookup search shows "no results" and then matches again). A closed
|
|
1190
|
+
// Subscription tears down anything added to it immediately, so start a fresh one.
|
|
1191
|
+
this.subscription.unsubscribe();
|
|
1192
|
+
this.subscription = new Subscription();
|
|
1193
|
+
this.connected = true;
|
|
1182
1194
|
this.subscription.add(collectionViewer.viewChange
|
|
1183
1195
|
.pipe(debounceTime(this.debounceTime))
|
|
1184
1196
|
.pipe(distinctUntilChanged())
|
|
@@ -1193,7 +1205,22 @@ class AXListDataSource extends DataSource {
|
|
|
1193
1205
|
return this.dataStream;
|
|
1194
1206
|
}
|
|
1195
1207
|
disconnect() {
|
|
1208
|
+
this.connected = false;
|
|
1196
1209
|
this.subscription.unsubscribe();
|
|
1210
|
+
this._range = { start: 0, end: 0 };
|
|
1211
|
+
}
|
|
1212
|
+
loadMissingPagesInRange(totalCount) {
|
|
1213
|
+
const end = Math.min(this._range.end, totalCount);
|
|
1214
|
+
if (end <= this._range.start) {
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
const startPage = this.getPageForIndex(this._range.start);
|
|
1218
|
+
const endPage = this.getPageForIndex(end - 1);
|
|
1219
|
+
for (let i = startPage; i <= endPage; i++) {
|
|
1220
|
+
if (!this.source.isPageFetched(i)) {
|
|
1221
|
+
this.source.setPage(i);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1197
1224
|
}
|
|
1198
1225
|
getPageForIndex(index) {
|
|
1199
1226
|
return Math.floor(index / this.source.config.pageSize);
|
|
@@ -1231,6 +1258,9 @@ class AXDataSource {
|
|
|
1231
1258
|
this._totalCount = 0;
|
|
1232
1259
|
this._items = [];
|
|
1233
1260
|
this.fetchedPages = new Set();
|
|
1261
|
+
/** Bumped on every reset so responses requested before it are dropped instead of corrupting the cache. */
|
|
1262
|
+
this.loadGeneration = 0;
|
|
1263
|
+
this.pendingLoads = 0;
|
|
1234
1264
|
this._page = 0;
|
|
1235
1265
|
this._query = { skip: 0, take: 0, sort: [] };
|
|
1236
1266
|
this.onChanged = new Subject();
|
|
@@ -1248,6 +1278,8 @@ class AXDataSource {
|
|
|
1248
1278
|
if (this.fetchedPages.has(page) && this.useCache) {
|
|
1249
1279
|
return;
|
|
1250
1280
|
}
|
|
1281
|
+
const generation = this.loadGeneration;
|
|
1282
|
+
this.pendingLoads++;
|
|
1251
1283
|
this.setLoadingState(true);
|
|
1252
1284
|
this.fetchedPages.add(page);
|
|
1253
1285
|
this._query.take = this.config.pageSize;
|
|
@@ -1255,25 +1287,50 @@ class AXDataSource {
|
|
|
1255
1287
|
this.config
|
|
1256
1288
|
.load({ ...this._query })
|
|
1257
1289
|
.then((result) => {
|
|
1258
|
-
if (
|
|
1259
|
-
|
|
1260
|
-
this._totalCount = result.total;
|
|
1290
|
+
if (generation !== this.loadGeneration) {
|
|
1291
|
+
return;
|
|
1261
1292
|
}
|
|
1262
|
-
this.
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
totalCount: this.totalCount,
|
|
1269
|
-
totalPages: this.totalPages,
|
|
1270
|
-
};
|
|
1271
|
-
this.onChanged.next(event);
|
|
1293
|
+
this.applyLoadResult(page, result);
|
|
1294
|
+
}, (error) => {
|
|
1295
|
+
if (generation === this.loadGeneration) {
|
|
1296
|
+
this.fetchedPages.delete(page);
|
|
1297
|
+
}
|
|
1298
|
+
throw error;
|
|
1272
1299
|
})
|
|
1273
1300
|
.finally(() => {
|
|
1274
|
-
this.
|
|
1301
|
+
if (generation !== this.loadGeneration) {
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
this.pendingLoads = Math.max(0, this.pendingLoads - 1);
|
|
1305
|
+
if (this.pendingLoads === 0) {
|
|
1306
|
+
this.setLoadingState(false);
|
|
1307
|
+
}
|
|
1275
1308
|
});
|
|
1276
1309
|
}
|
|
1310
|
+
applyLoadResult(page, result) {
|
|
1311
|
+
if (this._totalCount != result.total) {
|
|
1312
|
+
if (this._totalCount > 0) {
|
|
1313
|
+
// Rows of other pages are dropped with the old array, so they must be fetched again.
|
|
1314
|
+
this.fetchedPages = new Set([page]);
|
|
1315
|
+
}
|
|
1316
|
+
this._cachedItems = new Array(result.total);
|
|
1317
|
+
this._totalCount = result.total;
|
|
1318
|
+
}
|
|
1319
|
+
this._items = result.items;
|
|
1320
|
+
this._cachedItems.splice(page * this.config.pageSize, this.config.pageSize, ...result.items);
|
|
1321
|
+
const event = {
|
|
1322
|
+
cachedItems: this.cachedItems,
|
|
1323
|
+
items: this.items,
|
|
1324
|
+
page: page,
|
|
1325
|
+
totalCount: this.totalCount,
|
|
1326
|
+
totalPages: this.totalPages,
|
|
1327
|
+
};
|
|
1328
|
+
this.onChanged.next(event);
|
|
1329
|
+
}
|
|
1330
|
+
/** Whether `page` was loaded (or is loading) for the current filter/sort. */
|
|
1331
|
+
isPageFetched(page) {
|
|
1332
|
+
return this.fetchedPages.has(page);
|
|
1333
|
+
}
|
|
1277
1334
|
async getItemsByFilter(filter) {
|
|
1278
1335
|
return await this.config.load({ ...this.query, filter });
|
|
1279
1336
|
}
|
|
@@ -1282,7 +1339,7 @@ class AXDataSource {
|
|
|
1282
1339
|
this.onLoadingChanged.next(this._isLoading);
|
|
1283
1340
|
}
|
|
1284
1341
|
setPage(page) {
|
|
1285
|
-
if (this._page != page || this._items.length == 0) {
|
|
1342
|
+
if (this._page != page || this._items.length == 0 || !this.fetchedPages.has(page)) {
|
|
1286
1343
|
this._page = page;
|
|
1287
1344
|
this.load();
|
|
1288
1345
|
}
|
|
@@ -1301,12 +1358,22 @@ class AXDataSource {
|
|
|
1301
1358
|
this._query.filter = null;
|
|
1302
1359
|
}
|
|
1303
1360
|
reset() {
|
|
1361
|
+
const wasLoading = this._isLoading;
|
|
1362
|
+
this.resetState();
|
|
1363
|
+
if (wasLoading) {
|
|
1364
|
+
this.setLoadingState(false);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
/** Resets paging state without emitting `onLoadingChanged`, so a following `load()` keeps the loading state continuous. */
|
|
1368
|
+
resetState() {
|
|
1304
1369
|
this._query.filter = null;
|
|
1305
1370
|
this._query.sort = [];
|
|
1306
1371
|
this._query.skip = 0;
|
|
1307
1372
|
this._items = new Array(0);
|
|
1308
1373
|
this._cachedItems = new Array(this.config.pageSize);
|
|
1309
1374
|
this.fetchedPages.clear();
|
|
1375
|
+
this.loadGeneration++;
|
|
1376
|
+
this.pendingLoads = 0;
|
|
1310
1377
|
this._page = 0;
|
|
1311
1378
|
this._totalCount = 0;
|
|
1312
1379
|
}
|
|
@@ -1314,7 +1381,7 @@ class AXDataSource {
|
|
|
1314
1381
|
const currentFilter = this._query.filter;
|
|
1315
1382
|
const currentSort = this._query.sort;
|
|
1316
1383
|
if (options.reset) {
|
|
1317
|
-
this.
|
|
1384
|
+
this.resetState();
|
|
1318
1385
|
}
|
|
1319
1386
|
this._query.filter = currentFilter;
|
|
1320
1387
|
this._query.sort = currentSort;
|