canvu-react 0.4.71 → 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/react.d.cts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { V as VectorSceneItem } from './types-fJNwEnHf.cjs';
2
2
  export { C as CustomShapeResizeHandles, b as ResizeHandleId } from './types-fJNwEnHf.cjs';
3
- import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './raster-image-canvas-Byq087t9.cjs';
4
- export { b as RasterImageCanvasRenderRequest, c as RasterImageCanvasRenderTarget, d as RasterImageCanvasRenderTargetResolver, R as RasterImageCanvasRenderingOptions, e as RasterImageCanvasSource, f as RasterImageCanvasSourceRequest, g as RasterImageCanvasSourceResolver, h as RasterImageCanvasSourceSizeRequest, i as RasterImageCanvasSourceSizeResolver, j as VectorViewportAssetHydrationRequest, k as VectorViewportAssetResolveRequest, l as VectorViewportAssetResolveResult, m as VectorViewportAssetUploadRequest, n as VectorViewportAssetUploadResult } from './raster-image-canvas-Byq087t9.cjs';
5
- import { I as IndexedDbImageStore } from './asset-hydration-BeWWxiBq.cjs';
6
- export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-BeWWxiBq.cjs';
7
- import { B as BoardComponentPosition, V as VectorToolDefinition, C as CustomShapePlacementOptions, a as CanvuBeforeInteractionHook, b as CanvuAfterInteractionHook, c as CanvasPlugin, d as VectorSelectionInspector } from './types-f8d-2-6N.cjs';
8
- export { e as CanvasPluginComponentProps, f as CanvasPluginContribution, g as CanvasPluginItemsChangeMiddlewareContext, h as CanvasPluginRenderContext, i as CanvuAfterInteractionDetail, j as CanvuBeforeInteractionResult, k as CanvuChromeActiveToolStyle, l as CanvuChromeContext, m as CanvuChromeContextValue, n as CanvuChromeSelectionStyleChange, o as CanvuInteractionDetail, p as CanvuInteractionKind, q as CanvuInteractionOutcome, r as CanvuInteractionPoint, s as CanvuPluginContext, t as CanvuPluginContextValue, u as CanvuPluginViewportSnapshot, P as PlacementPreview, R as ReadOnlyInteractionOptions, v as ReadOnlyItemClickCandidateDetail, w as ReadOnlyItemClickScope, S as SHAPE_CONTEXT_MENU_ITEM_IDS, x as SelectModeItemClickDetail, y as SelectModeItemClickResult, z as ShapeContextMenu, A as ShapeContextMenuItem, D as ShapeContextMenuProps, E as ShapeContextMenuRenderContext, F as VectorCanvasSpacePosition, G as VectorItemsChangeInfo, H as VectorItemsChangeMotive, I as VectorSelectionInspectorProps, J as VectorViewport, K as VectorViewportHandle, L as VectorViewportProps, W as WorldPointerDownDetail, M as createCanvuPlugin, N as getBoardPositionStyle, O as useCanvuChromeContext, Q as useCanvuDocumentContext, T as useCanvuPluginContext, U as useCanvuPluginContribution, X as useCanvuResolvedTools, Y as useCanvuViewportContext } from './types-f8d-2-6N.cjs';
3
+ import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './raster-image-canvas-ByaCKEVw.cjs';
4
+ export { b as RasterImageCanvasRenderRequest, c as RasterImageCanvasRenderTarget, d as RasterImageCanvasRenderTargetResolver, R as RasterImageCanvasRenderingOptions, e as RasterImageCanvasSource, f as RasterImageCanvasSourceRequest, g as RasterImageCanvasSourceResolver, h as RasterImageCanvasSourceSizeRequest, i as RasterImageCanvasSourceSizeResolver, j as VectorViewportAssetHydrationRequest, k as VectorViewportAssetResolveRequest, l as VectorViewportAssetResolveResult, m as VectorViewportAssetUploadRequest, n as VectorViewportAssetUploadResult } from './raster-image-canvas-ByaCKEVw.cjs';
5
+ import { I as IndexedDbImageStore } from './asset-hydration-6swZ6ciN.cjs';
6
+ export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-6swZ6ciN.cjs';
7
+ import { B as BoardComponentPosition, V as VectorToolDefinition, C as CustomShapePlacementOptions, a as CanvuBeforeInteractionHook, b as CanvuAfterInteractionHook, c as CanvasPlugin, d as VectorSelectionInspector } from './types-DOUBapS4.cjs';
8
+ export { e as CanvasPluginComponentProps, f as CanvasPluginContribution, g as CanvasPluginItemsChangeMiddlewareContext, h as CanvasPluginRenderContext, i as CanvuAfterInteractionDetail, j as CanvuBeforeInteractionResult, k as CanvuChromeActiveToolStyle, l as CanvuChromeContext, m as CanvuChromeContextValue, n as CanvuChromeSelectionStyleChange, o as CanvuInteractionDetail, p as CanvuInteractionKind, q as CanvuInteractionOutcome, r as CanvuInteractionPoint, s as CanvuPluginContext, t as CanvuPluginContextValue, u as CanvuPluginViewportSnapshot, P as PlacementPreview, R as ReadOnlyInteractionOptions, v as ReadOnlyItemClickCandidateDetail, w as ReadOnlyItemClickScope, S as SHAPE_CONTEXT_MENU_ITEM_IDS, x as SelectModeItemClickDetail, y as SelectModeItemClickResult, z as ShapeContextMenu, A as ShapeContextMenuItem, D as ShapeContextMenuProps, E as ShapeContextMenuRenderContext, F as VectorCanvasSpacePosition, G as VectorItemsChangeInfo, H as VectorItemsChangeMotive, I as VectorSelectionInspectorProps, J as VectorViewport, K as VectorViewportHandle, L as VectorViewportProps, W as WorldPointerDownDetail, M as createCanvuPlugin, N as getBoardPositionStyle, O as useCanvuChromeContext, Q as useCanvuDocumentContext, T as useCanvuPluginContext, U as useCanvuPluginContribution, X as useCanvuResolvedTools, Y as useCanvuViewportContext } from './types-DOUBapS4.cjs';
9
9
  import * as react_jsx_runtime from 'react/jsx-runtime';
