canvu-react 0.4.70 → 0.4.72
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/{asset-hydration-D2xaUoAT.d.cts → asset-hydration-6swZ6ciN.d.cts} +1 -1
- package/dist/{asset-hydration-D9eThWse.d.ts → asset-hydration-P0M5hn-p.d.ts} +1 -1
- package/dist/chatbot.d.cts +2 -2
- package/dist/chatbot.d.ts +2 -2
- package/dist/index.cjs +139 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +139 -8
- package/dist/index.js.map +1 -1
- package/dist/{raster-image-canvas-nK9kM9UJ.d.cts → raster-image-canvas-ByaCKEVw.d.cts} +35 -1
- package/dist/{raster-image-canvas-CCOmB4NY.d.ts → raster-image-canvas-D3ZrySjr.d.ts} +35 -1
- package/dist/react.cjs +178 -15
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +13 -6
- package/dist/react.d.ts +13 -6
- package/dist/react.js +178 -15
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/realtime.js.map +1 -1
- package/dist/{types-CMuEaiM7.d.ts → types-C5wxwquF.d.ts} +1 -1
- package/dist/{types-D402X18k.d.cts → types-DOUBapS4.d.cts} +1 -1
- package/package.json +1 -1
|
@@ -22,6 +22,8 @@ type VectorViewportAssetUploadRequest = {
|
|
|
22
22
|
file: File;
|
|
23
23
|
/** High-level bucket for routing image vs PDF upload behavior. */
|
|
24
24
|
kind: VectorViewportAssetKind;
|
|
25
|
+
/** Optional lifecycle signal for cancelling in-flight uploads. */
|
|
26
|
+
signal?: AbortSignal;
|
|
25
27
|
};
|
|
26
28
|
/**
|
|
27
29
|
* Persisted metadata returned by a custom asset upload.
|
|
@@ -179,6 +181,37 @@ type RasterImageCanvasRenderRequest = {
|
|
|
179
181
|
cameraZoom: number;
|
|
180
182
|
devicePixelRatio: number;
|
|
181
183
|
};
|
|
184
|
+
/**
|
|
185
|
+
* Bitmap-like source returned by `imageCanvasRendering.resolveCanvasSource`.
|
|
186
|
+
*
|
|
187
|
+
* Apps can render into an offscreen canvas, create an `ImageBitmap`, or wrap any
|
|
188
|
+
* other canvas-compatible source and let Canvu copy it into the visible canvas
|
|
189
|
+
* without changing the underlying SVG image URL.
|
|
190
|
+
*/
|
|
191
|
+
type RasterImageCanvasSource = {
|
|
192
|
+
width: number;
|
|
193
|
+
height: number;
|
|
194
|
+
draw: (context: CanvasRenderingContext2D) => void;
|
|
195
|
+
close?: () => void;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Input passed to `imageCanvasRendering.resolveCanvasSource`.
|
|
199
|
+
*
|
|
200
|
+
* Use this for custom async rendering pipelines such as PDF page rasterization.
|
|
201
|
+
* Canvu keeps the previous canvas visible while this request resolves and aborts
|
|
202
|
+
* stale requests when the item leaves the viewport or a sharper target is queued.
|
|
203
|
+
*/
|
|
204
|
+
type RasterImageCanvasSourceRequest = RasterImageCanvasRenderRequest & {
|
|
205
|
+
targetHref: string;
|
|
206
|
+
sourceKey: string;
|
|
207
|
+
signal: AbortSignal;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Maps an image item plus requested bitmap size to a custom canvas source.
|
|
211
|
+
*
|
|
212
|
+
* Return `null`/`undefined` to let Canvu fetch and decode the resolved URL.
|
|
213
|
+
*/
|
|
214
|
+
type RasterImageCanvasSourceResolver = (request: RasterImageCanvasSourceRequest) => RasterImageCanvasSource | null | undefined | Promise<RasterImageCanvasSource | null | undefined>;
|
|
182
215
|
/**
|
|
183
216
|
* Resolved raster source for a zoom-aware canvas redraw.
|
|
184
217
|
*
|
|
@@ -209,6 +242,7 @@ type RasterImageCanvasRenderTargetResolver = (request: RasterImageCanvasRenderRe
|
|
|
209
242
|
type RasterImageCanvasRenderingOptions = {
|
|
210
243
|
resolveSourceSize?: RasterImageCanvasSourceSizeResolver;
|
|
211
244
|
resolveRenderTarget?: RasterImageCanvasRenderTargetResolver;
|
|
245
|
+
resolveCanvasSource?: RasterImageCanvasSourceResolver;
|
|
212
246
|
devicePixelRatio?: number;
|
|
213
247
|
pixelHeadroom?: number;
|
|
214
248
|
maxPixelCount?: number;
|
|
@@ -216,4 +250,4 @@ type RasterImageCanvasRenderingOptions = {
|
|
|
216
250
|
upscaleRedrawRatio?: number;
|
|
217
251
|
};
|
|
218
252
|
|
|
219
|
-
export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d,
|
|
253
|
+
export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d, RasterImageCanvasSource as e, RasterImageCanvasSourceRequest as f, RasterImageCanvasSourceResolver as g, RasterImageCanvasSourceSizeRequest as h, RasterImageCanvasSourceSizeResolver as i, VectorViewportAssetHydrationRequest as j, VectorViewportAssetResolveRequest as k, VectorViewportAssetResolveResult as l, VectorViewportAssetUploadRequest as m, VectorViewportAssetUploadResult as n };
|
|
@@ -22,6 +22,8 @@ type VectorViewportAssetUploadRequest = {
|
|
|
22
22
|
file: File;
|
|
23
23
|
/** High-level bucket for routing image vs PDF upload behavior. */
|
|
24
24
|
kind: VectorViewportAssetKind;
|
|
25
|
+
/** Optional lifecycle signal for cancelling in-flight uploads. */
|
|
26
|
+
signal?: AbortSignal;
|
|
25
27
|
};
|
|
26
28
|
/**
|
|
27
29
|
* Persisted metadata returned by a custom asset upload.
|
|
@@ -179,6 +181,37 @@ type RasterImageCanvasRenderRequest = {
|
|
|
179
181
|
cameraZoom: number;
|
|
180
182
|
devicePixelRatio: number;
|
|
181
183
|
};
|
|
184
|
+
/**
|
|
185
|
+
* Bitmap-like source returned by `imageCanvasRendering.resolveCanvasSource`.
|
|
186
|
+
*
|
|
187
|
+
* Apps can render into an offscreen canvas, create an `ImageBitmap`, or wrap any
|
|
188
|
+
* other canvas-compatible source and let Canvu copy it into the visible canvas
|
|
189
|
+
* without changing the underlying SVG image URL.
|
|
190
|
+
*/
|
|
191
|
+
type RasterImageCanvasSource = {
|
|
192
|
+
width: number;
|
|
193
|
+
height: number;
|
|
194
|
+
draw: (context: CanvasRenderingContext2D) => void;
|
|
195
|
+
close?: () => void;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Input passed to `imageCanvasRendering.resolveCanvasSource`.
|
|
199
|
+
*
|
|
200
|
+
* Use this for custom async rendering pipelines such as PDF page rasterization.
|
|
201
|
+
* Canvu keeps the previous canvas visible while this request resolves and aborts
|
|
202
|
+
* stale requests when the item leaves the viewport or a sharper target is queued.
|
|
203
|
+
*/
|
|
204
|
+
type RasterImageCanvasSourceRequest = RasterImageCanvasRenderRequest & {
|
|
205
|
+
targetHref: string;
|
|
206
|
+
sourceKey: string;
|
|
207
|
+
signal: AbortSignal;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Maps an image item plus requested bitmap size to a custom canvas source.
|
|
211
|
+
*
|
|
212
|
+
* Return `null`/`undefined` to let Canvu fetch and decode the resolved URL.
|
|
213
|
+
*/
|
|
214
|
+
type RasterImageCanvasSourceResolver = (request: RasterImageCanvasSourceRequest) => RasterImageCanvasSource | null | undefined | Promise<RasterImageCanvasSource | null | undefined>;
|
|
182
215
|
/**
|
|
183
216
|
* Resolved raster source for a zoom-aware canvas redraw.
|
|
184
217
|
*
|
|
@@ -209,6 +242,7 @@ type RasterImageCanvasRenderTargetResolver = (request: RasterImageCanvasRenderRe
|
|
|
209
242
|
type RasterImageCanvasRenderingOptions = {
|
|
210
243
|
resolveSourceSize?: RasterImageCanvasSourceSizeResolver;
|
|
211
244
|
resolveRenderTarget?: RasterImageCanvasRenderTargetResolver;
|
|
245
|
+
resolveCanvasSource?: RasterImageCanvasSourceResolver;
|
|
212
246
|
devicePixelRatio?: number;
|
|
213
247
|
pixelHeadroom?: number;
|
|
214
248
|
maxPixelCount?: number;
|
|
@@ -216,4 +250,4 @@ type RasterImageCanvasRenderingOptions = {
|
|
|
216
250
|
upscaleRedrawRatio?: number;
|
|
217
251
|
};
|
|
218
252
|
|
|
219
|
-
export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d,
|
|
253
|
+
export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d, RasterImageCanvasSource as e, RasterImageCanvasSourceRequest as f, RasterImageCanvasSourceResolver as g, RasterImageCanvasSourceSizeRequest as h, RasterImageCanvasSourceSizeResolver as i, VectorViewportAssetHydrationRequest as j, VectorViewportAssetResolveRequest as k, VectorViewportAssetResolveResult as l, VectorViewportAssetUploadRequest as m, VectorViewportAssetUploadResult as n };
|
package/dist/react.cjs
CHANGED
|
@@ -1208,7 +1208,8 @@ function getPdfJs() {
|
|
|
1208
1208
|
}
|
|
1209
1209
|
return pdfjsPromise;
|
|
1210
1210
|
}
|
|
1211
|
-
async function renderPageToCanvas(page, scale) {
|
|
1211
|
+
async function renderPageToCanvas(page, scale, signal) {
|
|
1212
|
+
throwIfAborted(signal);
|
|
1212
1213
|
const raw = page.getViewport({ scale: 1 });
|
|
1213
1214
|
const adjustedScale = Math.round(raw.width * scale) / raw.width;
|
|
1214
1215
|
const viewport = page.getViewport({ scale: adjustedScale });
|
|
@@ -1221,22 +1222,48 @@ async function renderPageToCanvas(page, scale) {
|
|
|
1221
1222
|
if (!ctx) throw new Error("Canvas 2D context unavailable");
|
|
1222
1223
|
ctx.imageSmoothingEnabled = true;
|
|
1223
1224
|
ctx.imageSmoothingQuality = "high";
|
|
1224
|
-
|
|
1225
|
+
const renderTask = page.render({ canvas, viewport });
|
|
1226
|
+
if (signal) {
|
|
1227
|
+
const abortRender = () => {
|
|
1228
|
+
renderTask.cancel();
|
|
1229
|
+
};
|
|
1230
|
+
signal.addEventListener("abort", abortRender, { once: true });
|
|
1231
|
+
try {
|
|
1232
|
+
await renderTask.promise;
|
|
1233
|
+
} catch (error) {
|
|
1234
|
+
if (signal.aborted) throw createAbortError();
|
|
1235
|
+
throw error;
|
|
1236
|
+
} finally {
|
|
1237
|
+
signal.removeEventListener("abort", abortRender);
|
|
1238
|
+
}
|
|
1239
|
+
} else {
|
|
1240
|
+
await renderTask.promise;
|
|
1241
|
+
}
|
|
1242
|
+
throwIfAborted(signal);
|
|
1225
1243
|
return { canvas, width: w, height: h };
|
|
1226
1244
|
}
|
|
1245
|
+
function createAbortError() {
|
|
1246
|
+
return new DOMException("Aborted", "AbortError");
|
|
1247
|
+
}
|
|
1248
|
+
function throwIfAborted(signal) {
|
|
1249
|
+
if (signal?.aborted) {
|
|
1250
|
+
throw createAbortError();
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1227
1253
|
function normalizePdfPageNumbers(pageNumbers, pageCount) {
|
|
1228
1254
|
if (!pageNumbers || pageNumbers.length === 0) {
|
|
1229
1255
|
return Array.from({ length: pageCount }, (_, index) => index + 1);
|
|
1230
1256
|
}
|
|
1231
1257
|
return [...new Set(pageNumbers)].filter((pageNumber) => pageNumber >= 1 && pageNumber <= pageCount).sort((left, right) => left - right);
|
|
1232
1258
|
}
|
|
1233
|
-
async function runWithConcurrency(items, concurrency, execute) {
|
|
1259
|
+
async function runWithConcurrency(items, concurrency, execute, signal) {
|
|
1234
1260
|
const results = new Array(items.length);
|
|
1235
1261
|
let nextIndex = 0;
|
|
1236
1262
|
const workerCount = Math.max(1, Math.min(concurrency, items.length));
|
|
1237
1263
|
await Promise.all(
|
|
1238
1264
|
Array.from({ length: workerCount }, async () => {
|
|
1239
1265
|
while (nextIndex < items.length) {
|
|
1266
|
+
throwIfAborted(signal);
|
|
1240
1267
|
const currentIndex = nextIndex;
|
|
1241
1268
|
nextIndex += 1;
|
|
1242
1269
|
const item = items[currentIndex];
|
|
@@ -1244,6 +1271,7 @@ async function runWithConcurrency(items, concurrency, execute) {
|
|
|
1244
1271
|
continue;
|
|
1245
1272
|
}
|
|
1246
1273
|
results[currentIndex] = await execute(item);
|
|
1274
|
+
throwIfAborted(signal);
|
|
1247
1275
|
}
|
|
1248
1276
|
})
|
|
1249
1277
|
);
|
|
@@ -1253,9 +1281,49 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1253
1281
|
const scale = options?.scale ?? 1.5;
|
|
1254
1282
|
const pageConcurrency = options?.pageConcurrency ?? 2;
|
|
1255
1283
|
const storeThumbnails = options?.storeThumbnails ?? false;
|
|
1284
|
+
const signal = options?.signal;
|
|
1285
|
+
throwIfAborted(signal);
|
|
1256
1286
|
const pdfjs = await getPdfJs();
|
|
1287
|
+
throwIfAborted(signal);
|
|
1257
1288
|
const arrayBuffer = await file.arrayBuffer();
|
|
1258
|
-
|
|
1289
|
+
throwIfAborted(signal);
|
|
1290
|
+
const loadingTask = pdfjs.getDocument({ data: arrayBuffer });
|
|
1291
|
+
if (signal) {
|
|
1292
|
+
const abortLoading = () => {
|
|
1293
|
+
void loadingTask.destroy();
|
|
1294
|
+
};
|
|
1295
|
+
signal.addEventListener("abort", abortLoading, { once: true });
|
|
1296
|
+
try {
|
|
1297
|
+
const pdf2 = await loadingTask.promise;
|
|
1298
|
+
signal.removeEventListener("abort", abortLoading);
|
|
1299
|
+
return await loadPdfDocumentToStore(pdf2, store, {
|
|
1300
|
+
scale,
|
|
1301
|
+
pageNumbers: options?.pageNumbers,
|
|
1302
|
+
pageConcurrency,
|
|
1303
|
+
storeThumbnails,
|
|
1304
|
+
signal,
|
|
1305
|
+
onPageStored: options?.onPageStored
|
|
1306
|
+
});
|
|
1307
|
+
} catch (error) {
|
|
1308
|
+
if (signal.aborted) throw createAbortError();
|
|
1309
|
+
throw error;
|
|
1310
|
+
} finally {
|
|
1311
|
+
signal.removeEventListener("abort", abortLoading);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
const pdf = await loadingTask.promise;
|
|
1315
|
+
return await loadPdfDocumentToStore(pdf, store, {
|
|
1316
|
+
scale,
|
|
1317
|
+
pageNumbers: options?.pageNumbers,
|
|
1318
|
+
pageConcurrency,
|
|
1319
|
+
storeThumbnails,
|
|
1320
|
+
onPageStored: options?.onPageStored
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
async function loadPdfDocumentToStore(pdf, store, options) {
|
|
1324
|
+
const { pageConcurrency, scale, signal } = options;
|
|
1325
|
+
const storeThumbnails = options.storeThumbnails ?? false;
|
|
1326
|
+
throwIfAborted(signal);
|
|
1259
1327
|
const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
|
|
1260
1328
|
const bufferedResults = /* @__PURE__ */ new Map();
|
|
1261
1329
|
let nextEmitIndex = 0;
|
|
@@ -1270,7 +1338,9 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1270
1338
|
if (!bufferedResult) break;
|
|
1271
1339
|
bufferedResults.delete(nextPageNumber);
|
|
1272
1340
|
nextEmitIndex += 1;
|
|
1341
|
+
throwIfAborted(signal);
|
|
1273
1342
|
await options?.onPageStored?.(bufferedResult);
|
|
1343
|
+
throwIfAborted(signal);
|
|
1274
1344
|
}
|
|
1275
1345
|
};
|
|
1276
1346
|
const nextChain = emitChain.then(run, run);
|
|
@@ -1282,11 +1352,20 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1282
1352
|
pageNumbers,
|
|
1283
1353
|
pageConcurrency,
|
|
1284
1354
|
async (pageNumber) => {
|
|
1355
|
+
throwIfAborted(signal);
|
|
1285
1356
|
const page = await pdf.getPage(pageNumber);
|
|
1286
|
-
|
|
1357
|
+
throwIfAborted(signal);
|
|
1358
|
+
const { canvas, width, height } = await renderPageToCanvas(
|
|
1359
|
+
page,
|
|
1360
|
+
scale,
|
|
1361
|
+
signal
|
|
1362
|
+
);
|
|
1363
|
+
throwIfAborted(signal);
|
|
1287
1364
|
const mime = "image/png";
|
|
1288
1365
|
const pageBlob = await encodeCanvasToBlob(canvas, { mimeType: mime });
|
|
1366
|
+
throwIfAborted(signal);
|
|
1289
1367
|
const blobId = await store.storeOriginal(pageBlob);
|
|
1368
|
+
throwIfAborted(signal);
|
|
1290
1369
|
const thumbnailBlobId = storeThumbnails ? await (async () => {
|
|
1291
1370
|
const thumbScale = Math.min(1, 256 / Math.max(width, height));
|
|
1292
1371
|
const tw = Math.max(1, Math.round(width * thumbScale));
|
|
@@ -1303,6 +1382,7 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1303
1382
|
const thumbBlob = await encodeCanvasToBlob(thumbCanvas, {
|
|
1304
1383
|
mimeType: mime
|
|
1305
1384
|
});
|
|
1385
|
+
throwIfAborted(signal);
|
|
1306
1386
|
return await store.storeThumbnail(thumbBlob);
|
|
1307
1387
|
})() : "";
|
|
1308
1388
|
const pageResult = {
|
|
@@ -1314,7 +1394,8 @@ async function loadPdfToStore(file, store, options) {
|
|
|
1314
1394
|
};
|
|
1315
1395
|
await queuePageEmission(pageResult);
|
|
1316
1396
|
return pageResult;
|
|
1317
|
-
}
|
|
1397
|
+
},
|
|
1398
|
+
signal
|
|
1318
1399
|
);
|
|
1319
1400
|
}
|
|
1320
1401
|
|
|
@@ -1655,9 +1736,22 @@ function finalizeIngestedItem(item, context, uploadResult, decorateItem) {
|
|
|
1655
1736
|
const itemWithAssetData = applyAssetUploadResultToItem(item, uploadResult);
|
|
1656
1737
|
return decorateItem ? decorateItem(itemWithAssetData, context) : itemWithAssetData;
|
|
1657
1738
|
}
|
|
1658
|
-
|
|
1739
|
+
function createAbortError2() {
|
|
1740
|
+
return new DOMException("Aborted", "AbortError");
|
|
1741
|
+
}
|
|
1742
|
+
function throwIfAborted2(signal) {
|
|
1743
|
+
if (signal?.aborted) {
|
|
1744
|
+
throw createAbortError2();
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
function isAbortError(error) {
|
|
1748
|
+
return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
|
|
1749
|
+
}
|
|
1750
|
+
async function uploadAssetIfNeeded(assetStore, file, kind, signal) {
|
|
1751
|
+
throwIfAborted2(signal);
|
|
1659
1752
|
if (!assetStore) return null;
|
|
1660
|
-
const result = await assetStore.upload({ file, kind });
|
|
1753
|
+
const result = await assetStore.upload({ file, kind, signal });
|
|
1754
|
+
throwIfAborted2(signal);
|
|
1661
1755
|
return result ?? null;
|
|
1662
1756
|
}
|
|
1663
1757
|
async function ingestAssetFilesToSceneItems(options) {
|
|
@@ -1671,6 +1765,7 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1671
1765
|
gapWorld = 16,
|
|
1672
1766
|
pdfScale = 1.15,
|
|
1673
1767
|
pdfPageConcurrency = 2,
|
|
1768
|
+
signal,
|
|
1674
1769
|
decorateItem,
|
|
1675
1770
|
onItemsReady,
|
|
1676
1771
|
onError
|
|
@@ -1679,6 +1774,7 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1679
1774
|
const errors = [];
|
|
1680
1775
|
let occupiedBottomY = existingItems.length > 0 ? Math.max(...existingItems.map((item) => item.bounds.y + item.bounds.height)) : null;
|
|
1681
1776
|
for (const file of files) {
|
|
1777
|
+
throwIfAborted2(signal);
|
|
1682
1778
|
const kind = getAssetKindForFile(file);
|
|
1683
1779
|
if (!kind) {
|
|
1684
1780
|
const error = {
|
|
@@ -1691,14 +1787,23 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1691
1787
|
}
|
|
1692
1788
|
try {
|
|
1693
1789
|
if (kind === "pdf") {
|
|
1694
|
-
const uploadResultPromise = uploadAssetIfNeeded(
|
|
1790
|
+
const uploadResultPromise = uploadAssetIfNeeded(
|
|
1791
|
+
assetStore,
|
|
1792
|
+
file,
|
|
1793
|
+
kind,
|
|
1794
|
+
signal
|
|
1795
|
+
);
|
|
1796
|
+
void uploadResultPromise.catch(() => void 0);
|
|
1695
1797
|
await loadPdfToStore(file, imageStore, {
|
|
1696
1798
|
scale: pdfScale,
|
|
1697
1799
|
pageConcurrency: pdfPageConcurrency,
|
|
1698
1800
|
storeThumbnails: false,
|
|
1801
|
+
signal,
|
|
1699
1802
|
onPageStored: async (page) => {
|
|
1803
|
+
throwIfAborted2(signal);
|
|
1700
1804
|
const uploadResult2 = await uploadResultPromise;
|
|
1701
1805
|
const fullUrl2 = await createBlobUrlFromStore(imageStore, page.blobId);
|
|
1806
|
+
throwIfAborted2(signal);
|
|
1702
1807
|
const naturalTopY2 = worldCenter.y - page.height / 2;
|
|
1703
1808
|
const stackedTopY2 = occupiedBottomY == null ? naturalTopY2 : occupiedBottomY + gapWorld;
|
|
1704
1809
|
const bounds2 = {
|
|
@@ -1738,15 +1843,18 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1738
1843
|
);
|
|
1739
1844
|
items.push(item2);
|
|
1740
1845
|
occupiedBottomY = bounds2.y + page.height;
|
|
1846
|
+
throwIfAborted2(signal);
|
|
1741
1847
|
onItemsReady?.([item2], { file, kind });
|
|
1742
1848
|
}
|
|
1743
1849
|
});
|
|
1744
1850
|
continue;
|
|
1745
1851
|
}
|
|
1852
|
+
throwIfAborted2(signal);
|
|
1746
1853
|
const [uploadResult, storedImage] = await Promise.all([
|
|
1747
|
-
uploadAssetIfNeeded(assetStore, file, kind),
|
|
1854
|
+
uploadAssetIfNeeded(assetStore, file, kind, signal),
|
|
1748
1855
|
loadImageToStore(file, imageStore)
|
|
1749
1856
|
]);
|
|
1857
|
+
throwIfAborted2(signal);
|
|
1750
1858
|
const { blobId, thumbnailBlobId, width, height } = storedImage;
|
|
1751
1859
|
const fullUrl = await createBlobUrlFromStore(imageStore, blobId);
|
|
1752
1860
|
const thumbBlob = await imageStore.getThumbnail(thumbnailBlobId);
|
|
@@ -1784,9 +1892,13 @@ async function ingestAssetFilesToSceneItems(options) {
|
|
|
1784
1892
|
decorateItem
|
|
1785
1893
|
);
|
|
1786
1894
|
items.push(item);
|
|
1895
|
+
throwIfAborted2(signal);
|
|
1787
1896
|
onItemsReady?.([item], { file, kind });
|
|
1788
1897
|
occupiedBottomY = occupiedBottomY == null ? bounds.y + height : Math.max(occupiedBottomY, bounds.y + height);
|
|
1789
1898
|
} catch (error) {
|
|
1899
|
+
if (isAbortError(error)) {
|
|
1900
|
+
throw error;
|
|
1901
|
+
}
|
|
1790
1902
|
const fileError = {
|
|
1791
1903
|
file,
|
|
1792
1904
|
kind,
|
|
@@ -6896,6 +7008,7 @@ function resolveRasterImageCanvasRenderingOptions(options) {
|
|
|
6896
7008
|
return {
|
|
6897
7009
|
resolveSourceSize: options.resolveSourceSize,
|
|
6898
7010
|
resolveRenderTarget: options.resolveRenderTarget,
|
|
7011
|
+
resolveCanvasSource: options.resolveCanvasSource,
|
|
6899
7012
|
devicePixelRatio: toPositiveFiniteNumber(
|
|
6900
7013
|
options.devicePixelRatio,
|
|
6901
7014
|
fallbackDevicePixelRatio
|
|
@@ -7160,6 +7273,36 @@ function loadImageElement(href, signal) {
|
|
|
7160
7273
|
image.src = href;
|
|
7161
7274
|
});
|
|
7162
7275
|
}
|
|
7276
|
+
function normalizeDecodedRasterImageSource(source) {
|
|
7277
|
+
if (!source) return null;
|
|
7278
|
+
const width = Math.max(1, Math.round(source.width));
|
|
7279
|
+
const height = Math.max(1, Math.round(source.height));
|
|
7280
|
+
if (!Number.isFinite(width) || !Number.isFinite(height)) return null;
|
|
7281
|
+
return {
|
|
7282
|
+
width,
|
|
7283
|
+
height,
|
|
7284
|
+
draw: source.draw,
|
|
7285
|
+
close: source.close ?? (() => {
|
|
7286
|
+
})
|
|
7287
|
+
};
|
|
7288
|
+
}
|
|
7289
|
+
async function resolveDecodedRasterImageSource({
|
|
7290
|
+
options,
|
|
7291
|
+
request,
|
|
7292
|
+
width,
|
|
7293
|
+
height,
|
|
7294
|
+
signal
|
|
7295
|
+
}) {
|
|
7296
|
+
if (options?.resolveCanvasSource) {
|
|
7297
|
+
const source = await options.resolveCanvasSource({
|
|
7298
|
+
...request,
|
|
7299
|
+
signal
|
|
7300
|
+
});
|
|
7301
|
+
const decoded = normalizeDecodedRasterImageSource(source);
|
|
7302
|
+
if (decoded) return decoded;
|
|
7303
|
+
}
|
|
7304
|
+
return decodeRasterImage(request.targetHref, width, height, signal);
|
|
7305
|
+
}
|
|
7163
7306
|
var SvgVectorRenderer = class {
|
|
7164
7307
|
container;
|
|
7165
7308
|
scene;
|
|
@@ -7392,7 +7535,20 @@ var SvgVectorRenderer = class {
|
|
|
7392
7535
|
}
|
|
7393
7536
|
const request = {
|
|
7394
7537
|
itemHref: item.imageRasterHref,
|
|
7395
|
-
target
|
|
7538
|
+
target,
|
|
7539
|
+
sourceRequest: {
|
|
7540
|
+
item,
|
|
7541
|
+
href: item.imageRasterHref,
|
|
7542
|
+
intrinsicSize: item.imageIntrinsicSize,
|
|
7543
|
+
sourceSize,
|
|
7544
|
+
contentRect: target.contentRect,
|
|
7545
|
+
targetSize: target.targetSize,
|
|
7546
|
+
viewportSize,
|
|
7547
|
+
cameraZoom: this.camera.zoom,
|
|
7548
|
+
devicePixelRatio: options.devicePixelRatio,
|
|
7549
|
+
targetHref: target.href,
|
|
7550
|
+
sourceKey: target.sourceKey
|
|
7551
|
+
}
|
|
7396
7552
|
};
|
|
7397
7553
|
if (rasterCanvas.abortController) {
|
|
7398
7554
|
if (rasterCanvas.loadingItemHref !== item.imageRasterHref) {
|
|
@@ -7482,7 +7638,13 @@ var SvgVectorRenderer = class {
|
|
|
7482
7638
|
rasterCanvas.loadingWidth = width;
|
|
7483
7639
|
rasterCanvas.loadingHeight = height;
|
|
7484
7640
|
rasterCanvas.queuedTarget = null;
|
|
7485
|
-
|
|
7641
|
+
resolveDecodedRasterImageSource({
|
|
7642
|
+
options: this.rasterImageCanvasRendering,
|
|
7643
|
+
request: request.sourceRequest,
|
|
7644
|
+
width,
|
|
7645
|
+
height,
|
|
7646
|
+
signal: abortController.signal
|
|
7647
|
+
}).then((decoded) => {
|
|
7486
7648
|
if (abortController.signal.aborted || rasterCanvas.loadSequence !== sequence) {
|
|
7487
7649
|
decoded.close();
|
|
7488
7650
|
return;
|
|
@@ -8391,6 +8553,7 @@ function shallowEqualStringArray(a, b) {
|
|
|
8391
8553
|
}
|
|
8392
8554
|
|
|
8393
8555
|
// src/react/stroke-input.ts
|
|
8556
|
+
var MAX_INTERPOLATED_POINTS_PER_SAMPLE = 192;
|
|
8394
8557
|
function getPointerEventSamples(event) {
|
|
8395
8558
|
if (typeof event.getCoalescedEvents !== "function") {
|
|
8396
8559
|
return [event];
|
|
@@ -8414,9 +8577,9 @@ function appendInterpolatedStrokePoint(points, nextPoint, maxStepWorld) {
|
|
|
8414
8577
|
const distanceSquared = deltaX * deltaX + deltaY * deltaY;
|
|
8415
8578
|
if (distanceSquared < 1e-12) return points;
|
|
8416
8579
|
const distance = Math.sqrt(distanceSquared);
|
|
8417
|
-
const stepCount = Math.
|
|
8418
|
-
|
|
8419
|
-
Math.ceil(distance / resolveMaxStepWorld(maxStepWorld))
|
|
8580
|
+
const stepCount = Math.min(
|
|
8581
|
+
MAX_INTERPOLATED_POINTS_PER_SAMPLE,
|
|
8582
|
+
Math.max(1, Math.ceil(distance / resolveMaxStepWorld(maxStepWorld)))
|
|
8420
8583
|
);
|
|
8421
8584
|
if (stepCount === 1) return [...points, nextPoint];
|
|
8422
8585
|
const interpolatedPoints = Array.from({ length: stepCount }, (_, index) => {
|