canvu-react 0.4.68 → 0.4.70

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.
@@ -110,6 +110,39 @@ type VectorViewportAssetStore = {
110
110
  getHydrationRequest?: (item: VectorSceneItem) => VectorViewportAssetHydrationRequest | null;
111
111
  };
112
112
 
113
+ /**
114
+ * Input passed to `imageCanvasRendering.resolveSourceSize`.
115
+ *
116
+ * Use it when the item's current `imageIntrinsicSize` is only a preview size,
117
+ * but your backing image service can provide a larger source for zoomed canvas
118
+ * rendering. Return the effective source size Canvu should cap against before
119
+ * computing the next bitmap target.
120
+ */
121
+ type RasterImageCanvasSourceSizeRequest = {
122
+ item: VectorSceneItem;
123
+ href: string;
124
+ intrinsicSize: {
125
+ width: number;
126
+ height: number;
127
+ };
128
+ contentRect: Rect;
129
+ viewportSize: {
130
+ width: number;
131
+ height: number;
132
+ };
133
+ cameraZoom: number;
134
+ devicePixelRatio: number;
135
+ };
136
+ /**
137
+ * Maps an image item to the effective source size used for zoom-aware bitmap
138
+ * sizing.
139
+ *
140
+ * Return `null`/`undefined` to use the item's `imageIntrinsicSize`.
141
+ */
142
+ type RasterImageCanvasSourceSizeResolver = (request: RasterImageCanvasSourceSizeRequest) => {
143
+ width: number;
144
+ height: number;
145
+ } | null | undefined;
113
146
  /**
114
147
  * Input passed to `imageCanvasRendering.resolveRenderTarget`.
115
148
  *
@@ -130,6 +163,10 @@ type RasterImageCanvasRenderRequest = {
130
163
  width: number;
131
164
  height: number;
132
165
  };
166
+ sourceSize: {
167
+ width: number;
168
+ height: number;
169
+ };
133
170
  contentRect: Rect;
134
171
  targetSize: {
135
172
  width: number;
@@ -170,6 +207,7 @@ type RasterImageCanvasRenderTargetResolver = (request: RasterImageCanvasRenderRe
170
207
  * already drawn instead of downgrading immediately.
171
208
  */
172
209
  type RasterImageCanvasRenderingOptions = {
210
+ resolveSourceSize?: RasterImageCanvasSourceSizeResolver;
173
211
  resolveRenderTarget?: RasterImageCanvasRenderTargetResolver;
174
212
  devicePixelRatio?: number;
175
213
  pixelHeadroom?: number;
@@ -178,4 +216,4 @@ type RasterImageCanvasRenderingOptions = {
178
216
  upscaleRedrawRatio?: number;
179
217
  };
180
218
 
181
- export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d, VectorViewportAssetHydrationRequest as e, VectorViewportAssetResolveRequest as f, VectorViewportAssetResolveResult as g, VectorViewportAssetUploadRequest as h, VectorViewportAssetUploadResult as i };
219
+ export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d, RasterImageCanvasSourceSizeRequest as e, RasterImageCanvasSourceSizeResolver as f, VectorViewportAssetHydrationRequest as g, VectorViewportAssetResolveRequest as h, VectorViewportAssetResolveResult as i, VectorViewportAssetUploadRequest as j, VectorViewportAssetUploadResult as k };
@@ -110,6 +110,39 @@ type VectorViewportAssetStore = {
110
110
  getHydrationRequest?: (item: VectorSceneItem) => VectorViewportAssetHydrationRequest | null;
111
111
  };
112
112
 