10
10
  import * as react from 'react';
11
11
  import { CSSProperties, ReactNode, ReactElement, SVGProps } from 'react';
@@ -115,6 +115,13 @@ type IngestAssetFilesToSceneItemsOptions = {
115
115
  */
116
116
  pdfScale?: number;
117
117
  pdfPageConcurrency?: number;
118
+ /**
119
+ * Cancels in-flight PDF rendering, asset uploads, and item emission.
120
+ *
121
+ * Pass this when ingestion is tied to a component lifecycle or route so stale
122
+ * imports stop work instead of continuing in the background.
123
+ */
124
+ signal?: AbortSignal;
118
125
  /**
119
126
  * Called as soon as canvu finishes converting one or more items from the
120
127
  * source files.
package/dist/react.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { V as VectorSceneItem } from './types-fJNwEnHf.js';
2
2
  export { C as CustomShapeResizeHandles, b as ResizeHandleId } from './types-fJNwEnHf.js';
3
- import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './raster-image-canvas-BqBgE8C-.js';
4
- export { b as RasterImageCanvasRenderRequest, c as RasterImageCanvasRenderTarget, d as RasterImageCanvasRenderTargetResolver, R as RasterImageCanvasRenderingOptions, e as RasterImageCanvasSource, f as RasterImageCanvasSourceRequest, g as RasterImageCanvasSourceResolver, h as RasterImageCanvasSourceSizeRequest, i as RasterImageCanvasSourceSizeResolver, j as VectorViewportAssetHydrationRequest, k as VectorViewportAssetResolveRequest, l as VectorViewportAssetResolveResult, m as VectorViewportAssetUploadRequest, n as VectorViewportAssetUploadResult } from './raster-image-canvas-BqBgE8C-.js';
5
- import { I as IndexedDbImageStore } from './asset-hydration-CLoDkZDh.js';
6
- export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-CLoDkZDh.js';
7
- import { B as BoardComponentPosition, V as VectorToolDefinition, C as CustomShapePlacementOptions, a as CanvuBeforeInteractionHook, b as CanvuAfterInteractionHook, c as CanvasPlugin, d as VectorSelectionInspector } from './types-D_cQxUug.js';
8
- export { e as CanvasPluginComponentProps, f as CanvasPluginContribution, g as CanvasPluginItemsChangeMiddlewareContext, h as CanvasPluginRenderContext, i as CanvuAfterInteractionDetail, j as CanvuBeforeInteractionResult, k as CanvuChromeActiveToolStyle, l as CanvuChromeContext, m as CanvuChromeContextValue, n as CanvuChromeSelectionStyleChange, o as CanvuInteractionDetail, p as CanvuInteractionKind, q as CanvuInteractionOutcome, r as CanvuInteractionPoint, s as CanvuPluginContext, t as CanvuPluginContextValue, u as CanvuPluginViewportSnapshot, P as PlacementPreview, R as ReadOnlyInteractionOptions, v as ReadOnlyItemClickCandidateDetail, w as ReadOnlyItemClickScope, S as SHAPE_CONTEXT_MENU_ITEM_IDS, x as SelectModeItemClickDetail, y as SelectModeItemClickResult, z as ShapeContextMenu, A as ShapeContextMenuItem, D as ShapeContextMenuProps, E as ShapeContextMenuRenderContext, F as VectorCanvasSpacePosition, G as VectorItemsChangeInfo, H as VectorItemsChangeMotive, I as VectorSelectionInspectorProps, J as VectorViewport, K as VectorViewportHandle, L as VectorViewportProps, W as WorldPointerDownDetail, M as createCanvuPlugin, N as getBoardPositionStyle, O as useCanvuChromeContext, Q as useCanvuDocumentContext, T as useCanvuPluginContext, U as useCanvuPluginContribution, X as useCanvuResolvedTools, Y as useCanvuViewportContext } from './types-D_cQxUug.js';
3
+ import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './raster-image-canvas-D3ZrySjr.js';
4
+ export { b as RasterImageCanvasRenderRequest, c as RasterImageCanvasRenderTarget, d as RasterImageCanvasRenderTargetResolver, R as RasterImageCanvasRenderingOptions, e as RasterImageCanvasSource, f as RasterImageCanvasSourceRequest, g as RasterImageCanvasSourceResolver, h as RasterImageCanvasSourceSizeRequest, i as RasterImageCanvasSourceSizeResolver, j as VectorViewportAssetHydrationRequest, k as VectorViewportAssetResolveRequest, l as VectorViewportAssetResolveResult, m as VectorViewportAssetUploadRequest, n as VectorViewportAssetUploadResult } from './raster-image-canvas-D3ZrySjr.js';
5
+ import { I as IndexedDbImageStore } from './asset-hydration-P0M5hn-p.js';
6
+ export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-P0M5hn-p.js';
7
+ import { B as BoardComponentPosition, V as VectorToolDefinition, C as CustomShapePlacementOptions, a as CanvuBeforeInteractionHook, b as CanvuAfterInteractionHook, c as CanvasPlugin, d as VectorSelectionInspector } from './types-C5wxwquF.js';
8
+ export { e as CanvasPluginComponentProps, f as CanvasPluginContribution, g as CanvasPluginItemsChangeMiddlewareContext, h as CanvasPluginRenderContext, i as CanvuAfterInteractionDetail, j as CanvuBeforeInteractionResult, k as CanvuChromeActiveToolStyle, l as CanvuChromeContext, m as CanvuChromeContextValue, n as CanvuChromeSelectionStyleChange, o as CanvuInteractionDetail, p as CanvuInteractionKind, q as CanvuInteractionOutcome, r as CanvuInteractionPoint, s as CanvuPluginContext, t as CanvuPluginContextValue, u as CanvuPluginViewportSnapshot, P as PlacementPreview, R as ReadOnlyInteractionOptions, v as ReadOnlyItemClickCandidateDetail, w as ReadOnlyItemClickScope, S as SHAPE_CONTEXT_MENU_ITEM_IDS, x as SelectModeItemClickDetail, y as SelectModeItemClickResult, z as ShapeContextMenu, A as ShapeContextMenuItem, D as ShapeContextMenuProps, E as ShapeContextMenuRenderContext, F as VectorCanvasSpacePosition, G as VectorItemsChangeInfo, H as VectorItemsChangeMotive, I as VectorSelectionInspectorProps, J as VectorViewport, K as VectorViewportHandle, L as VectorViewportProps, W as WorldPointerDownDetail, M as createCanvuPlugin, N as getBoardPositionStyle, O as useCanvuChromeContext, Q as useCanvuDocumentContext, T as useCanvuPluginContext, U as useCanvuPluginContribution, X as useCanvuResolvedTools, Y as useCanvuViewportContext } from './types-C5wxwquF.js';
9
9
  import * as react_jsx_runtime from 'react/jsx-runtime';
10
10
  import * as react from 'react';
11
11
  import { CSSProperties, ReactNode, ReactElement, SVGProps } from 'react';
@@ -115,6 +115,13 @@ type IngestAssetFilesToSceneItemsOptions = {
115
115
  */
116
116
  pdfScale?: number;
117
117
  pdfPageConcurrency?: number;
118
+ /**
119
+ * Cancels in-flight PDF rendering, asset uploads, and item emission.
120
+ *
121
+ * Pass this when ingestion is tied to a component lifecycle or route so stale
122
+ * imports stop work instead of continuing in the background.
123
+ */
124
+ signal?: AbortSignal;
118
125
  /**
119
126
  * Called as soon as canvu finishes converting one or more items from the
120
127
  * source files.
package/dist/react.js CHANGED
@@ -1201,7 +1201,8 @@ function getPdfJs() {
1201
1201
  }
1202
1202
  return pdfjsPromise;
1203
1203
  }
1204
- async function renderPageToCanvas(page, scale) {
1204
+ async function renderPageToCanvas(page, scale, signal) {
1205
+ throwIfAborted(signal);
1205
1206
  const raw = page.getViewport({ scale: 1 });
1206
1207
  const adjustedScale = Math.round(raw.width * scale) / raw.width;
1207
1208
  const viewport = page.getViewport({ scale: adjustedScale });
@@ -1214,22 +1215,48 @@ async function renderPageToCanvas(page, scale) {
1214
1215
  if (!ctx) throw new Error("Canvas 2D context unavailable");
1215
1216
  ctx.imageSmoothingEnabled = true;
1216
1217
  ctx.imageSmoothingQuality = "high";
1217
- await page.render({ canvas, viewport }).promise;
1218
+ const renderTask = page.render({ canvas, viewport });
1219
+ if (signal) {
1220
+ const abortRender = () => {
1221
+ renderTask.cancel();
1222
+ };
1223
+ signal.addEventListener("abort", abortRender, { once: true });
1224
+ try {
1225
+ await renderTask.promise;
1226
+ } catch (error) {
1227
+ if (signal.aborted) throw createAbortError();
1228
+ throw error;
1229
+ } finally {
1230
+ signal.removeEventListener("abort", abortRender);
1231
+ }
1232
+ } else {
1233
+ await renderTask.promise;
1234
+ }
1235
+ throwIfAborted(signal);
1218
1236
  return { canvas, width: w, height: h };
1219
1237
  }
1238
+ function createAbortError() {
1239
+ return new DOMException("Aborted", "AbortError");
1240
+ }
1241
+ function throwIfAborted(signal) {
1242
+ if (signal?.aborted) {
1243
+ throw createAbortError();
1244
+ }
1245
+ }
1220
1246
  function normalizePdfPageNumbers(pageNumbers, pageCount) {
1221
1247
  if (!pageNumbers || pageNumbers.length === 0) {
1222
1248
  return Array.from({ length: pageCount }, (_, index) => index + 1);
1223
1249
  }
1224
1250
  return [...new Set(pageNumbers)].filter((pageNumber) => pageNumber >= 1 && pageNumber <= pageCount).sort((left, right) => left - right);
1225
1251
  }
1226
- async function runWithConcurrency(items, concurrency, execute) {
1252
+ async function runWithConcurrency(items, concurrency, execute, signal) {
1227
1253
  const results = new Array(items.length);
1228
1254
  let nextIndex = 0;
1229
1255
  const workerCount = Math.max(1, Math.min(concurrency, items.length));
1230
1256
  await Promise.all(
1231
1257
  Array.from({ length: workerCount }, async () => {
1232
1258
  while (nextIndex < items.length) {
1259
+ throwIfAborted(signal);
1233
1260
  const currentIndex = nextIndex;
1234
1261
  nextIndex += 1;
1235
1262
  const item = items[currentIndex];
@@ -1237,6 +1264,7 @@ async function runWithConcurrency(items, concurrency, execute) {
1237
1264
  continue;
1238
1265
  }
1239
1266
  results[currentIndex] = await execute(item);
1267
+ throwIfAborted(signal);
1240
1268
  }
1241
1269
  })
1242
1270
  );
@@ -1246,9 +1274,49 @@ async function loadPdfToStore(file, store, options) {
1246
1274
  const scale = options?.scale ?? 1.5;
1247
1275
  const pageConcurrency = options?.pageConcurrency ?? 2;
1248
1276
  const storeThumbnails = options?.storeThumbnails ?? false;
1277
+ const signal = options?.signal;
1278
+ throwIfAborted(signal);
1249
1279
  const pdfjs = await getPdfJs();
1280
+ throwIfAborted(signal);
1250
1281
  const arrayBuffer = await file.arrayBuffer();
1251
- const pdf = await pdfjs.getDocument({ data: arrayBuffer }).promise;
1282
+ throwIfAborted(signal);
1283
+ const loadingTask = pdfjs.getDocument({ data: arrayBuffer });
1284
+ if (signal) {
1285
+ const abortLoading = () => {
1286
+ void loadingTask.destroy();
1287
+ };
1288
+ signal.addEventListener("abort", abortLoading, { once: true });
1289
+ try {
1290
+ const pdf2 = await loadingTask.promise;
1291
+ signal.removeEventListener("abort", abortLoading);
1292
+ return await loadPdfDocumentToStore(pdf2, store, {
1293
+ scale,
1294
+ pageNumbers: options?.pageNumbers,
1295
+ pageConcurrency,
1296
+ storeThumbnails,
1297
+ signal,
1298
+ onPageStored: options?.onPageStored
1299
+ });
1300
+ } catch (error) {
1301
+ if (signal.aborted) throw createAbortError();
1302
+ throw error;
1303
+ } finally {
1304
+ signal.removeEventListener("abort", abortLoading);
1305
+ }
1306
+ }
1307
+ const pdf = await loadingTask.promise;
1308
+ return await loadPdfDocumentToStore(pdf, store, {
1309
+ scale,
1310
+ pageNumbers: options?.pageNumbers,
1311
+ pageConcurrency,
1312
+ storeThumbnails,
1313
+ onPageStored: options?.onPageStored
1314
+ });
1315
+ }
1316
+ async function loadPdfDocumentToStore(pdf, store, options) {
1317
+ const { pageConcurrency, scale, signal } = options;
1318
+ const storeThumbnails = options.storeThumbnails ?? false;
1319
+ throwIfAborted(signal);
1252
1320
  const pageNumbers = normalizePdfPageNumbers(options?.pageNumbers, pdf.numPages);
1253
1321
  const bufferedResults = /* @__PURE__ */ new Map();
1254
1322
  let nextEmitIndex = 0;
@@ -1263,7 +1331,9 @@ async function loadPdfToStore(file, store, options) {
1263
1331
  if (!bufferedResult) break;
1264
1332
  bufferedResults.delete(nextPageNumber);
1265
1333
  nextEmitIndex += 1;
1334
+ throwIfAborted(signal);
1266
1335
  await options?.onPageStored?.(bufferedResult);
1336
+ throwIfAborted(signal);
1267
1337
  }
1268
1338
  };
