canvu-react 0.4.67 → 0.4.69

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 { I as IndexedDbImageStore } from './asset-hydration-F6aM5C7x.cjs';
4
- export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-F6aM5C7x.cjs';
5
- import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './asset-store-35ysK28r.cjs';
6
- export { b as VectorViewportAssetHydrationRequest, c as VectorViewportAssetResolveRequest, d as VectorViewportAssetResolveResult, e as VectorViewportAssetUploadRequest, f as VectorViewportAssetUploadResult } from './asset-store-35ysK28r.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-D5d-3dvz.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-D5d-3dvz.cjs';
3
+ import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './raster-image-canvas-nK9kM9UJ.cjs';
4
+ export { b as RasterImageCanvasRenderRequest, c as RasterImageCanvasRenderTarget, d as RasterImageCanvasRenderTargetResolver, R as RasterImageCanvasRenderingOptions, e as RasterImageCanvasSourceSizeRequest, f as RasterImageCanvasSourceSizeResolver, g as VectorViewportAssetHydrationRequest, h as VectorViewportAssetResolveRequest, i as VectorViewportAssetResolveResult, j as VectorViewportAssetUploadRequest, k as VectorViewportAssetUploadResult } from './raster-image-canvas-nK9kM9UJ.cjs';
5
+ import { I as IndexedDbImageStore } from './asset-hydration-D2xaUoAT.cjs';
6
+ export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-D2xaUoAT.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-D402X18k.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-D402X18k.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';
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 { I as IndexedDbImageStore } from './asset-hydration-BSjiek7Q.js';
4
- export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-BSjiek7Q.js';
5
- import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './asset-store-D_FjW_CN.js';
6
- export { b as VectorViewportAssetHydrationRequest, c as VectorViewportAssetResolveRequest, d as VectorViewportAssetResolveResult, e as VectorViewportAssetUploadRequest, f as VectorViewportAssetUploadResult } from './asset-store-D_FjW_CN.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-B-Jdh-n6.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-B-Jdh-n6.js';
3
+ import { V as VectorViewportAssetKind, a as VectorViewportAssetStore } from './raster-image-canvas-CCOmB4NY.js';
4
+ export { b as RasterImageCanvasRenderRequest, c as RasterImageCanvasRenderTarget, d as RasterImageCanvasRenderTargetResolver, R as RasterImageCanvasRenderingOptions, e as RasterImageCanvasSourceSizeRequest, f as RasterImageCanvasSourceSizeResolver, g as VectorViewportAssetHydrationRequest, h as VectorViewportAssetResolveRequest, i as VectorViewportAssetResolveResult, j as VectorViewportAssetUploadRequest, k as VectorViewportAssetUploadResult } from './raster-image-canvas-CCOmB4NY.js';
5
+ import { I as IndexedDbImageStore } from './asset-hydration-D9eThWse.js';
6
+ export { H as HydratedSceneItemsWithAssetsResult, h as hydrateSceneItemsWithAssets } from './asset-hydration-D9eThWse.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-CMuEaiM7.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-CMuEaiM7.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';
package/dist/react.js CHANGED
@@ -6877,6 +6877,177 @@ function cullItemsByViewport(items, visibleWorld) {
6877
6877
  return cullItemsByViewportSpatial(items, visibleWorld, SPATIAL_CELL_SIZE);
6878
6878
  }
6879
6879
 