113
+ /**
114
+ * Input passed to `imageCanvasRendering.resolveSourceSize`.
115
+ *
116
+ * Use it when the item's current `imageIntrinsicSize` is only a preview size,
117
+ * but your backing image service can provide a larger source for zoomed canvas
118
+ * rendering. Return the effective source size Canvu should cap against before
119
+ * computing the next bitmap target.
120
+ */
121
+ type RasterImageCanvasSourceSizeRequest = {
122
+ item: VectorSceneItem;
123
+ href: string;
124
+ intrinsicSize: {
125
+ width: number;
126
+ height: number;
127
+ };
128
+ contentRect: Rect;
129
+ viewportSize: {
130
+ width: number;
131
+ height: number;
132
+ };
133
+ cameraZoom: number;
134
+ devicePixelRatio: number;
135
+ };
136
+ /**
137
+ * Maps an image item to the effective source size used for zoom-aware bitmap
138
+ * sizing.
139
+ *
140
+ * Return `null`/`undefined` to use the item's `imageIntrinsicSize`.
141
+ */
142
+ type RasterImageCanvasSourceSizeResolver = (request: RasterImageCanvasSourceSizeRequest) => {
143
+ width: number;
144
+ height: number;
145
+ } | null | undefined;
113
146
  /**
114
147
  * Input passed to `imageCanvasRendering.resolveRenderTarget`.
115
148
  *
@@ -130,6 +163,10 @@ type RasterImageCanvasRenderRequest = {
130
163
  width: number;
131
164
  height: number;
132
165
  };
166
+ sourceSize: {
167
+ width: number;
168
+ height: number;
169
+ };
133
170
  contentRect: Rect;
134
171
  targetSize: {
135
172
  width: number;
@@ -170,6 +207,7 @@ type RasterImageCanvasRenderTargetResolver = (request: RasterImageCanvasRenderRe
170
207
  * already drawn instead of downgrading immediately.
171
208
  */