1269
1339
  const nextChain = emitChain.then(run, run);
@@ -1275,11 +1345,20 @@ async function loadPdfToStore(file, store, options) {
1275
1345
  pageNumbers,
1276
1346
  pageConcurrency,
1277
1347
  async (pageNumber) => {
1348
+ throwIfAborted(signal);
1278
1349
  const page = await pdf.getPage(pageNumber);
1279
- const { canvas, width, height } = await renderPageToCanvas(page, scale);
1350
+ throwIfAborted(signal);
1351
+ const { canvas, width, height } = await renderPageToCanvas(
1352
+ page,
1353
+ scale,
1354
+ signal
1355
+ );
1356
+ throwIfAborted(signal);
1280
1357
  const mime = "image/png";
1281
1358
  const pageBlob = await encodeCanvasToBlob(canvas, { mimeType: mime });
1359
+ throwIfAborted(signal);
1282
1360
  const blobId = await store.storeOriginal(pageBlob);
1361
+ throwIfAborted(signal);
1283
1362
  const thumbnailBlobId = storeThumbnails ? await (async () => {
1284
1363
  const thumbScale = Math.min(1, 256 / Math.max(width, height));
1285
1364
  const tw = Math.max(1, Math.round(width * thumbScale));
@@ -1296,6 +1375,7 @@ async function loadPdfToStore(file, store, options) {
1296
1375
  const thumbBlob = await encodeCanvasToBlob(thumbCanvas, {
1297
1376
  mimeType: mime
1298
1377
  });
1378
+ throwIfAborted(signal);
1299
1379
  return await store.storeThumbnail(thumbBlob);
1300
1380
  })() : "";
1301
1381
  const pageResult = {
@@ -1307,7 +1387,8 @@ async function loadPdfToStore(file, store, options) {
1307
1387
  };
1308
1388
  await queuePageEmission(pageResult);
1309
1389
  return pageResult;
1310
- }
1390
+ },
1391
+ signal
1311
1392
  );
1312
1393
  }
