canvu-react 0.3.12 → 0.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/index.cjs +135 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +135 -63
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +194 -115
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +9 -1
- package/dist/react.d.ts +9 -1
- package/dist/react.js +194 -115
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs +30 -5
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.js +30 -5
- package/dist/realtime.js.map +1 -1
- package/package.json +1 -1
package/dist/react.d.cts
CHANGED
|
@@ -107,10 +107,18 @@ type IngestAssetFilesToSceneItemsOptions = {
|
|
|
107
107
|
/**
|
|
108
108
|
* PDF rasterization scale forwarded to `pdfjs-dist`.
|
|
109
109
|
*
|
|
110
|
-
* Defaults to `1.
|
|
110
|
+
* Defaults to `1.15` to balance first paint latency with zoom quality.
|
|
111
111
|
*/
|
|
112
112
|
pdfScale?: number;
|
|
113
113
|
pdfPageConcurrency?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Called as soon as canvu finishes converting one or more items from the
|
|
116
|
+
* source files.
|
|
117
|
+
*/
|
|
118
|
+
onItemsReady?: (items: VectorSceneItem[], context: {
|
|
119
|
+
file: File;
|
|
120
|
+
kind: VectorViewportAssetKind;
|
|
121
|
+
}) => void;
|
|
114
122
|
/**
|
|
115
123
|
* Final hook to customize each created item after canvu attaches its own
|
|
116
124
|
* image metadata and any `assetStore.upload(...)` `pluginData`.
|
package/dist/react.d.ts
CHANGED
|
@@ -107,10 +107,18 @@ type IngestAssetFilesToSceneItemsOptions = {
|
|
|
107
107
|
/**
|
|
108
108
|
* PDF rasterization scale forwarded to `pdfjs-dist`.
|
|
109
109
|
*
|
|
110
|
-
* Defaults to `1.
|
|
110
|
+
* Defaults to `1.15` to balance first paint latency with zoom quality.
|
|
111
111
|
*/
|
|
112
112
|
pdfScale?: number;
|
|
113
113
|
pdfPageConcurrency?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Called as soon as canvu finishes converting one or more items from the
|
|
116
|
+
* source files.
|
|
117
|
+
*/
|
|
118
|
+
onItemsReady?: (items: VectorSceneItem[], context: {
|
|
119
|
+
file: File;
|
|
120
|
+
kind: VectorViewportAssetKind;
|
|
121
|
+
}) => void;
|
|
114
122
|
/**
|
|
115
123
|
* Final hook to customize each created item after canvu attaches its own
|
|
116
124
|
* image metadata and any `assetStore.upload(...)` `pluginData`.
|
package/dist/react.js
CHANGED
|
@@ -949,10 +949,32 @@ async function runWithConcurrency(items, concurrency, execute) {
|
|
|
949
949
|
async function loadPdfToStore(file, store, options) {
|
|
950
950
|
const scale = options?.scale ?? 1.5;
|
|
951
951
|
const pageConcurrency = options?.pageConcurrency ?? 2;
|
|
952
|
+
const storeThumbnails = options?.storeThumbnails ?? false;
|
|
952
953
|
const pdfjs = await getPdfJs();
|
|
953
954
|
const arrayBuffer = await file.arrayBuffer();
|
|
954
955
|
const pdf = await pdfjs.getDocument({ data: arrayBuffer }).promise;
|
|
955
956
|
const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
|
|
957
|
+
const bufferedResults = /* @__PURE__ */ new Map();
|
|
958
|
+
let nextEmitIndex = 0;
|
|
959
|
+
let emitChain = Promise.resolve();
|
|
960
|
+
const queuePageEmission = async (pageResult) => {
|
|
961
|
+
bufferedResults.set(pageResult.pageNumber, pageResult);
|
|
962
|
+
const run = async () => {
|
|
963
|
+
while (nextEmitIndex < pageNumbers.length) {
|
|
964
|
+
const nextPageNumber = pageNumbers[nextEmitIndex];
|
|
965
|
+
if (nextPageNumber == null) break;
|
|
966
|
+
const bufferedResult = bufferedResults.get(nextPageNumber);
|
|
967
|
+
if (!bufferedResult) break;
|
|
968
|
+
bufferedResults.delete(nextPageNumber);
|
|
969
|
+
nextEmitIndex += 1;
|
|
970
|
+
await options?.onPageStored?.(bufferedResult);
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
const nextChain = emitChain.then(run, run);
|
|
974
|
+
emitChain = nextChain.catch(() => {
|
|
975
|
+
});
|
|
976
|
+
await nextChain;
|
|
977
|
+
};
|
|
956
978
|
return await runWithConcurrency(
|
|
957
979
|
pageNumbers,
|
|
958
980
|
pageConcurrency,
|
|
@@ -962,27 +984,31 @@ async function loadPdfToStore(file, store, options) {
|
|
|
962
984
|
const mime = "image/png";
|
|
963
985
|
const pageBlob = await canvasToBlob2(canvas, mime);
|
|
964
986
|
const blobId = await store.storeOriginal(pageBlob);
|
|
965
|
-
const
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
tCtx
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
987
|
+
const thumbnailBlobId = storeThumbnails ? await (async () => {
|
|
988
|
+
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
989
|
+
const tw = Math.max(1, Math.round(width * thumbScale));
|
|
990
|
+
const th = Math.max(1, Math.round(height * thumbScale));
|
|
991
|
+
const thumbCanvas = document.createElement("canvas");
|
|
992
|
+
thumbCanvas.width = tw;
|
|
993
|
+
thumbCanvas.height = th;
|
|
994
|
+
const tCtx = thumbCanvas.getContext("2d");
|
|
995
|
+
if (tCtx) {
|
|
996
|
+
tCtx.imageSmoothingEnabled = true;
|
|
997
|
+
tCtx.imageSmoothingQuality = "high";
|
|
998
|
+
tCtx.drawImage(canvas, 0, 0, tw, th);
|
|
999
|
+
}
|
|
1000
|
+
const thumbBlob = await canvasToBlob2(thumbCanvas, mime);
|
|
1001
|
+
return await store.storeThumbnail(thumbBlob);
|
|
1002
|
+
})() : "";
|
|
1003
|
+
const pageResult = {
|
|
980
1004
|
blobId,
|
|
981
1005
|
thumbnailBlobId,
|
|
982
1006
|
width,
|
|
983
1007
|
height,
|
|
984
1008
|
pageNumber
|
|
985
1009
|
};
|
|
1010
|
+
await queuePageEmission(pageResult);
|
|
1011
|
+
return pageResult;
|
|
986
1012
|
}
|
|
987
1013
|
);
|
|
988
1014
|
}
|
|
@@ -992,7 +1018,8 @@ init_shape_builders();
|
|
|
992
1018
|
var HYDRATION_CACHE_NAME = "canvu-asset-hydration-v1";
|
|
993
1019
|
var DEFAULT_PDF_SCALE = 1.15;
|
|
994
1020
|
var DEFAULT_PDF_PAGE_CONCURRENCY = 2;
|
|
995
|
-
var
|
|
1021
|
+
var hydrationSourcePromises = /* @__PURE__ */ new Map();
|
|
1022
|
+
var pdfSourceBlobPromises = /* @__PURE__ */ new Map();
|
|
996
1023
|
function buildImageHydrationKey(assetId) {
|
|
997
1024
|
return `image:${assetId}`;
|
|
998
1025
|
}
|
|
@@ -1040,23 +1067,38 @@ async function fetchBlob(url) {
|
|
|
1040
1067
|
return null;
|
|
1041
1068
|
}
|
|
1042
1069
|
}
|
|
1043
|
-
async function
|
|
1070
|
+
async function getHydrationSource(key, preferCachedRasters, loader) {
|
|
1044
1071
|
const cached = preferCachedRasters ? await readCachedHydrationBlob(key) : null;
|
|
1045
|
-
if (cached)
|
|
1046
|
-
|
|
1072
|
+
if (cached) {
|
|
1073
|
+
return {
|
|
1074
|
+
blob: cached
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
const inFlight = hydrationSourcePromises.get(key);
|
|
1047
1078
|
if (inFlight) return await inFlight;
|
|
1048
1079
|
const nextPromise = (async () => {
|
|
1049
|
-
const
|
|
1050
|
-
if (blob) {
|
|
1051
|
-
await writeCachedHydrationBlob(key, blob);
|
|
1080
|
+
const source = await loader();
|
|
1081
|
+
if (source?.blob) {
|
|
1082
|
+
await writeCachedHydrationBlob(key, source.blob);
|
|
1052
1083
|
}
|
|
1053
|
-
return
|
|
1084
|
+
return source;
|
|
1054
1085
|
})();
|
|
1055
|
-
|
|
1086
|
+
hydrationSourcePromises.set(key, nextPromise);
|
|
1087
|
+
try {
|
|
1088
|
+
return await nextPromise;
|
|
1089
|
+
} finally {
|
|
1090
|
+
hydrationSourcePromises.delete(key);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
async function getPdfSourceBlob(url) {
|
|
1094
|
+
const inFlight = pdfSourceBlobPromises.get(url);
|
|
1095
|
+
if (inFlight) return await inFlight;
|
|
1096
|
+
const nextPromise = fetchBlob(url);
|
|
1097
|
+
pdfSourceBlobPromises.set(url, nextPromise);
|
|
1056
1098
|
try {
|
|
1057
1099
|
return await nextPromise;
|
|
1058
1100
|
} finally {
|
|
1059
|
-
|
|
1101
|
+
pdfSourceBlobPromises.delete(url);
|
|
1060
1102
|
}
|
|
1061
1103
|
}
|
|
1062
1104
|
function registerObjectUrl(objectUrls, blob) {
|
|
@@ -1110,18 +1152,22 @@ async function hydrateImageAssets(requests, resolvedAssetUrls, objectUrls, prefe
|
|
|
1110
1152
|
if (!resolvedAsset?.url) {
|
|
1111
1153
|
return [assetId, null];
|
|
1112
1154
|
}
|
|
1113
|
-
const
|
|
1155
|
+
const source = await getHydrationSource(
|
|
1114
1156
|
buildImageHydrationKey(assetId),
|
|
1115
1157
|
preferCachedRasters,
|
|
1116
|
-
async () =>
|
|
1158
|
+
async () => {
|
|
1159
|
+
const blob = await fetchBlob(resolvedAsset.url);
|
|
1160
|
+
if (!blob) return null;
|
|
1161
|
+
return { blob };
|
|
1162
|
+
}
|
|
1117
1163
|
);
|
|
1118
|
-
if (!blob) {
|
|
1164
|
+
if (!source?.blob) {
|
|
1119
1165
|
return [assetId, null];
|
|
1120
1166
|
}
|
|
1121
1167
|
return [
|
|
1122
1168
|
assetId,
|
|
1123
1169
|
{
|
|
1124
|
-
href: registerObjectUrl(objectUrls, blob)
|
|
1170
|
+
href: registerObjectUrl(objectUrls, source.blob)
|
|
1125
1171
|
}
|
|
1126
1172
|
];
|
|
1127
1173
|
})
|
|
@@ -1136,45 +1182,69 @@ async function hydratePdfAssets(requests, resolvedAssetUrls, objectUrls, options
|
|
|
1136
1182
|
if (!resolvedAsset?.url) {
|
|
1137
1183
|
continue;
|
|
1138
1184
|
}
|
|
1139
|
-
const
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1185
|
+
const pageKeys = group.pageNumbers.map((pageNumber) => ({
|
|
1186
|
+
pageNumber,
|
|
1187
|
+
cacheKey: buildPdfHydrationKey(group.assetId, pageNumber, group.scale)
|
|
1188
|
+
}));
|
|
1189
|
+
const pagesToRender = [];
|
|
1190
|
+
for (const { pageNumber, cacheKey } of pageKeys) {
|
|
1191
|
+
const cachedBlob = options.preferCachedRasters ? await readCachedHydrationBlob(cacheKey) : null;
|
|
1192
|
+
if (cachedBlob) {
|
|
1193
|
+
hydratedPages.set(cacheKey, {
|
|
1194
|
+
href: registerObjectUrl(objectUrls, cachedBlob)
|
|
1195
|
+
});
|
|
1145
1196
|
continue;
|
|
1146
1197
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
if (missingPages.length === 0) {
|
|
1152
|
-
continue;
|
|
1198
|
+
if (!hydrationSourcePromises.has(cacheKey)) {
|
|
1199
|
+
pagesToRender.push({ pageNumber, cacheKey });
|
|
1200
|
+
}
|
|
1153
1201
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1202
|
+
if (pagesToRender.length > 0) {
|
|
1203
|
+
const renderPromise = (async () => {
|
|
1204
|
+
const pdfBlob = await getPdfSourceBlob(resolvedAsset.url);
|
|
1205
|
+
if (!pdfBlob) {
|
|
1206
|
+
return /* @__PURE__ */ new Map();
|
|
1207
|
+
}
|
|
1208
|
+
const renderedPages = await loadPdfToStore(pdfBlob, options.imageStore, {
|
|
1209
|
+
scale: group.scale,
|
|
1210
|
+
pageNumbers: pagesToRender.map(({ pageNumber }) => pageNumber),
|
|
1211
|
+
pageConcurrency: options.pdfPageConcurrency
|
|
1212
|
+
});
|
|
1213
|
+
const renderedByPage = /* @__PURE__ */ new Map();
|
|
1214
|
+
for (const renderedPage of renderedPages) {
|
|
1215
|
+
const pageBlob = await options.imageStore.getOriginal(renderedPage.blobId);
|
|
1216
|
+
renderedByPage.set(
|
|
1217
|
+
renderedPage.pageNumber,
|
|
1218
|
+
pageBlob ? {
|
|
1219
|
+
blob: pageBlob,
|
|
1220
|
+
width: renderedPage.width,
|
|
1221
|
+
height: renderedPage.height
|
|
1222
|
+
} : null
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
return renderedByPage;
|
|
1226
|
+
})();
|
|
1227
|
+
for (const { pageNumber, cacheKey } of pagesToRender) {
|
|
1228
|
+
const pagePromise = getHydrationSource(
|
|
1229
|
+
cacheKey,
|
|
1230
|
+
options.preferCachedRasters,
|
|
1231
|
+
async () => (await renderPromise).get(pageNumber) ?? null
|
|
1232
|
+
);
|
|
1233
|
+
hydrationSourcePromises.set(cacheKey, pagePromise);
|
|
1234
|
+
}
|
|
1157
1235
|
}
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
const cacheKey = buildPdfHydrationKey(
|
|
1165
|
-
group.assetId,
|
|
1166
|
-
renderedPage.pageNumber,
|
|
1167
|
-
group.scale
|
|
1236
|
+
for (const { cacheKey } of pageKeys) {
|
|
1237
|
+
if (hydratedPages.has(cacheKey)) continue;
|
|
1238
|
+
const source = await getHydrationSource(
|
|
1239
|
+
cacheKey,
|
|
1240
|
+
options.preferCachedRasters,
|
|
1241
|
+
async () => null
|
|
1168
1242
|
);
|
|
1169
|
-
|
|
1170
|
-
if (!pageBlob) {
|
|
1171
|
-
continue;
|
|
1172
|
-
}
|
|
1173
|
-
await writeCachedHydrationBlob(cacheKey, pageBlob);
|
|
1243
|
+
if (!source?.blob) continue;
|
|
1174
1244
|
hydratedPages.set(cacheKey, {
|
|
1175
|
-
href: registerObjectUrl(objectUrls,
|
|
1176
|
-
width:
|
|
1177
|
-
height:
|
|
1245
|
+
href: registerObjectUrl(objectUrls, source.blob),
|
|
1246
|
+
width: source.width,
|
|
1247
|
+
height: source.height
|
|
1178
1248
|
});
|
|
1179
1249
|
}
|
|
1180
1250
|
}
|
|
@@ -1215,7 +1285,9 @@ async function hydrateSceneItemsWithAssets(items, assetStore, options = {}) {
|
|
|
1215
1285
|
objectUrls,
|
|
1216
1286
|
{
|
|
1217
1287
|
imageStore,
|
|
1218
|
-
pdfPageConcurrency
|
|
1288
|
+
pdfPageConcurrency,
|
|
1289
|
+
preferCachedRasters
|
|
1290
|
+
}
|
|
1219
1291
|
);
|
|
1220
1292
|
return {
|
|
1221
1293
|
items: items.map((item) => {
|
|
@@ -1292,9 +1364,10 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1292
1364
|
createId = createShapeId,
|
|
1293
1365
|
gapWorld = 16,
|
|
1294
1366
|
stepWorld = 48,
|
|
1295
|
-
pdfScale = 1.
|
|
1367
|
+
pdfScale = 1.15,
|
|
1296
1368
|
pdfPageConcurrency = 2,
|
|
1297
1369
|
decorateItem,
|
|
1370
|
+
onItemsReady,
|
|
1298
1371
|
onError
|
|
1299
1372
|
} = options;
|
|
1300
1373
|
const items = [];
|
|
@@ -1316,55 +1389,56 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1316
1389
|
}
|
|
1317
1390
|
try {
|
|
1318
1391
|
if (kind === "pdf") {
|
|
1319
|
-
const
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1392
|
+
const uploadResultPromise = uploadAssetIfNeeded(assetStore, file, kind);
|
|
1393
|
+
await loadPdfToStore(file, imageStore, {
|
|
1394
|
+
scale: pdfScale,
|
|
1395
|
+
pageConcurrency: pdfPageConcurrency,
|
|
1396
|
+
storeThumbnails: false,
|
|
1397
|
+
onPageStored: async (page) => {
|
|
1398
|
+
const uploadResult2 = await uploadResultPromise;
|
|
1399
|
+
const fullUrl2 = await createBlobUrlFromStore(imageStore, page.blobId);
|
|
1400
|
+
const naturalTopY2 = worldCenter.y - page.height / 2;
|
|
1401
|
+
const stackedTopY = occupiedBottomY == null ? naturalTopY2 : occupiedBottomY + gapWorld;
|
|
1402
|
+
const bounds2 = {
|
|
1403
|
+
x: worldCenter.x - page.width / 2,
|
|
1404
|
+
y: Math.max(naturalTopY2, stackedTopY),
|
|
1405
|
+
width: page.width,
|
|
1406
|
+
height: page.height
|
|
1407
|
+
};
|
|
1408
|
+
const itemContext2 = {
|
|
1409
|
+
file,
|
|
1410
|
+
kind,
|
|
1411
|
+
itemIndex: items.length,
|
|
1412
|
+
pageNumber: page.pageNumber
|
|
1413
|
+
};
|
|
1414
|
+
const item2 = finalizeIngestedItem(
|
|
1415
|
+
{
|
|
1416
|
+
id: createId(),
|
|
1417
|
+
x: bounds2.x,
|
|
1418
|
+
y: bounds2.y,
|
|
1419
|
+
bounds: { ...bounds2 },
|
|
1420
|
+
toolKind: "image",
|
|
1421
|
+
imageBlobId: page.blobId,
|
|
1422
|
+
imageRasterHref: fullUrl2 ?? void 0,
|
|
1423
|
+
imageIntrinsicSize: {
|
|
1424
|
+
width: page.width,
|
|
1425
|
+
height: page.height
|
|
1426
|
+
},
|
|
1427
|
+
childrenSvg: fullUrl2 ? buildRasterImageChildrenSvg(
|
|
1428
|
+
fullUrl2,
|
|
1429
|
+
{ width: page.width, height: page.height },
|
|
1430
|
+
bounds2
|
|
1431
|
+
) : ""
|
|
1354
1432
|
},
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
);
|
|
1365
|
-
items.push(item2);
|
|
1366
|
-
occupiedBottomY = bounds2.y + page.height;
|
|
1367
|
-
}
|
|
1433
|
+
itemContext2,
|
|
1434
|
+
uploadResult2,
|
|
1435
|
+
decorateItem
|
|
1436
|
+
);
|
|
1437
|
+
items.push(item2);
|
|
1438
|
+
occupiedBottomY = bounds2.y + page.height;
|
|
1439
|
+
onItemsReady?.([item2], { file, kind });
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1368
1442
|
hasImagePlacementBase = false;
|
|
1369
1443
|
imagePlacementIndex = 0;
|
|
1370
1444
|
imageYOffsetAdjustment = 0;
|
|
@@ -1417,6 +1491,7 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1417
1491
|
decorateItem
|
|
1418
1492
|
);
|
|
1419
1493
|
items.push(item);
|
|
1494
|
+
onItemsReady?.([item], { file, kind });
|
|
1420
1495
|
imagePlacementIndex++;
|
|
1421
1496
|
occupiedBottomY = occupiedBottomY == null ? bounds.y + height : Math.max(occupiedBottomY, bounds.y + height);
|
|
1422
1497
|
} catch (error) {
|
|
@@ -7329,7 +7404,13 @@ var VectorViewport = forwardRef(
|
|
|
7329
7404
|
y: worldY
|
|
7330
7405
|
},
|
|
7331
7406
|
imageStore: store,
|
|
7332
|
-
assetStore: assetStoreRef.current ?? void 0
|
|
7407
|
+
assetStore: assetStoreRef.current ?? void 0,
|
|
7408
|
+
onItemsReady: (nextItems) => {
|
|
7409
|
+
if (nextItems.length === 0) return;
|
|
7410
|
+
setLoadingSkeletons([]);
|
|
7411
|
+
change([...itemsRef.current, ...nextItems]);
|
|
7412
|
+
setEffectiveSelectedIdsRef.current(nextItems.map((item) => item.id));
|
|
7413
|
+
}
|
|
7333
7414
|
});
|
|
7334
7415
|
if (result.errors.length > 0) {
|
|
7335
7416
|
for (const error of result.errors) {
|
|
@@ -7337,8 +7418,6 @@ var VectorViewport = forwardRef(
|
|
|
7337
7418
|
}
|
|
7338
7419
|
}
|
|
7339
7420
|
if (result.items.length === 0) return;
|
|
7340
|
-
change([...itemsRef.current, ...result.items]);
|
|
7341
|
-
setEffectiveSelectedIdsRef.current(result.items.map((item) => item.id));
|
|
7342
7421
|
} finally {
|
|
7343
7422
|
setLoadingSkeletons([]);
|
|
7344
7423
|
}
|