172
209
  type RasterImageCanvasRenderingOptions = {
210
+ resolveSourceSize?: RasterImageCanvasSourceSizeResolver;
173
211
  resolveRenderTarget?: RasterImageCanvasRenderTargetResolver;
174
212
  devicePixelRatio?: number;
175
213
  pixelHeadroom?: number;
@@ -178,4 +216,4 @@ type RasterImageCanvasRenderingOptions = {
178
216
  upscaleRedrawRatio?: number;
179
217
  };
180
218
 
181
- export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d, VectorViewportAssetHydrationRequest as e, VectorViewportAssetResolveRequest as f, VectorViewportAssetResolveResult as g, VectorViewportAssetUploadRequest as h, VectorViewportAssetUploadResult as i };
219
+ export type { RasterImageCanvasRenderingOptions as R, VectorViewportAssetKind as V, VectorViewportAssetStore as a, RasterImageCanvasRenderRequest as b, RasterImageCanvasRenderTarget as c, RasterImageCanvasRenderTargetResolver as d, RasterImageCanvasSourceSizeRequest as e, RasterImageCanvasSourceSizeResolver as f, VectorViewportAssetHydrationRequest as g, VectorViewportAssetResolveRequest as h, VectorViewportAssetResolveResult as i, VectorViewportAssetUploadRequest as j, VectorViewportAssetUploadResult as k };
package/dist/react.cjs CHANGED
@@ -6894,6 +6894,7 @@ function resolveRasterImageCanvasRenderingOptions(options) {
6894
6894
  if (!options) return null;
6895
6895
  const fallbackDevicePixelRatio = typeof window === "undefined" ? 1 : window.devicePixelRatio;
6896
6896
  return {
6897
+ resolveSourceSize: options.resolveSourceSize,
6897
6898
  resolveRenderTarget: options.resolveRenderTarget,
6898
6899
  devicePixelRatio: toPositiveFiniteNumber(
6899
6900
  options.devicePixelRatio,
@@ -6936,6 +6937,28 @@ function getRasterImageContentRect(item) {
6936
6937
  const height = width / imageAspectRatio;
6937
6938
  return { x: 0, y: (bounds.height - height) / 2, width, height };
6938
6939
  }
6940
+ function resolveRasterImageCanvasSourceSize({
6941
+ item,
6942
+ href,
6943
+ intrinsicSize,
6944
+ contentRect,
6945
+ viewportSize,
6946
+ cameraZoom,
6947
+ options
6948
+ }) {
6949
+ const resolved = options.resolveSourceSize?.({
6950
+ item,
6951
+ href,
6952
+ intrinsicSize,
6953
+ contentRect,
6954
+ viewportSize,
6955
+ cameraZoom,
6956
+ devicePixelRatio: options.devicePixelRatio
6957
+ });
6958
+ const width = toPositiveFiniteNumber(resolved?.width, intrinsicSize.width);
6959
+ const height = toPositiveFiniteNumber(resolved?.height, intrinsicSize.height);
6960
+ return { width, height };
6961
+ }
6939
6962
  function getRasterImageCanvasTargetSize({
6940
6963
  intrinsicSize,
6941
6964
  contentRect,
@@ -6975,6 +6998,7 @@ function resolveRasterImageCanvasRenderTarget({
6975
6998
  item,
6976
6999
  href,
6977
7000
  intrinsicSize,
7001
+ sourceSize,
6978
7002
  contentRect,
6979
7003
  targetSize,
6980
7004
  viewportSize,
@@ -6985,6 +7009,7 @@ function resolveRasterImageCanvasRenderTarget({
6985
7009
  item,
6986
7010
  href,
6987
7011
  intrinsicSize,
7012
+ sourceSize,
6988
7013
  contentRect,
6989
7014
  targetSize,
6990
7015
  viewportSize,
@@ -7320,9 +7345,18 @@ var SvgVectorRenderer = class {
7320
7345
  this.releaseRasterImageCanvas(cached);
7321
7346
  return;
7322
7347
  }
7323
- const targetSize = getRasterImageCanvasTargetSize({
7348
+ const sourceSize = resolveRasterImageCanvasSourceSize({
7349
+ item,
7350
+ href: item.imageRasterHref,
7324
7351
  intrinsicSize: item.imageIntrinsicSize,
7325
7352
  contentRect,
7353
+ viewportSize,
7354
+ cameraZoom: this.camera.zoom,
7355
+ options
7356
+ });
7357
+ const targetSize = getRasterImageCanvasTargetSize({
7358
+ intrinsicSize: sourceSize,
7359
+ contentRect,
7326
7360
  cameraZoom: this.camera.zoom,
7327
7361
  devicePixelRatio: options.devicePixelRatio,
7328
7362
  pixelHeadroom: options.pixelHeadroom,
@@ -7333,6 +7367,7 @@ var SvgVectorRenderer = class {
7333
7367
  item,
7334
7368
  href: item.imageRasterHref,
7335
7369
  intrinsicSize: item.imageIntrinsicSize,
7370
+ sourceSize,
7336
7371
  contentRect,
7337
7372
  targetSize,
7338
7373
  viewportSize,
@@ -8355,6 +8390,47 @@ function shallowEqualStringArray(a, b) {
8355
8390
  return true;
8356
8391
  }
8357
8392
 
8393
+ // src/react/stroke-input.ts
8394
+ function getPointerEventSamples(event) {
8395
+ if (typeof event.getCoalescedEvents !== "function") {
8396
+ return [event];
8397
+ }
8398
+ const samples = event.getCoalescedEvents();
8399
+ return samples.length > 0 ? samples : [event];
8400
+ }
8401
+ var resolveInterpolatedPressure = (lastPoint, nextPoint, ratio) => {
8402
+ if (lastPoint.pressure != null && nextPoint.pressure != null) {
8403
+ return lastPoint.pressure + (nextPoint.pressure - lastPoint.pressure) * ratio;
8404
+ }
8405
+ return ratio === 1 ? nextPoint.pressure : void 0;
8406
+ };
8407
+ var resolveMaxStepWorld = (maxStepWorld) => Number.isFinite(maxStepWorld) && maxStepWorld > 0 ? maxStepWorld : Number.POSITIVE_INFINITY;
8408
+ function appendInterpolatedStrokePoint(points, nextPoint, maxStepWorld) {
8409
+ if (points.length === 0) return [nextPoint];
8410
+ const lastPoint = points[points.length - 1];
8411
+ if (!lastPoint) return [...points, nextPoint];
8412
+ const deltaX = nextPoint.x - lastPoint.x;
8413
+ const deltaY = nextPoint.y - lastPoint.y;
8414
+ const distanceSquared = deltaX * deltaX + deltaY * deltaY;
8415
+ if (distanceSquared < 1e-12) return points;
8416
+ const distance = Math.sqrt(distanceSquared);
8417
+ const stepCount = Math.max(
8418
+ 1,
8419
+ Math.ceil(distance / resolveMaxStepWorld(maxStepWorld))
8420
+ );
8421
+ if (stepCount === 1) return [...points, nextPoint];
8422
+ const interpolatedPoints = Array.from({ length: stepCount }, (_, index) => {
8423
+ const ratio = (index + 1) / stepCount;
8424
+ const pressure = resolveInterpolatedPressure(lastPoint, nextPoint, ratio);
8425
+ return {
8426
+ x: lastPoint.x + deltaX * ratio,
8427
+ y: lastPoint.y + deltaY * ratio,
8428
+ ...pressure != null ? { pressure } : {}
8429
+ };
8430
+ });
8431
+ return [...points, ...interpolatedPoints];
8432
+ }
8433
+
8358
8434
  // src/react/TextEditOverlay.tsx
8359
8435
  init_rect();
8360
8436
  init_text_svg();
@@ -8614,13 +8690,6 @@ function pointInSelectedItemBounds(item, worldX, worldY) {
8614
8690
  );
8615
8691
  return local.x >= 0 && local.x <= bounds.width && local.y >= 0 && local.y <= bounds.height;
8616
8692
  }
8617
- function pointerEventSamples(ev) {
8618
- if (ev.pointerType !== "pen" || typeof ev.getCoalescedEvents !== "function") {
8619
- return [ev];
8620
- }
8621
- const samples = ev.getCoalescedEvents();
8622
- return samples.length > 0 ? samples : [ev];
8623
- }
8624
8693
  var CANVU_PEN_ACTIVE_UI_BLOCK_CSS = `
8625
8694
  [data-canvu-pen-active="true"] [data-slot="vector-canvas-toolbar"],
8626
8695
  [data-canvu-pen-active="true"] [data-slot="vector-canvas-toolbar"] *,
@@ -8722,15 +8791,6 @@ function VectorViewportPluginInstances({
8722
8791
  ] }, plugin.id);
8723
8792
  }) });
8724
8793
  }
8725
- function appendInterpolatedPoints(points, next, maxStepWorld) {
8726
- if (points.length === 0) return [next];
8727
- const last = points[points.length - 1];
8728
- if (!last) return [...points, next];
8729
- const dx = next.x - last.x;
8730
- const dy = next.y - last.y;
8731
- if (dx * dx + dy * dy < 1e-12) return points;
8732
- return [...points, next];
8733
- }
8734
8794
  function pointerSampleToWorldPoint(screenToWorldFn, clientX, clientY, pressure) {
8735
8795
  const { worldX, worldY } = screenToWorldFn(clientX, clientY);
8736
8796
  const safePressure = pressure != null && Number.isFinite(pressure) ? Math.min(1, Math.max(0, pressure)) : void 0;
@@ -8761,15 +8821,19 @@ function isLikelyStylusTouch(touch) {
8761
8821
  }
8762
8822
  function appendPointerEventSamplesToStrokePoints(points, ev, zoom, screenToWorldFn) {
8763
8823
  let interpolated = points;
8764
- ev.pointerType === "pen" ? 0.35 / zoom : 1 / zoom;
8765
- for (const sample of pointerEventSamples(ev)) {
8824
+ const maxStepWorld = ev.pointerType === "pen" ? 0.35 / zoom : 1 / zoom;
8825
+ for (const sample of getPointerEventSamples(ev)) {
8766
8826
  const nextPoint = pointerSampleToWorldPoint(
8767
8827
  screenToWorldFn,
8768
8828
  sample.clientX,
8769
8829
  sample.clientY,
8770
8830
  sample.pointerType === "pen" ? sample.pressure : void 0
8771
8831
  );
8772
- interpolated = appendInterpolatedPoints(interpolated, nextPoint);
8832
+ interpolated = appendInterpolatedStrokePoint(
8833
+ interpolated,
8834
+ nextPoint,
8835
+ maxStepWorld
8836
+ );
8773
8837
  }
8774
8838
  return interpolated;
8775
8839
  }
@@ -8780,7 +8844,7 @@ function appendTouchToStrokePoints(points, touch, zoom, screenToWorldFn) {
8780
8844
  touch.clientY,
8781
8845
  touchPressure(touch)
8782
8846
  );
8783
- return appendInterpolatedPoints(points, nextPoint);
8847
+ return appendInterpolatedStrokePoint(points, nextPoint, 0.35 / zoom);
8784
8848
  }
8785
8849
  function createStraightStrokeState(anchorPoint, clientX, clientY) {
8786
8850
  return {