1313
1394
 
@@ -1648,9 +1729,22 @@ function finalizeIngestedItem(item, context, uploadResult, decorateItem) {
1648
1729
  const itemWithAssetData = applyAssetUploadResultToItem(item, uploadResult);
1649
1730
  return decorateItem ? decorateItem(itemWithAssetData, context) : itemWithAssetData;
1650
1731
  }
1651
- async function uploadAssetIfNeeded(assetStore, file, kind) {
1732
+ function createAbortError2() {
1733
+ return new DOMException("Aborted", "AbortError");
1734
+ }
1735
+ function throwIfAborted2(signal) {
1736
+ if (signal?.aborted) {
1737
+ throw createAbortError2();
1738
+ }
1739
+ }
1740
+ function isAbortError(error) {
1741
+ return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
1742
+ }
1743
+ async function uploadAssetIfNeeded(assetStore, file, kind, signal) {
1744
+ throwIfAborted2(signal);
1652
1745
  if (!assetStore) return null;
1653
- const result = await assetStore.upload({ file, kind });
1746
+ const result = await assetStore.upload({ file, kind, signal });
1747
+ throwIfAborted2(signal);
1654
1748
  return result ?? null;
1655
1749
  }
1656
1750
  async function ingestAssetFilesToSceneItems(options) {
@@ -1664,6 +1758,7 @@ async function ingestAssetFilesToSceneItems(options) {
1664
1758
  gapWorld = 16,
1665
1759
  pdfScale = 1.15,
1666
1760
  pdfPageConcurrency = 2,
1761
+ signal,
1667
1762
  decorateItem,
1668
1763
  onItemsReady,
1669
1764
  onError
@@ -1672,6 +1767,7 @@ async function ingestAssetFilesToSceneItems(options) {
1672
1767
  const errors = [];
1673
1768
  let occupiedBottomY = existingItems.length > 0 ? Math.max(...existingItems.map((item) => item.bounds.y + item.bounds.height)) : null;
1674
1769
  for (const file of files) {
1770
+ throwIfAborted2(signal);
1675
1771
  const kind = getAssetKindForFile(file);
1676
1772
  if (!kind) {
1677
1773
  const error = {
@@ -1684,14 +1780,23 @@ async function ingestAssetFilesToSceneItems(options) {
1684
1780
  }
1685
1781
  try {
1686
1782
  if (kind === "pdf") {
1687
- const uploadResultPromise = uploadAssetIfNeeded(assetStore, file, kind);
1783
+ const uploadResultPromise = uploadAssetIfNeeded(
1784
+ assetStore,
1785
+ file,
1786
+ kind,
1787
+ signal
1788
+ );
1789
+ void uploadResultPromise.catch(() => void 0);
1688
1790
  await loadPdfToStore(file, imageStore, {
1689
1791
  scale: pdfScale,
1690
1792
  pageConcurrency: pdfPageConcurrency,
1691
1793
  storeThumbnails: false,
1794
+ signal,
1692
1795
  onPageStored: async (page) => {
1796
+ throwIfAborted2(signal);
1693
1797
  const uploadResult2 = await uploadResultPromise;
1694
1798
  const fullUrl2 = await createBlobUrlFromStore(imageStore, page.blobId);
1799
+ throwIfAborted2(signal);
1695
1800
  const naturalTopY2 = worldCenter.y - page.height / 2;
1696
1801
  const stackedTopY2 = occupiedBottomY == null ? naturalTopY2 : occupiedBottomY + gapWorld;
1697
1802
  const bounds2 = {
@@ -1731,15 +1836,18 @@ async function ingestAssetFilesToSceneItems(options) {
1731
1836
  );
1732
1837
  items.push(item2);
1733
1838
  occupiedBottomY = bounds2.y + page.height;
1839
+ throwIfAborted2(signal);
1734
1840
  onItemsReady?.([item2], { file, kind });
1735
1841
  }
1736
1842
  });
1737
1843
  continue;
1738
1844
  }
1845
+ throwIfAborted2(signal);
1739
1846
  const [uploadResult, storedImage] = await Promise.all([
1740
- uploadAssetIfNeeded(assetStore, file, kind),
1847
+ uploadAssetIfNeeded(assetStore, file, kind, signal),
1741
1848
  loadImageToStore(file, imageStore)
1742
1849
  ]);
1850
+ throwIfAborted2(signal);
1743
1851
  const { blobId, thumbnailBlobId, width, height } = storedImage;
1744
1852
  const fullUrl = await createBlobUrlFromStore(imageStore, blobId);
1745
1853
  const thumbBlob = await imageStore.getThumbnail(thumbnailBlobId);
@@ -1777,9 +1885,13 @@ async function ingestAssetFilesToSceneItems(options) {
1777
1885
  decorateItem
1778
1886
  );
1779
1887
  items.push(item);
1888
+ throwIfAborted2(signal);
1780
1889
  onItemsReady?.([item], { file, kind });
1781
1890
  occupiedBottomY = occupiedBottomY == null ? bounds.y + height : Math.max(occupiedBottomY, bounds.y + height);
1782
1891
  } catch (error) {
1892
+ if (isAbortError(error)) {
1893
+ throw error;
1894
+ }
1783
1895
  const fileError = {
1784
1896
  file,
1785
1897
  kind,
@@ -8433,6 +8545,48 @@ function shallowEqualStringArray(a, b) {
8433
8545
  return true;
8434
8546
  }
8435
8547
 
8548
+ // src/react/stroke-input.ts
8549
+ var MAX_INTERPOLATED_POINTS_PER_SAMPLE = 192;
8550
+ function getPointerEventSamples(event) {
8551
+ if (typeof event.getCoalescedEvents !== "function") {
8552
+ return [event];
8553
+ }
8554
+ const samples = event.getCoalescedEvents();
8555
+ return samples.length > 0 ? samples : [event];
8556
+ }
8557
+ var resolveInterpolatedPressure = (lastPoint, nextPoint, ratio) => {
8558
+ if (lastPoint.pressure != null && nextPoint.pressure != null) {
8559
+ return lastPoint.pressure + (nextPoint.pressure - lastPoint.pressure) * ratio;
8560
+ }
8561
+ return ratio === 1 ? nextPoint.pressure : void 0;
8562
+ };
8563
+ var resolveMaxStepWorld = (maxStepWorld) => Number.isFinite(maxStepWorld) && maxStepWorld > 0 ? maxStepWorld : Number.POSITIVE_INFINITY;
8564
+ function appendInterpolatedStrokePoint(points, nextPoint, maxStepWorld) {
8565
+ if (points.length === 0) return [nextPoint];
8566
+ const lastPoint = points[points.length - 1];
8567
+ if (!lastPoint) return [...points, nextPoint];
8568
+ const deltaX = nextPoint.x - lastPoint.x;
8569
+ const deltaY = nextPoint.y - lastPoint.y;
8570
+ const distanceSquared = deltaX * deltaX + deltaY * deltaY;
8571
+ if (distanceSquared < 1e-12) return points;
8572
+ const distance = Math.sqrt(distanceSquared);
8573
+ const stepCount = Math.min(
8574
+ MAX_INTERPOLATED_POINTS_PER_SAMPLE,
8575
+ Math.max(1, Math.ceil(distance / resolveMaxStepWorld(maxStepWorld)))
8576
+ );
8577
+ if (stepCount === 1) return [...points, nextPoint];
8578
+ const interpolatedPoints = Array.from({ length: stepCount }, (_, index) => {
8579
+ const ratio = (index + 1) / stepCount;
8580
+ const pressure = resolveInterpolatedPressure(lastPoint, nextPoint, ratio);
8581
+ return {
8582
+ x: lastPoint.x + deltaX * ratio,
8583
+ y: lastPoint.y + deltaY * ratio,
8584
+ ...pressure != null ? { pressure } : {}
8585
+ };
8586
+ });
8587
+ return [...points, ...interpolatedPoints];
8588
+ }
8589
+
8436
8590
  // src/react/TextEditOverlay.tsx
8437
8591
  init_rect();
8438
8592
  init_text_svg();
@@ -8692,13 +8846,6 @@ function pointInSelectedItemBounds(item, worldX, worldY) {
8692
8846
  );
8693
8847
  return local.x >= 0 && local.x <= bounds.width && local.y >= 0 && local.y <= bounds.height;
8694
8848
  }
8695
- function pointerEventSamples(ev) {
8696
- if (ev.pointerType !== "pen" || typeof ev.getCoalescedEvents !== "function") {
8697
- return [ev];
8698
- }
8699
- const samples = ev.getCoalescedEvents();
8700
- return samples.length > 0 ? samples : [ev];
8701
- }
8702
8849
  var CANVU_PEN_ACTIVE_UI_BLOCK_CSS = `
8703
8850
  [data-canvu-pen-active="true"] [data-slot="vector-canvas-toolbar"],
8704
8851
  [data-canvu-pen-active="true"] [data-slot="vector-canvas-toolbar"] *,
@@ -8800,15 +8947,6 @@ function VectorViewportPluginInstances({
8800
8947
  ] }, plugin.id);
8801
8948
  }) });
8802
8949
  }
8803
- function appendInterpolatedPoints(points, next, maxStepWorld) {
8804
- if (points.length === 0) return [next];
8805
- const last = points[points.length - 1];
8806
- if (!last) return [...points, next];
8807
- const dx = next.x - last.x;
8808
- const dy = next.y - last.y;
8809
- if (dx * dx + dy * dy < 1e-12) return points;
8810
- return [...points, next];
8811
- }
8812
8950
  function pointerSampleToWorldPoint(screenToWorldFn, clientX, clientY, pressure) {
8813
8951
  const { worldX, worldY } = screenToWorldFn(clientX, clientY);
8814
8952
  const safePressure = pressure != null && Number.isFinite(pressure) ? Math.min(1, Math.max(0, pressure)) : void 0;
@@ -8839,15 +8977,19 @@ function isLikelyStylusTouch(touch) {
8839
8977
  }
8840
8978
  function appendPointerEventSamplesToStrokePoints(points, ev, zoom, screenToWorldFn) {
8841
8979
  let interpolated = points;
8842
- ev.pointerType === "pen" ? 0.35 / zoom : 1 / zoom;
8843
- for (const sample of pointerEventSamples(ev)) {
8980
+ const maxStepWorld = ev.pointerType === "pen" ? 0.35 / zoom : 1 / zoom;
8981
+ for (const sample of getPointerEventSamples(ev)) {
8844
8982
  const nextPoint = pointerSampleToWorldPoint(
8845
8983
  screenToWorldFn,
8846
8984
  sample.clientX,
8847
8985
  sample.clientY,
8848
8986
  sample.pointerType === "pen" ? sample.pressure : void 0
8849
8987
  );
8850
- interpolated = appendInterpolatedPoints(interpolated, nextPoint);
8988
+ interpolated = appendInterpolatedStrokePoint(
8989
+ interpolated,
8990
+ nextPoint,
8991
+ maxStepWorld
8992
+ );
8851
8993
  }
8852
8994
  return interpolated;
8853
8995
  }
@@ -8858,7 +9000,7 @@ function appendTouchToStrokePoints(points, touch, zoom, screenToWorldFn) {
8858
9000
  touch.clientY,
8859
9001
  touchPressure(touch)
8860
9002
  );
8861
- return appendInterpolatedPoints(points, nextPoint);
9003
+ return appendInterpolatedStrokePoint(points, nextPoint, 0.35 / zoom);
8862
9004
  }
8863
9005
  function createStraightStrokeState(anchorPoint, clientX, clientY) {
8864
9006
  return {