6880
+ // src/renderer/raster-image-canvas.ts
6881
+ init_rect();
6882
+ var DEFAULT_PIXEL_HEADROOM = 1.5;
6883
+ var DEFAULT_MAX_PIXEL_COUNT = 12e6;
6884
+ var DEFAULT_MAX_DIMENSION = 4096;
6885
+ var DEFAULT_UPSCALE_REDRAW_RATIO = 1.15;
6886
+ function resolveRasterImageCanvasRenderingOptions(options) {
6887
+ if (!options) return null;
6888
+ const fallbackDevicePixelRatio = typeof window === "undefined" ? 1 : window.devicePixelRatio;
6889
+ return {
6890
+ resolveSourceSize: options.resolveSourceSize,
6891
+ resolveRenderTarget: options.resolveRenderTarget,
6892
+ devicePixelRatio: toPositiveFiniteNumber(
6893
+ options.devicePixelRatio,
6894
+ fallbackDevicePixelRatio
6895
+ ),
6896
+ pixelHeadroom: toPositiveFiniteNumber(
6897
+ options.pixelHeadroom,
6898
+ DEFAULT_PIXEL_HEADROOM
6899
+ ),
6900
+ maxPixelCount: toPositiveFiniteNumber(
6901
+ options.maxPixelCount,
6902
+ DEFAULT_MAX_PIXEL_COUNT
6903
+ ),
6904
+ maxDimension: toPositiveFiniteNumber(
6905
+ options.maxDimension,
6906
+ DEFAULT_MAX_DIMENSION
6907
+ ),
6908
+ upscaleRedrawRatio: toPositiveFiniteNumber(
6909
+ options.upscaleRedrawRatio,
6910
+ DEFAULT_UPSCALE_REDRAW_RATIO
6911
+ )
6912
+ };
6913
+ }
6914
+ function getRasterImageContentRect(item) {
6915
+ if (item.toolKind !== "image" || !item.imageIntrinsicSize) return null;
6916
+ const bounds = normalizeRect(item.bounds);
6917
+ const intrinsicWidth = Math.max(1e-6, item.imageIntrinsicSize.width);
6918
+ const intrinsicHeight = Math.max(1e-6, item.imageIntrinsicSize.height);
6919
+ const boundsAspectRatio = bounds.width / Math.max(1e-9, bounds.height);
6920
+ const imageAspectRatio = intrinsicWidth / intrinsicHeight;
6921
+ if (Math.abs(boundsAspectRatio - imageAspectRatio) < 1e-3) {
6922
+ return { x: 0, y: 0, width: bounds.width, height: bounds.height };
6923
+ }
6924
+ if (boundsAspectRatio > imageAspectRatio) {
6925
+ const height2 = bounds.height;
6926
+ const width2 = height2 * imageAspectRatio;
6927
+ return { x: (bounds.width - width2) / 2, y: 0, width: width2, height: height2 };
6928
+ }
6929
+ const width = bounds.width;
6930
+ const height = width / imageAspectRatio;
6931
+ return { x: 0, y: (bounds.height - height) / 2, width, height };
6932
+ }
6933
+ function resolveRasterImageCanvasSourceSize({
6934
+ item,
6935
+ href,
6936
+ intrinsicSize,
6937
+ contentRect,
6938
+ viewportSize,
6939
+ cameraZoom,
6940
+ options
6941
+ }) {
6942
+ const resolved = options.resolveSourceSize?.({
6943
+ item,
6944
+ href,
6945
+ intrinsicSize,
6946
+ contentRect,
6947
+ viewportSize,
6948
+ cameraZoom,
6949
+ devicePixelRatio: options.devicePixelRatio
6950
+ });
6951
+ const width = toPositiveFiniteNumber(resolved?.width, intrinsicSize.width);
6952
+ const height = toPositiveFiniteNumber(resolved?.height, intrinsicSize.height);
6953
+ return { width, height };
6954
+ }
6955
+ function getRasterImageCanvasTargetSize({
6956
+ intrinsicSize,
6957
+ contentRect,
6958
+ cameraZoom,
6959
+ devicePixelRatio,
6960
+ pixelHeadroom,
6961
+ maxPixelCount,
6962
+ maxDimension
6963
+ }) {
6964
+ const intrinsicWidth = Math.max(1, Math.round(intrinsicSize.width));
6965
+ const intrinsicHeight = Math.max(1, Math.round(intrinsicSize.height));
6966
+ const targetCssWidth = Math.max(1, contentRect.width * cameraZoom);
6967
+ const targetCssHeight = Math.max(1, contentRect.height * cameraZoom);
6968
+ const desiredWidth = targetCssWidth * toPositiveFiniteNumber(devicePixelRatio, 1) * pixelHeadroom;
6969
+ const desiredHeight = targetCssHeight * toPositiveFiniteNumber(devicePixelRatio, 1) * pixelHeadroom;
6970
+ const dimensionScale = Math.min(
6971
+ 1,
6972
+ toPositiveFiniteNumber(maxDimension, intrinsicWidth) / Math.max(intrinsicWidth, intrinsicHeight)
6973
+ );
6974
+ const pixelScale = Math.min(
6975
+ 1,
6976
+ Math.sqrt(
6977
+ toPositiveFiniteNumber(maxPixelCount, intrinsicWidth * intrinsicHeight) / (intrinsicWidth * intrinsicHeight)
6978
+ )
6979
+ );
6980
+ const viewportScale = Math.min(
6981
+ 1,
6982
+ desiredWidth / intrinsicWidth,
6983
+ desiredHeight / intrinsicHeight
6984
+ );
6985
+ const scale = Math.min(dimensionScale, pixelScale, viewportScale);
6986
+ const width = Math.max(1, Math.round(intrinsicWidth * scale));
6987
+ const height = Math.max(1, Math.round(width * (intrinsicHeight / intrinsicWidth)));
6988
+ return { width, height };
6989
+ }
6990
+ function resolveRasterImageCanvasRenderTarget({
6991
+ item,
6992
+ href,
6993
+ intrinsicSize,
6994
+ sourceSize,
6995
+ contentRect,
6996
+ targetSize,
6997
+ viewportSize,
6998
+ cameraZoom,
6999
+ options
7000
+ }) {
7001
+ const request = {
7002
+ item,
7003
+ href,
7004
+ intrinsicSize,
7005
+ sourceSize,
7006
+ contentRect,
7007
+ targetSize,
7008
+ viewportSize,
7009
+ cameraZoom,
7010
+ devicePixelRatio: options.devicePixelRatio
7011
+ };
7012
+ const resolved = options.resolveRenderTarget?.(request);
7013
+ if (typeof resolved === "string") {
7014
+ return { href: resolved, sourceKey: resolved, targetSize, contentRect };
7015
+ }
7016
+ if (resolved?.href) {
7017
+ return {
7018
+ href: resolved.href,
7019
+ sourceKey: resolved.sourceKey ?? resolved.href,
7020
+ targetSize,
7021
+ contentRect
7022
+ };
7023
+ }
7024
+ return { href, sourceKey: href, targetSize, contentRect };
7025
+ }
7026
+ function shouldRedrawRasterImageCanvas({
7027
+ currentSourceKey,
7028
+ currentWidth,
7029
+ currentHeight,
7030
+ nextSourceKey,
7031
+ nextWidth,
7032
+ nextHeight,
7033
+ upscaleRedrawRatio
7034
+ }) {
7035
+ const safeCurrentWidth = Math.max(0, Math.round(currentWidth));
7036
+ const safeCurrentHeight = Math.max(0, Math.round(currentHeight));
7037
+ const safeNextWidth = Math.max(1, Math.round(nextWidth));
7038
+ const safeNextHeight = Math.max(1, Math.round(nextHeight));
7039
+ if (!currentSourceKey || safeCurrentWidth <= 1 || safeCurrentHeight <= 1) {
7040
+ return true;
7041
+ }
7042
+ if (currentSourceKey !== nextSourceKey && safeCurrentWidth === safeNextWidth && safeCurrentHeight === safeNextHeight) {
7043
+ return true;
7044
+ }
7045
+ return safeNextWidth > safeCurrentWidth * upscaleRedrawRatio || safeNextHeight > safeCurrentHeight * upscaleRedrawRatio;
7046
+ }
7047
+ function toPositiveFiniteNumber(value, fallback) {
7048
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
7049
+ }
7050
+
6880
7051
  // src/renderer/svg-vector-renderer.ts
