canvu-react 0.4.75 → 0.4.76

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/react.js CHANGED
@@ -1186,342 +1186,6 @@ async function createThumbnailBlobUrlFromStore(store, thumbnailBlobId) {
1186
1186
  return URL.createObjectURL(blob);
1187
1187
  }
1188
1188
 
1189
- // src/image/pdf-worker-renderer.ts
1190
- var PDF_WORKER_SOURCE = `
1191
- let pdfjsPromise = null;
1192
-
1193
- const loadPdfJs = async (pdfjsModuleCandidates) => {
1194
- if (!pdfjsPromise) {
1195
- pdfjsPromise = (async () => {
1196
- let lastError;
1197
- for (const candidate of pdfjsModuleCandidates) {
1198
- try {
1199
- const pdfjs = await import(candidate.moduleUrl);
1200
- if (pdfjs.GlobalWorkerOptions) {
1201
- pdfjs.GlobalWorkerOptions.workerSrc = candidate.workerUrl;
1202
- }
1203
- return pdfjs;
1204
- } catch (error) {
1205
- lastError = error;
1206
- }
1207
- }
1208
- throw lastError ?? new Error("Unable to load pdfjs-dist");
1209
- })();
1210
- }
1211
- return await pdfjsPromise;
1212
- };
1213
-
1214
- const createErrorPayload = (error) => ({
1215
- message: error instanceof Error ? error.message : String(error),
1216
- name: error instanceof Error ? error.name : "Error",
1217
- stack: error instanceof Error ? error.stack : undefined,
1218
- });
1219
-
1220
- const normalizePdfPageNumbers = (pageNumbers, pageCount) => {
1221
- if (!Array.isArray(pageNumbers) || pageNumbers.length === 0) {
1222
- return Array.from({ length: pageCount }, (_, index) => index + 1);
1223
- }
1224
- return [...new Set(pageNumbers)]
1225
- .filter((pageNumber) => pageNumber >= 1 && pageNumber <= pageCount)
1226
- .sort((left, right) => left - right);
1227
- };
1228
-
1229
- const runWithConcurrency = async (items, concurrency, execute) => {
1230
- const results = new Array(items.length);
1231
- let nextIndex = 0;
1232
- const safeConcurrency = Number.isFinite(concurrency) && concurrency > 0
1233
- ? Math.round(concurrency)
1234
- : 1;
1235
- const workerCount = Math.max(1, Math.min(safeConcurrency, items.length));
1236
- await Promise.all(
1237
- Array.from({ length: workerCount }, async () => {
1238
- while (nextIndex < items.length) {
1239
- const currentIndex = nextIndex;
1240
- nextIndex += 1;
1241
- const item = items[currentIndex];
1242
- if (item === undefined) {
1243
- continue;
1244
- }
1245
- results[currentIndex] = await execute(item);
1246
- }
1247
- }),
1248
- );
1249
- return results;
1250
- };
1251
-
1252
- const renderPageToBlob = async (page, scale, storeThumbnails) => {
1253
- const raw = page.getViewport({ scale: 1 });
1254
- const adjustedScale = Math.round(raw.width * scale) / raw.width;
1255
- const viewport = page.getViewport({ scale: adjustedScale });
1256
- const width = Math.round(viewport.width);
1257
- const height = Math.round(viewport.height);
1258
- const canvas = new OffscreenCanvas(width, height);
1259
- const canvasContext = canvas.getContext("2d");
1260
- if (!canvasContext) {
1261
- throw new Error("OffscreenCanvas 2D context unavailable");
1262
- }
1263
- canvasContext.imageSmoothingEnabled = true;
1264
- canvasContext.imageSmoothingQuality = "high";
1265
- await page.render({ canvasContext, viewport }).promise;
1266
- const blob = await canvas.convertToBlob({ type: "image/png" });
1267
- let thumbnailBlob;
1268
- if (storeThumbnails) {
1269
- const thumbScale = Math.min(1, 256 / Math.max(width, height));
1270
- const thumbnailWidth = Math.max(1, Math.round(width * thumbScale));
1271
- const thumbnailHeight = Math.max(1, Math.round(height * thumbScale));
1272
- const thumbnailCanvas = new OffscreenCanvas(thumbnailWidth, thumbnailHeight);
1273
- const thumbnailContext = thumbnailCanvas.getContext("2d");
1274
- if (thumbnailContext) {
1275
- thumbnailContext.imageSmoothingEnabled = true;
1276
- thumbnailContext.imageSmoothingQuality = "high";
1277
- thumbnailContext.drawImage(canvas, 0, 0, thumbnailWidth, thumbnailHeight);
1278
- }
1279
- thumbnailBlob = await thumbnailCanvas.convertToBlob({ type: "image/png" });
1280
- }
1281
- return { blob, height, thumbnailBlob, width };
1282
- };
1283
-
1284
- self.onmessage = async (event) => {
1285
- const message = event.data;
1286
- if (!message || message.type !== "render") {
1287
- return;
1288
- }
1289
- try {
1290
- const pdfjs = await loadPdfJs(message.pdfjsModuleCandidates);
1291
- const pdf = await pdfjs.getDocument({
1292
- data: new Uint8Array(message.pdfData),
1293
- disableWorker: true,
1294
- }).promise;
1295
- try {
1296
- const pageNumbers = normalizePdfPageNumbers(message.pageNumbers, pdf.numPages);
1297
- const bufferedPages = new Map();
1298
- let nextEmitIndex = 0;
1299
- let emitChain = Promise.resolve();
1300
- const emitPageInOrder = async (pageNumber, renderedPage) => {
1301
- bufferedPages.set(pageNumber, renderedPage);
1302
- const flush = () => {
1303
- while (nextEmitIndex < pageNumbers.length) {
1304
- const nextPageNumber = pageNumbers[nextEmitIndex];
1305
- if (nextPageNumber == null) break;
1306
- const nextPage = bufferedPages.get(nextPageNumber);
1307
- if (!nextPage) break;
1308
- bufferedPages.delete(nextPageNumber);
1309
- nextEmitIndex += 1;
1310
- self.postMessage({
1311
- type: "page",
1312
- page: {
1313
- ...nextPage,
1314
- pageNumber: nextPageNumber,
1315
- },
1316
- });
1317
- }
1318
- };
1319
- const nextChain = emitChain.then(flush, flush);
1320
- emitChain = nextChain.catch(() => {});
1321
- await nextChain;
1322
- };
1323
- await runWithConcurrency(
1324
- pageNumbers,
1325
- message.pageConcurrency,
1326
- async (pageNumber) => {
1327
- const page = await pdf.getPage(pageNumber);
1328
- try {
1329
- const renderedPage = await renderPageToBlob(
1330
- page,
1331
- message.scale,
1332
- message.storeThumbnails,
1333
- );
1334
- await emitPageInOrder(pageNumber, renderedPage);
1335
- } finally {
1336
- page.cleanup();
1337
- }
1338
- },
1339
- );
1340
- await emitChain;
1341
- } finally {
1342
- await pdf.destroy();
1343
- }
1344
- self.postMessage({ type: "done" });
1345
- } catch (error) {
1346
- self.postMessage({ type: "error", error: createErrorPayload(error) });
1347
- }
1348
- };
1349
- `;
1350
- var isRecord = (value) => typeof value === "object" && value !== null;
1351
- var hasObjectMembers = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
1352
- var isOffscreenCanvasCandidate = (value) => typeof value === "function";
1353
- var getEnvironmentRecord = (environment) => isRecord(environment) ? environment : null;
1354
- var canUsePdfWorkerRenderer = (environment = globalThis) => {
1355
- const candidateEnvironment = getEnvironmentRecord(environment);
1356
- if (!candidateEnvironment) return false;
1357
- if (typeof candidateEnvironment.Worker !== "function") return false;
1358
- if (typeof candidateEnvironment.Blob !== "function") return false;
1359
- if (!isOffscreenCanvasCandidate(candidateEnvironment.OffscreenCanvas)) {
1360
- return false;
1361
- }
1362
- const urlCandidate = candidateEnvironment.URL;
1363
- if (!hasObjectMembers(urlCandidate)) return false;
1364
- if (typeof urlCandidate.createObjectURL !== "function") return false;
1365
- if (typeof urlCandidate.revokeObjectURL !== "function") return false;
1366
- try {
1367
- const canvas = new candidateEnvironment.OffscreenCanvas(1, 1);
1368
- return typeof canvas.getContext === "function" && typeof canvas.convertToBlob === "function";
1369
- } catch {
1370
- return false;
1371
- }
1372
- };
1373
- var createAbortError = () => new DOMException("Aborted", "AbortError");
1374
- var throwIfAborted = (signal) => {
1375
- if (signal?.aborted) {
1376
- throw createAbortError();
1377
- }
1378
- };
1379
- var createPdfWorker = () => {
1380
- const workerBlob = new Blob([PDF_WORKER_SOURCE], {
1381
- type: "text/javascript"
1382
- });
1383
- const workerUrl = URL.createObjectURL(workerBlob);
1384
- try {
1385
- const worker = new Worker(workerUrl, {
1386
- name: "canvu-pdf-renderer",
1387
- type: "module"
1388
- });
1389
- return {
1390
- release: () => URL.revokeObjectURL(workerUrl),
1391
- worker
1392
- };
1393
- } catch (error) {
1394
- URL.revokeObjectURL(workerUrl);
1395
- throw error;
1396
- }
1397
- };
1398
- var createWorkerError = (message) => {
1399
- const error = new Error(message.error.message);
1400
- error.name = message.error.name;
1401
- error.stack = message.error.stack;
1402
- return error;
1403
- };
1404
- var PACKAGED_PDFJS_MODULE_FILE = "./pdf.mjs";
1405
- var PACKAGED_PDFJS_WORKER_FILE = "./pdf.worker.mjs";
1406
- var resolveRelativeAssetUrl = (path, baseUrl) => new URL(path, baseUrl).toString();
1407
- var resolvePackagedPdfJsModuleCandidate = (baseUrl = import.meta.url) => ({
1408
- moduleUrl: resolveRelativeAssetUrl(PACKAGED_PDFJS_MODULE_FILE, baseUrl),
1409
- workerUrl: resolveRelativeAssetUrl(PACKAGED_PDFJS_WORKER_FILE, baseUrl)
1410
- });
1411
- var resolveBundledPdfJsModuleCandidate = () => ({
1412
- moduleUrl: new URL("pdfjs-dist/build/pdf.min.mjs", import.meta.url).toString(),
1413
- workerUrl: new URL(
1414
- "pdfjs-dist/build/pdf.worker.min.mjs",
1415
- import.meta.url
1416
- ).toString()
1417
- });
1418
- var resolvePdfJsModuleCandidates = () => [
1419
- resolvePackagedPdfJsModuleCandidate(),
1420
- resolveBundledPdfJsModuleCandidate()
1421
- ];
1422
- var loadPdfToStoreWithWorker = async (file, store, options) => {
1423
- throwIfAborted(options.signal);
1424
- const arrayBuffer = await file.arrayBuffer();
1425
- throwIfAborted(options.signal);
1426
- return await new Promise((resolve, reject) => {
1427
- const { release, worker } = createPdfWorker();
1428
- const pageResults = [];
1429
- let storeChain = Promise.resolve();
1430
- let cleanedUp = false;
1431
- let settled = false;
1432
- const cleanup = () => {
1433
- if (cleanedUp) return;
1434
- cleanedUp = true;
1435
- options.signal?.removeEventListener("abort", abortWorker);
1436
- worker.onmessage = null;
1437
- worker.onerror = null;
1438
- worker.terminate();
1439
- release();
1440
- };
1441
- const rejectOnce = (error) => {
1442
- if (settled) return;
1443
- settled = true;
1444
- cleanup();
1445
- reject(error);
1446
- };
1447
- const rejectAfterQueuedStores = (error) => {
1448
- if (settled) return;
1449
- cleanup();
1450
- storeChain.then(() => {
1451
- if (settled) return;
1452
- settled = true;
1453
- reject(error);
1454
- }).catch(rejectOnce);
1455
- };
1456
- function abortWorker() {
1457
- rejectOnce(createAbortError());
1458
- }
1459
- const storePage = (message) => {
1460
- try {
1461
- options.onPageReceived?.({ pageNumber: message.page.pageNumber });
1462
- } catch (error) {
1463
- rejectOnce(error);
1464
- return;
1465
- }
1466
- storeChain = storeChain.then(async () => {
1467
- throwIfAborted(options.signal);
1468
- const blobId = await store.storeOriginal(message.page.blob);
1469
- throwIfAborted(options.signal);
1470
- const thumbnailBlobId = options.storeThumbnails && message.page.thumbnailBlob ? await store.storeThumbnail(message.page.thumbnailBlob) : "";
1471
- throwIfAborted(options.signal);
1472
- const pageResult = {
1473
- blobId,
1474
- height: message.page.height,
1475
- pageNumber: message.page.pageNumber,
1476
- thumbnailBlobId,
1477
- width: message.page.width
1478
- };
1479
- pageResults.push(pageResult);
1480
- await options.onPageStored?.(pageResult);
1481
- throwIfAborted(options.signal);
1482
- });
1483
- void storeChain.catch(rejectOnce);
1484
- };
1485
- worker.onmessage = (event) => {
1486
- const message = event.data;
1487
- if (message.type === "page") {
1488
- storePage(message);
1489
- return;
1490
- }
1491
- if (message.type === "error") {
1492
- rejectAfterQueuedStores(createWorkerError(message));
1493
- return;
1494
- }
1495
- storeChain.then(() => {
1496
- if (settled) return;
1497
- settled = true;
1498
- cleanup();
1499
- resolve(pageResults);
1500
- }).catch(rejectOnce);
1501
- };
1502
- worker.onerror = (event) => {
1503
- rejectAfterQueuedStores(event.error ?? new Error(event.message));
1504
- };
1505
- options.signal?.addEventListener("abort", abortWorker, { once: true });
1506
- try {
1507
- worker.postMessage(
1508
- {
1509
- pdfData: arrayBuffer,
1510
- pdfjsModuleCandidates: resolvePdfJsModuleCandidates(),
1511
- pageNumbers: options.pageNumbers ? [...options.pageNumbers] : void 0,
1512
- pageConcurrency: options.pageConcurrency,
1513
- scale: options.scale,
1514
- storeThumbnails: options.storeThumbnails,
1515
- type: "render"
1516
- },
1517
- [arrayBuffer]
1518
- );
1519
- } catch (error) {
1520
- rejectOnce(error);
1521
- }
1522
- });
1523
- };
1524
-
1525
1189
  // src/image/pdf-loader.ts