6881
7052
  function formatCameraTransform(camera) {
6882
7053
  const z = camera.zoom;
@@ -6901,6 +7072,87 @@ function itemClassName(item) {
6901
7072
  }
6902
7073
  return classes.join(" ");
6903
7074
  }
7075
+ async function decodeRasterImage(href, width, height, signal) {
7076
+ if (typeof createImageBitmap === "function") {
7077
+ try {
7078
+ const response = await fetch(href, { signal, credentials: "same-origin" });
7079
+ if (!response.ok) {
7080
+ throw new Error(`Failed to fetch raster image: ${response.status}`);
7081
+ }
7082
+ const blob = await response.blob();
7083
+ if (signal.aborted) throw new DOMException("Aborted", "AbortError");
7084
+ const bitmap = await createImageBitmap(blob, {
7085
+ resizeWidth: width,
7086
+ resizeHeight: height,
7087
+ resizeQuality: "high"
7088
+ });
7089
+ return {
7090
+ width: bitmap.width,
7091
+ height: bitmap.height,
7092
+ draw: (context) => {
7093
+ context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height);
7094
+ },
7095
+ close: () => bitmap.close()
7096
+ };
7097
+ } catch (error) {
7098
+ if (signal.aborted) throw error;
7099
+ }
7100
+ }
7101
+ const image = await loadImageElement(href, signal);
7102
+ return {
7103
+ width,
7104
+ height,
7105
+ draw: (context) => {
7106
+ context.drawImage(image, 0, 0, width, height);
7107
+ },
7108
+ close: () => {
7109
+ }
7110
+ };
7111
+ }
7112
+ function loadImageElement(href, signal) {
7113
+ return new Promise((resolve, reject) => {
7114
+ if (signal.aborted) {
7115
+ reject(new DOMException("Aborted", "AbortError"));
7116
+ return;
7117
+ }
7118
+ const image = new Image();
7119
+ const cleanup = () => {
7120
+ signal.removeEventListener("abort", abort);
7121
+ image.onload = null;
7122
+ image.onerror = null;
7123
+ };
7124
+ const abort = () => {
7125
+ cleanup();
7126
+ image.removeAttribute("src");
7127
+ reject(new DOMException("Aborted", "AbortError"));
7128
+ };
7129
+ image.decoding = "async";
7130
+ image.onload = () => {
7131
+ const decodePromise = image.decode?.();
7132
+ if (!decodePromise) {
7133
+ cleanup();
7134
+ resolve(image);
7135
+ return;
7136
+ }
7137
+ decodePromise.then(
7138
+ () => {
7139
+ cleanup();
7140
+ resolve(image);
7141
+ },
7142
+ () => {
7143
+ cleanup();
7144
+ resolve(image);
7145
+ }
7146
+ );
7147
+ };
7148
+ image.onerror = () => {
7149
+ cleanup();
7150
+ reject(new Error("Failed to load raster image"));
7151
+ };
7152
+ signal.addEventListener("abort", abort, { once: true });
7153
+ image.src = href;
7154
+ });
7155
+ }
6904
7156
  var SvgVectorRenderer = class {
6905
7157
  container;
6906
7158
  scene;
@@ -6912,10 +7164,14 @@ var SvgVectorRenderer = class {
6912
7164
  hoveredItemId = null;
6913
7165
  liveOverlay = null;
6914
7166
  resizeObserver;
7167
+ rasterImageCanvasRendering;
6915
7168
  constructor(options) {
6916
7169
  this.container = options.container;
6917
7170
  this.scene = options.scene;
6918
7171
  this.camera = options.camera;
7172
+ this.rasterImageCanvasRendering = resolveRasterImageCanvasRenderingOptions(
7173
+ options.rasterImageCanvas
7174
+ );
6919
7175
  this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
6920
7176
  this.svg.setAttribute("width", "100%");
6921
7177
  this.svg.setAttribute("height", "100%");
@@ -6944,6 +7200,15 @@ var SvgVectorRenderer = class {
6944
7200
  this.applyInteractionAttributes(cached.g, id);
6945
7201
  }
6946
7202
  }
7203
+ setRasterImageCanvasRendering(options) {
7204
+ this.rasterImageCanvasRendering = resolveRasterImageCanvasRenderingOptions(options);
7205
+ if (!this.rasterImageCanvasRendering) {
7206
+ for (const cached of this.itemNodeCache.values()) {
7207
+ this.releaseRasterImageCanvas(cached);
7208
+ }
7209
+ }
7210
+ this.render();
7211
+ }
6947
7212
  /**
6948
7213
  * Reads container size, culls items, and updates the SVG (incrementally when possible).
6949
7214
  */
@@ -7017,6 +7282,7 @@ var SvgVectorRenderer = class {
7017
7282
  }
7018
7283
  for (const [id, cached] of this.itemNodeCache) {
7019
7284
  if (!visibleIds.has(id)) {
7285
+ this.releaseRasterImageCanvas(cached);
7020
7286
  cached.g.remove();
7021
7287
  }
7022
7288
  }
@@ -7049,6 +7315,7 @@ var SvgVectorRenderer = class {
7049
7315
  g.innerHTML = item.childrenSvg;
7050
7316
  cached.lastChildrenSvg = item.childrenSvg;
7051
7317
  }
7318
+ this.syncRasterImageCanvas(cached, item);
7052
7319
  const expectedPosition = previousNode ? previousNode.nextSibling : this.rootG.firstChild;
7053
7320
  if (expectedPosition !== g) {
7054
7321
  this.rootG.insertBefore(g, expectedPosition);
@@ -7056,6 +7323,238 @@ var SvgVectorRenderer = class {
7056
7323
  previousNode = g;
7057
7324
  }
7058
7325
  }
7326
+ syncRasterImageCanvas(cached, item) {
7327
+ const options = this.rasterImageCanvasRendering;
7328
+ if (!options || item.toolKind !== "image" || !item.imageRasterHref || !item.imageIntrinsicSize) {
7329
+ this.releaseRasterImageCanvas(cached);
7330
+ return;
7331
+ }
7332
+ const contentRect = getRasterImageContentRect(item);
7333
+ const viewportSize = {
7334
+ width: this.container.clientWidth,
7335
+ height: this.container.clientHeight
7336
+ };
7337
+ if (!contentRect || viewportSize.width <= 0 || viewportSize.height <= 0) {
7338
+ this.releaseRasterImageCanvas(cached);
7339
+ return;
7340
+ }
7341
+ const sourceSize = resolveRasterImageCanvasSourceSize({
7342
+ item,
7343
+ href: item.imageRasterHref,
7344
+ intrinsicSize: item.imageIntrinsicSize,
7345
+ contentRect,
7346
+ viewportSize,
7347
+ cameraZoom: this.camera.zoom,
7348
+ options
7349
+ });
7350
+ const targetSize = getRasterImageCanvasTargetSize({
7351
+ intrinsicSize: sourceSize,
7352
+ contentRect,
7353
+ cameraZoom: this.camera.zoom,
7354
+ devicePixelRatio: options.devicePixelRatio,
7355
+ pixelHeadroom: options.pixelHeadroom,
7356
+ maxPixelCount: options.maxPixelCount,
7357
+ maxDimension: options.maxDimension
7358
+ });
7359
+ const target = resolveRasterImageCanvasRenderTarget({
7360
+ item,
7361
+ href: item.imageRasterHref,
7362
+ intrinsicSize: item.imageIntrinsicSize,
7363
+ sourceSize,
7364
+ contentRect,
7365
+ targetSize,
7366
+ viewportSize,
7367
+ cameraZoom: this.camera.zoom,
7368
+ options
7369
+ });
7370
+ const rasterCanvas = this.ensureRasterImageCanvas(cached);
7371
+ this.positionRasterImageCanvas(rasterCanvas, target.contentRect);
7372
+ if (rasterCanvas.itemHref !== null && rasterCanvas.itemHref !== item.imageRasterHref) {
7373
+ this.clearRasterImageCanvasBitmap(rasterCanvas);
7374
+ }
7375
+ if (!shouldRedrawRasterImageCanvas({
7376
+ currentSourceKey: rasterCanvas.sourceKey,
7377
+ currentWidth: rasterCanvas.width,
7378
+ currentHeight: rasterCanvas.height,
7379
+ nextSourceKey: target.sourceKey,
7380
+ nextWidth: target.targetSize.width,
7381
+ nextHeight: target.targetSize.height,
7382
+ upscaleRedrawRatio: options.upscaleRedrawRatio
7383
+ })) {
7384
+ return;
7385
+ }
7386
+ const request = {
7387
+ itemHref: item.imageRasterHref,
7388
+ target
7389
+ };
7390
+ if (rasterCanvas.abortController) {
7391
+ if (rasterCanvas.loadingItemHref !== item.imageRasterHref) {
7392
+ rasterCanvas.abortController.abort();
7393
+ rasterCanvas.abortController = null;
7394
+ rasterCanvas.loadingItemHref = null;
7395
+ rasterCanvas.loadingSourceKey = null;
7396
+ rasterCanvas.loadingWidth = 0;
7397
+ rasterCanvas.loadingHeight = 0;
7398
+ rasterCanvas.queuedTarget = null;
7399
+ this.drawRasterImageCanvas(rasterCanvas, request);
7400
+ return;
7401
+ }
7402
+ if (rasterCanvas.loadingSourceKey === target.sourceKey && rasterCanvas.loadingWidth === target.targetSize.width && rasterCanvas.loadingHeight === target.targetSize.height) {
7403
+ return;
7404
+ }
7405
+ if (shouldRedrawRasterImageCanvas({
7406
+ currentSourceKey: rasterCanvas.loadingSourceKey,
7407
+ currentWidth: rasterCanvas.loadingWidth,
7408
+ currentHeight: rasterCanvas.loadingHeight,
7409
+ nextSourceKey: target.sourceKey,
7410
+ nextWidth: target.targetSize.width,
7411
+ nextHeight: target.targetSize.height,
7412
+ upscaleRedrawRatio: options.upscaleRedrawRatio
7413
+ })) {
7414
+ rasterCanvas.queuedTarget = request;
7415
+ }
7416
+ return;
7417
+ }
7418
+ this.drawRasterImageCanvas(rasterCanvas, request);
7419
+ }
7420
+ ensureRasterImageCanvas(cached) {
7421
+ if (cached.rasterCanvas) {
7422
+ if (!cached.rasterCanvas.foreignObject.isConnected) {
7423
+ cached.g.appendChild(cached.rasterCanvas.foreignObject);
7424
+ }
7425
+ return cached.rasterCanvas;
7426
+ }
7427
+ const foreignObject = document.createElementNS(
7428
+ "http://www.w3.org/2000/svg",
7429
+ "foreignObject"
7430
+ );
7431
+ foreignObject.setAttribute("data-canvu-raster-canvas", "true");
7432
+ foreignObject.style.pointerEvents = "none";
7433
+ const canvas = document.createElement("canvas");
7434
+ canvas.width = 1;
7435
+ canvas.height = 1;
7436
+ canvas.style.display = "block";
7437
+ canvas.style.width = "100%";
7438
+ canvas.style.height = "100%";
7439
+ foreignObject.appendChild(canvas);
7440
+ cached.g.appendChild(foreignObject);
7441
+ cached.rasterCanvas = {
7442
+ foreignObject,
7443
+ canvas,
7444
+ itemHref: null,
7445
+ sourceKey: null,
7446
+ width: 0,
7447
+ height: 0,
7448
+ loadSequence: 0,
7449
+ abortController: null,
7450
+ loadingItemHref: null,
7451
+ loadingSourceKey: null,
7452
+ loadingWidth: 0,
7453
+ loadingHeight: 0,
7454
+ queuedTarget: null
7455
+ };
7456
+ return cached.rasterCanvas;
7457
+ }
7458
+ positionRasterImageCanvas(rasterCanvas, contentRect) {
7459
+ rasterCanvas.foreignObject.setAttribute("x", String(contentRect.x));
7460
+ rasterCanvas.foreignObject.setAttribute("y", String(contentRect.y));
7461
+ rasterCanvas.foreignObject.setAttribute("width", String(contentRect.width));
7462
+ rasterCanvas.foreignObject.setAttribute("height", String(contentRect.height));
7463
+ }
7464
+ drawRasterImageCanvas(rasterCanvas, request) {
7465
+ const { target } = request;
7466
+ const width = Math.max(1, Math.round(target.targetSize.width));
7467
+ const height = Math.max(1, Math.round(target.targetSize.height));
7468
+ const sequence = rasterCanvas.loadSequence + 1;
7469
+ rasterCanvas.loadSequence = sequence;
7470
+ rasterCanvas.abortController?.abort();
7471
+ const abortController = new AbortController();
7472
+ rasterCanvas.abortController = abortController;
7473
+ rasterCanvas.loadingItemHref = request.itemHref;
7474
+ rasterCanvas.loadingSourceKey = target.sourceKey;
7475
+ rasterCanvas.loadingWidth = width;
7476
+ rasterCanvas.loadingHeight = height;
7477
+ rasterCanvas.queuedTarget = null;
7478
+ decodeRasterImage(target.href, width, height, abortController.signal).then((decoded) => {
7479
+ if (abortController.signal.aborted || rasterCanvas.loadSequence !== sequence) {
7480
+ decoded.close();
7481
+ return;
7482
+ }
7483
+ const context = rasterCanvas.canvas.getContext("2d");
7484
+ if (!context) {
7485
+ decoded.close();
7486
+ rasterCanvas.abortController = null;
7487
+ rasterCanvas.loadingItemHref = null;
7488
+ rasterCanvas.loadingSourceKey = null;
7489
+ rasterCanvas.loadingWidth = 0;
7490
+ rasterCanvas.loadingHeight = 0;
7491
+ this.drawQueuedRasterImageCanvasTarget(rasterCanvas);
7492
+ return;
7493
+ }
7494
+ rasterCanvas.canvas.width = decoded.width;
7495
+ rasterCanvas.canvas.height = decoded.height;
7496
+ context.clearRect(0, 0, decoded.width, decoded.height);
7497
+ decoded.draw(context);
7498
+ decoded.close();
7499
+ rasterCanvas.itemHref = request.itemHref;
7500
+ rasterCanvas.sourceKey = target.sourceKey;
7501
+ rasterCanvas.width = decoded.width;
7502
+ rasterCanvas.height = decoded.height;
7503
+ rasterCanvas.abortController = null;
7504
+ rasterCanvas.loadingItemHref = null;
7505
+ rasterCanvas.loadingSourceKey = null;
7506
+ rasterCanvas.loadingWidth = 0;
7507
+ rasterCanvas.loadingHeight = 0;
7508
+ this.drawQueuedRasterImageCanvasTarget(rasterCanvas);
7509
+ }).catch((error) => {
7510
+ if (abortController.signal.aborted) return;
7511
+ if (error instanceof Error && error.name === "AbortError") return;
7512
+ if (rasterCanvas.loadSequence === sequence) {
7513
+ rasterCanvas.abortController = null;
7514
+ rasterCanvas.loadingItemHref = null;
7515
+ rasterCanvas.loadingSourceKey = null;
7516
+ rasterCanvas.loadingWidth = 0;
7517
+ rasterCanvas.loadingHeight = 0;
7518
+ this.drawQueuedRasterImageCanvasTarget(rasterCanvas);
7519
+ }
7520
+ });
7521
+ }
7522
+ drawQueuedRasterImageCanvasTarget(rasterCanvas) {
7523
+ const queuedTarget = rasterCanvas.queuedTarget;
7524
+ if (!queuedTarget) return;
7525
+ rasterCanvas.queuedTarget = null;
7526
+ if (!shouldRedrawRasterImageCanvas({
7527
+ currentSourceKey: rasterCanvas.sourceKey,
7528
+ currentWidth: rasterCanvas.width,
7529
+ currentHeight: rasterCanvas.height,
7530
+ nextSourceKey: queuedTarget.target.sourceKey,
7531
+ nextWidth: queuedTarget.target.targetSize.width,
7532
+ nextHeight: queuedTarget.target.targetSize.height,
7533
+ upscaleRedrawRatio: this.rasterImageCanvasRendering?.upscaleRedrawRatio ?? 1
7534
+ })) {
7535
+ return;
7536
+ }
7537
+ this.drawRasterImageCanvas(rasterCanvas, queuedTarget);
7538
+ }
7539
+ clearRasterImageCanvasBitmap(rasterCanvas) {
7540
+ const context = rasterCanvas.canvas.getContext("2d");
7541
+ context?.clearRect(0, 0, rasterCanvas.canvas.width, rasterCanvas.canvas.height);
7542
+ rasterCanvas.canvas.width = 1;
7543
+ rasterCanvas.canvas.height = 1;
7544
+ rasterCanvas.itemHref = null;
7545
+ rasterCanvas.sourceKey = null;
7546
+ rasterCanvas.width = 0;
7547
+ rasterCanvas.height = 0;
7548
+ }
7549
+ releaseRasterImageCanvas(cached) {
7550
+ const rasterCanvas = cached.rasterCanvas;
7551
+ if (!rasterCanvas) return;
7552
+ rasterCanvas.abortController?.abort();
7553
+ rasterCanvas.loadSequence += 1;
7554
+ rasterCanvas.queuedTarget = null;
7555
+ rasterCanvas.foreignObject.remove();
7556
+ cached.rasterCanvas = void 0;
7557
+ }
7059
7558
  applyInteractionAttributes(g, itemId) {
7060
7559
  g.setAttribute(
7061
7560
  "data-canvu-selected",
@@ -7068,6 +7567,9 @@ var SvgVectorRenderer = class {
7068
7567
  }
7069
7568
  destroy() {
7070
7569
  this.resizeObserver.disconnect();
7570
+ for (const cached of this.itemNodeCache.values()) {
7571
+ this.releaseRasterImageCanvas(cached);
7572
+ }
7071
7573
  this.itemNodeCache.clear();
7072
7574
  this.liveOverlay = null;
7073
7575
  this.svg.remove();
@@ -8357,6 +8859,7 @@ var VectorViewport = forwardRef(
8357
8859
  customPlacement: consumerCustomPlacement,
8358
8860
  customPlacements: consumerCustomPlacements,
8359
8861
  assetStore,
8862
+ imageCanvasRendering,
8360
8863
  toolLocked = false,
8361
8864
  autoResetToolTo = "select",
8362
8865
  onToolChangeRequest,
@@ -8563,6 +9066,8 @@ var VectorViewport = forwardRef(
8563
9066
  onActivateLinkRef.current = onActivateLink;
8564
9067
  const assetStoreRef = useRef(assetStore);
8565
9068
  assetStoreRef.current = assetStore;
9069
+ const imageCanvasRenderingRef = useRef(imageCanvasRendering);
9070
+ imageCanvasRenderingRef.current = imageCanvasRendering;
8566
9071
  const customPlacementRef = useRef(customPlacement);
8567
9072
  customPlacementRef.current = customPlacement;
8568
9073
  const allCustomPlacementsRef = useRef(allCustomPlacements);
@@ -9183,7 +9688,8 @@ var VectorViewport = forwardRef(
9183
9688
  container: el,
9184
9689
  scene,
9185
9690
  camera,
9186
- pointerEventsNone: interactiveRef.current
9691
+ pointerEventsNone: interactiveRef.current,
9692
+ rasterImageCanvas: imageCanvasRenderingRef.current
9187
9693
  });
9188
9694
  rendererRef.current = renderer;
9189
9695
  renderer.setInteractionState({
@@ -9235,6 +9741,9 @@ var VectorViewport = forwardRef(
9235
9741
  hoveredItemId: hoveredItemIdRef.current
9236
9742
  });
9237
9743
  }, [effectiveSelectedIds]);
9744
+ useEffect(() => {
9745
+ rendererRef.current?.setRasterImageCanvasRendering(imageCanvasRendering);
9746
+ }, [imageCanvasRendering]);
9238
9747
  useEffect(() => {
9239
9748
  const r = rendererRef.current;
9240
9749
  if (!r) return;