1526
1190
  var pdfjsPromise = null;
1527
1191
  function getPdfJs() {
@@ -1538,7 +1202,7 @@ function getPdfJs() {
1538
1202
  return pdfjsPromise;
1539
1203
  }
1540
1204
  async function renderPageToCanvas(page, scale, signal) {
1541
- throwIfAborted2(signal);
1205
+ throwIfAborted(signal);
1542
1206
  const raw = page.getViewport({ scale: 1 });
1543
1207
  const adjustedScale = Math.round(raw.width * scale) / raw.width;
1544
1208
  const viewport = page.getViewport({ scale: adjustedScale });
@@ -1560,7 +1224,7 @@ async function renderPageToCanvas(page, scale, signal) {
1560
1224
  try {
1561
1225
  await renderTask.promise;
1562
1226
  } catch (error) {
1563
- if (signal.aborted) throw createAbortError2();
1227
+ if (signal.aborted) throw createAbortError();
1564
1228
  throw error;
1565
1229
  } finally {
1566
1230
  signal.removeEventListener("abort", abortRender);
@@ -1568,15 +1232,15 @@ async function renderPageToCanvas(page, scale, signal) {
1568
1232
  } else {
1569
1233
  await renderTask.promise;
1570
1234
  }
1571
- throwIfAborted2(signal);
1235
+ throwIfAborted(signal);
1572
1236
  return { canvas, width: w, height: h };
1573
1237
  }
1574
- function createAbortError2() {
1238
+ function createAbortError() {
1575
1239
  return new DOMException("Aborted", "AbortError");
1576
1240
  }
1577
- function throwIfAborted2(signal) {
1241
+ function throwIfAborted(signal) {
1578
1242
  if (signal?.aborted) {
1579
- throw createAbortError2();
1243
+ throw createAbortError();
1580
1244
  }
1581
1245
  }
1582
1246
  function normalizePdfPageNumbers(pageNumbers, pageCount) {
@@ -1592,7 +1256,7 @@ async function runWithConcurrency(items, concurrency, execute, signal) {
1592
1256
  await Promise.all(
1593
1257
  Array.from({ length: workerCount }, async () => {
1594
1258
  while (nextIndex < items.length) {
1595
- throwIfAborted2(signal);
1259
+ throwIfAborted(signal);
1596
1260
  const currentIndex = nextIndex;
1597
1261
  nextIndex += 1;
1598
1262
  const item = items[currentIndex];
@@ -1600,7 +1264,7 @@ async function runWithConcurrency(items, concurrency, execute, signal) {
1600
1264
  continue;
1601
1265
  }
1602
1266
  results[currentIndex] = await execute(item);
1603
- throwIfAborted2(signal);
1267
+ throwIfAborted(signal);
1604
1268
  }
1605
1269
  })
1606
1270
  );
@@ -1611,52 +1275,11 @@ async function loadPdfToStore(file, store, options) {
1611
1275
  const pageConcurrency = options?.pageConcurrency ?? 2;
1612
1276
  const storeThumbnails = options?.storeThumbnails ?? false;
1613
1277
  const signal = options?.signal;
1614
- throwIfAborted2(signal);
1615
- if (canUsePdfWorkerRenderer()) {
1616
- let workerPageCount = 0;
1617
- try {
1618
- return await loadPdfToStoreWithWorker(file, store, {
1619
- scale,
1620
- pageNumbers: options?.pageNumbers,
1621
- pageConcurrency,
1622
- storeThumbnails,
1623
- signal,
1624
- onPageReceived: () => {
1625
- workerPageCount += 1;
1626
- },
1627
- onPageStored: async (page) => {
1628
- await options?.onPageStored?.(page);
1629
- }
1630
- });
1631
- } catch (error) {
1632
- if (signal?.aborted || workerPageCount > 0) {
1633
- throw error;
1634
- }
1635
- }
1636
- }
1637
- return await loadPdfToStoreOnMainThread(file, store, {
1638
- scale,
1639
- pageNumbers: options?.pageNumbers,
1640
- pageConcurrency,
1641
- storeThumbnails,
1642
- signal,
1643
- onPageStored: options?.onPageStored
1644
- });
1645
- }
1646
- async function loadPdfToStoreOnMainThread(file, store, options) {
1647
- const {
1648
- pageConcurrency,
1649
- scale,
1650
- signal,
1651
- storeThumbnails,
1652
- onPageStored,
1653
- pageNumbers
1654
- } = options;
1655
- throwIfAborted2(signal);
1278
+ throwIfAborted(signal);
1656
1279
  const pdfjs = await getPdfJs();
1657
- throwIfAborted2(signal);
1280
+ throwIfAborted(signal);
1658
1281
  const arrayBuffer = await file.arrayBuffer();
1659
- throwIfAborted2(signal);
1282
+ throwIfAborted(signal);
1660
1283
  const loadingTask = pdfjs.getDocument({ data: arrayBuffer });
1661
1284
  if (signal) {
1662
1285
  const abortLoading = () => {
@@ -1668,14 +1291,14 @@ async function loadPdfToStoreOnMainThread(file, store, options) {
1668
1291
  signal.removeEventListener("abort", abortLoading);
1669
1292
  return await loadPdfDocumentToStore(pdf2, store, {
1670
1293
  scale,
1671
- pageNumbers,
1294
+ pageNumbers: options?.pageNumbers,
1672
1295
  pageConcurrency,
1673
1296
  storeThumbnails,
1674
1297
  signal,
1675
- onPageStored
1298
+ onPageStored: options?.onPageStored
1676
1299
  });
1677
1300
  } catch (error) {
1678
- if (signal.aborted) throw createAbortError2();
1301
+ if (signal.aborted) throw createAbortError();
1679
1302
  throw error;
1680
1303
  } finally {
1681
1304
  signal.removeEventListener("abort", abortLoading);
@@ -1684,16 +1307,16 @@ async function loadPdfToStoreOnMainThread(file, store, options) {
1684
1307
  const pdf = await loadingTask.promise;
1685
1308
  return await loadPdfDocumentToStore(pdf, store, {
1686
1309
  scale,
1687
- pageNumbers,
1310
+ pageNumbers: options?.pageNumbers,
1688
1311
  pageConcurrency,
1689
1312
  storeThumbnails,
1690
- onPageStored
1313
+ onPageStored: options?.onPageStored
1691
1314
  });
1692
1315
  }
1693
1316
  async function loadPdfDocumentToStore(pdf, store, options) {
1694
1317
  const { pageConcurrency, scale, signal } = options;
1695
1318
  const storeThumbnails = options.storeThumbnails ?? false;
1696
- throwIfAborted2(signal);
1319
+ throwIfAborted(signal);
1697
1320
  const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
1698
1321
  const bufferedResults = /* @__PURE__ */ new Map();
1699
1322
  let nextEmitIndex = 0;
@@ -1708,9 +1331,9 @@ async function loadPdfDocumentToStore(pdf, store, options) {
1708
1331
  if (!bufferedResult) break;
1709
1332
  bufferedResults.delete(nextPageNumber);
1710
1333
  nextEmitIndex += 1;
1711
- throwIfAborted2(signal);
1334
+ throwIfAborted(signal);
1712
1335
  await options?.onPageStored?.(bufferedResult);
1713
- throwIfAborted2(signal);
1336
+ throwIfAborted(signal);
1714
1337
  }
1715
1338
  };
1716
1339
  const nextChain = emitChain.then(run, run);
@@ -1722,20 +1345,20 @@ async function loadPdfDocumentToStore(pdf, store, options) {
1722
1345
  pageNumbers,
1723
1346
  pageConcurrency,
1724
1347
  async (pageNumber) => {
1725
- throwIfAborted2(signal);
1348
+ throwIfAborted(signal);
1726
1349
  const page = await pdf.getPage(pageNumber);
1727
- throwIfAborted2(signal);
1350
+ throwIfAborted(signal);
1728
1351
  const { canvas, width, height } = await renderPageToCanvas(
1729
1352
  page,
1730
1353
  scale,
1731
1354
  signal
1732
1355
  );
1733
- throwIfAborted2(signal);
1356
+ throwIfAborted(signal);
1734
1357
  const mime = "image/png";
1735
1358
  const pageBlob = await encodeCanvasToBlob(canvas, { mimeType: mime });
1736
- throwIfAborted2(signal);
1359
+ throwIfAborted(signal);
1737
1360
  const blobId = await store.storeOriginal(pageBlob);
1738
- throwIfAborted2(signal);
1361
+ throwIfAborted(signal);
1739
1362
  const thumbnailBlobId = storeThumbnails ? await (async () => {
1740
1363
  const thumbScale = Math.min(1, 256 / Math.max(width, height));
1741
1364
  const tw = Math.max(1, Math.round(width * thumbScale));
@@ -1752,7 +1375,7 @@ async function loadPdfDocumentToStore(pdf, store, options) {
1752
1375
  const thumbBlob = await encodeCanvasToBlob(thumbCanvas, {
1753
1376
  mimeType: mime
1754
1377
  });
1755
- throwIfAborted2(signal);
1378
+ throwIfAborted(signal);
1756
1379
  return await store.storeThumbnail(thumbBlob);
1757
1380
  })() : "";
1758
1381
  const pageResult = {
@@ -2106,22 +1729,22 @@ function finalizeIngestedItem(item, context, uploadResult, decorateItem) {
2106
1729
  const itemWithAssetData = applyAssetUploadResultToItem(item, uploadResult);
2107
1730
  return decorateItem ? decorateItem(itemWithAssetData, context) : itemWithAssetData;
2108
1731
  }
2109
- function createAbortError3() {
1732
+ function createAbortError2() {
2110
1733
  return new DOMException("Aborted", "AbortError");
2111
1734
  }
2112
- function throwIfAborted3(signal) {
1735
+ function throwIfAborted2(signal) {
2113
1736
  if (signal?.aborted) {
2114
- throw createAbortError3();
1737
+ throw createAbortError2();
2115
1738
  }
2116
1739
  }
2117
1740
  function isAbortError(error) {
2118
1741
  return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
2119
1742
  }
2120
1743
  async function uploadAssetIfNeeded(assetStore, file, kind, signal) {
2121
- throwIfAborted3(signal);
1744
+ throwIfAborted2(signal);
2122
1745
  if (!assetStore) return null;
2123
1746
  const result = await assetStore.upload({ file, kind, signal });
2124
- throwIfAborted3(signal);
1747
+ throwIfAborted2(signal);
2125
1748
  return result ?? null;
2126
1749
  }
2127
1750
  async function ingestAssetFilesToSceneItems(options) {
@@ -2144,7 +1767,7 @@ async function ingestAssetFilesToSceneItems(options) {
2144
1767
  const errors = [];
2145
1768
  let occupiedBottomY = existingItems.length > 0 ? Math.max(...existingItems.map((item) => item.bounds.y + item.bounds.height)) : null;
2146
1769
  for (const file of files) {
2147
- throwIfAborted3(signal);
1770
+ throwIfAborted2(signal);
2148
1771
  const kind = getAssetKindForFile(file);
2149
1772
  if (!kind) {
2150
1773
  const error = {
@@ -2170,10 +1793,10 @@ async function ingestAssetFilesToSceneItems(options) {
2170
1793
  storeThumbnails: false,
2171
1794
  signal,
2172
1795
  onPageStored: async (page) => {
2173
- throwIfAborted3(signal);
1796
+ throwIfAborted2(signal);
2174
1797
  const uploadResult2 = await uploadResultPromise;
2175
1798
  const fullUrl2 = await createBlobUrlFromStore(imageStore, page.blobId);
2176
- throwIfAborted3(signal);
1799
+ throwIfAborted2(signal);
2177
1800
  const naturalTopY2 = worldCenter.y - page.height / 2;
2178
1801
  const stackedTopY2 = occupiedBottomY == null ? naturalTopY2 : occupiedBottomY + gapWorld;
2179
1802
  const bounds2 = {
@@ -2213,18 +1836,18 @@ async function ingestAssetFilesToSceneItems(options) {
2213
1836
  );
2214
1837
  items.push(item2);
2215
1838
  occupiedBottomY = bounds2.y + page.height;
2216
- throwIfAborted3(signal);
1839
+ throwIfAborted2(signal);
2217
1840
  onItemsReady?.([item2], { file, kind });
2218
1841
  }
2219
1842
  });
2220
1843
  continue;
2221
1844
  }
2222
- throwIfAborted3(signal);
1845
+ throwIfAborted2(signal);
2223
1846
  const [uploadResult, storedImage] = await Promise.all([
2224
1847
  uploadAssetIfNeeded(assetStore, file, kind, signal),
2225
1848
  loadImageToStore(file, imageStore)
2226
1849
  ]);
2227
- throwIfAborted3(signal);
1850
+ throwIfAborted2(signal);
2228
1851
  const { blobId, thumbnailBlobId, width, height } = storedImage;
2229
1852
  const fullUrl = await createBlobUrlFromStore(imageStore, blobId);
2230
1853
  const thumbBlob = await imageStore.getThumbnail(thumbnailBlobId);
@@ -2262,7 +1885,7 @@ async function ingestAssetFilesToSceneItems(options) {
2262
1885
  decorateItem
2263
1886
  );
2264
1887
  items.push(item);
2265
- throwIfAborted3(signal);
1888
+ throwIfAborted2(signal);
2266
1889
  onItemsReady?.([item], { file, kind });
2267
1890
  occupiedBottomY = occupiedBottomY == null ? bounds.y + height : Math.max(occupiedBottomY, bounds.y + height);
2268
1891
  } catch (error) {
@@ -7539,6 +7162,9 @@ function shouldRedrawRasterImageCanvas({
7539
7162
  if (currentSourceKey !== nextSourceKey && safeCurrentWidth === safeNextWidth && safeCurrentHeight === safeNextHeight) {
7540
7163
  return true;
7541
7164
  }
7165
+ if (currentSourceKey !== nextSourceKey && (safeNextWidth < safeCurrentWidth || safeNextHeight < safeCurrentHeight)) {
7166
+ return true;
7167
+ }
7542
7168
  return safeNextWidth > safeCurrentWidth * upscaleRedrawRatio || safeNextHeight > safeCurrentHeight * upscaleRedrawRatio;
7543
7169
  }
7544
7170
  function toPositiveFiniteNumber(value, fallback) {