@inditextech/weave-sdk 4.0.0 → 4.1.0

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/sdk.node.js CHANGED
@@ -4,6 +4,7 @@ import pino from "pino";
4
4
  import { WEAVE_ASYNC_STATUS, WEAVE_AWARENESS_LAYER_ID, WEAVE_EXPORT_BACKGROUND_COLOR, WEAVE_EXPORT_FORMATS, WEAVE_EXPORT_RETURN_FORMAT, WEAVE_INSTANCE_STATUS, WEAVE_KONVA_BACKEND, WEAVE_LOG_LEVEL, WEAVE_NODE_CHANGE_TYPE, WEAVE_NODE_CUSTOM_EVENTS, WEAVE_NODE_LAYER_ID, WEAVE_NODE_POSITION, WEAVE_STORE_CONNECTION_STATUS, WEAVE_UTILITY_LAYER_ID } from "@inditextech/weave-types";
5
5
  import { getYjsDoc, getYjsValue, observeDeep, syncedStore } from "@syncedstore/core";
6
6
  import * as Y from "yjs";
7
+ import simplify from "simplify-js";
7
8
  import "konva/lib/types";
8
9
  import "konva/lib/Stage";
9
10
 
@@ -18952,7 +18953,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18952
18953
  const nodesSelected = tr.nodes();
18953
18954
  if (nodesSelected.length === 1) {
18954
18955
  const node = nodesSelected[0];
18955
- stage.container().style.cursor = node.defineMousePointer?.() ?? "grab";
18956
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "grab";
18956
18957
  } else stage.container().style.cursor = "grab";
18957
18958
  });
18958
18959
  tr.on("mouseout", (e) => {
@@ -19015,8 +19016,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19015
19016
  let selectedNodes = [];
19016
19017
  tr.on("dragstart", (e) => {
19017
19018
  this.dragInProcess = true;
19019
+ if (!e?.evt) return;
19018
19020
  let isWheelMousePressed = false;
19019
- if (e.evt.button === 1) isWheelMousePressed = true;
19021
+ if (e.evt?.button === 1) isWheelMousePressed = true;
19020
19022
  const mainLayer = this.instance.getMainLayer();
19021
19023
  if (!mainLayer) return;
19022
19024
  initialPos = {
@@ -19057,7 +19059,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19057
19059
  y: e.target.y()
19058
19060
  };
19059
19061
  let isWheelMousePressed = false;
19060
- if (e.evt.button === 1) isWheelMousePressed = true;
19062
+ if (e.evt?.button === 1) isWheelMousePressed = true;
19061
19063
  e.cancelBubble = true;
19062
19064
  this.instance.getHooks().callHook("weave:onTransformerDragMove", {
19063
19065
  e,
@@ -19414,8 +19416,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19414
19416
  this.handledClickOrTap = false;
19415
19417
  this.pointers[e.evt.pointerId] = e.evt;
19416
19418
  if (e.evt.pointerType === "touch" && Object.keys(this.pointers).length > 1) return;
19417
- if (e.evt.pointerType === "mouse" && e.evt.button !== 0) return;
19418
- if (e.evt.pointerType === "pen" && e.evt.pressure <= .05) return;
19419
+ if (e.evt.pointerType === "mouse" && e.evt?.button !== 0) return;
19420
+ if (e.evt.pointerType === "pen" && e.evt?.pressure <= .05) return;
19419
19421
  if (!this.initialized) return;
19420
19422
  if (!this.active) return;
19421
19423
  if (stage.mode() !== WEAVE_STAGE_DEFAULT_MODE) return;
@@ -19468,8 +19470,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19468
19470
  this.panLoopId = requestAnimationFrame(() => this.panLoop());
19469
19471
  });
19470
19472
  const handleMouseMove = (e) => {
19473
+ if (!e?.evt) return;
19471
19474
  const moved = this.checkMoved(e);
19472
- if (e.evt.buttons === 0) return;
19475
+ if (e.evt?.buttons === 0) return;
19473
19476
  if (e.evt.pointerType === "touch" && Object.keys(this.pointers).length > 1) return;
19474
19477
  if (!this.initialized) return;
19475
19478
  if (!this.active) return;
@@ -19635,7 +19638,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19635
19638
  this.hideHoverState();
19636
19639
  const selectedGroup = getTargetedNode(this.instance);
19637
19640
  if (!this.initialized) return;
19638
- if (e.evt.pointerType === "mouse" && e.evt.button && e.evt.button !== 0) return;
19641
+ if (e.evt.pointerType === "mouse" && e.evt?.button && e.evt?.button !== 0) return;
19639
19642
  let areNodesSelected = false;
19640
19643
  let nodeTargeted = selectedGroup && !(selectedGroup.getAttrs().active ?? false) ? selectedGroup : e.target;
19641
19644
  if (e.target === this.instance.getStage()) {
@@ -19698,7 +19701,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19698
19701
  if (areNodesSelected) {
19699
19702
  stage.container().tabIndex = 1;
19700
19703
  stage.container().focus();
19701
- stage.container().style.cursor = nodeTargeted.defineMousePointer?.() ?? "grab";
19704
+ stage.container().style.cursor = (typeof nodeTargeted?.defineMousePointer === "function" ? nodeTargeted.defineMousePointer() : null) ?? "grab";
19702
19705
  }
19703
19706
  this.triggerSelectedNodesEvent();
19704
19707
  }
@@ -19858,6 +19861,10 @@ const WEAVE_COPY_PASTE_CONFIG_DEFAULT = {
19858
19861
  }
19859
19862
  };
19860
19863
 
19864
+ //#endregion
19865
+ //#region src/actions/fit-to-selection-tool/constants.ts
19866
+ const FIT_TO_SELECTION_TOOL_ACTION_NAME = "fitToSelectionTool";
19867
+
19861
19868
  //#endregion
19862
19869
  //#region src/plugins/copy-paste-nodes/copy-paste-nodes.ts
19863
19870
  var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
@@ -20069,8 +20076,8 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
20069
20076
  }
20070
20077
  const nodesSelectionPlugin = this.getNodesSelectionPlugin();
20071
20078
  nodesSelectionPlugin?.setSelectedNodes(realNodes);
20072
- this.instance?.triggerAction("fitToSelectionTool", {
20073
- previousAction: "selectionTool",
20079
+ this.instance?.triggerAction(FIT_TO_SELECTION_TOOL_ACTION_NAME, {
20080
+ previousAction: SELECTION_TOOL_ACTION_NAME,
20074
20081
  smartZoom: true
20075
20082
  });
20076
20083
  this.instance.emitEvent("onPaste", {
@@ -20345,6 +20352,33 @@ const augmentKonvaNodeClass = (config) => {
20345
20352
  Konva.Node.prototype.closeCrop = function() {};
20346
20353
  Konva.Node.prototype.resetCrop = function() {};
20347
20354
  Konva.Node.prototype.dblClick = function() {};
20355
+ Konva.Node.prototype.allowedAnchors = function() {
20356
+ return [];
20357
+ };
20358
+ Konva.Node.prototype.isSelectable = function() {
20359
+ return true;
20360
+ };
20361
+ Konva.Node.prototype.handleMouseover = function() {};
20362
+ Konva.Node.prototype.handleMouseout = function() {};
20363
+ Konva.Node.prototype.handleSelectNode = function() {};
20364
+ Konva.Node.prototype.handleDeselectNode = function() {};
20365
+ Konva.Node.prototype.defineMousePointer = function() {
20366
+ return "default";
20367
+ };
20368
+ Konva.Node.prototype.canBeHovered = function() {
20369
+ return false;
20370
+ };
20371
+ Konva.Node.prototype.canDrag = function() {
20372
+ return false;
20373
+ };
20374
+ Konva.Node.prototype.canMoveToContainer = function() {
20375
+ return false;
20376
+ };
20377
+ Konva.Node.prototype.getNodeAnchors = function() {
20378
+ return [];
20379
+ };
20380
+ Konva.Node.prototype.lockMutex = function() {};
20381
+ Konva.Node.prototype.releaseMutex = function() {};
20348
20382
  };
20349
20383
  var WeaveNode = class {
20350
20384
  async register(instance) {
@@ -20629,10 +20663,11 @@ var WeaveNode = class {
20629
20663
  node.off("dragstart");
20630
20664
  node.on("dragstart", (e) => {
20631
20665
  const nodeTarget = e.target;
20666
+ if (!e.evt) return;
20632
20667
  let isWheelMousePressed = false;
20633
- if (e.evt.button === 1) isWheelMousePressed = true;
20668
+ if (e.evt?.button === 1) isWheelMousePressed = true;
20634
20669
  this.getNodesSelectionFeedbackPlugin()?.hideSelectionHalo(nodeTarget);
20635
- const canMove = nodeTarget?.canDrag() ?? false;
20670
+ const canMove = typeof nodeTarget?.canDrag === "function" ? nodeTarget.canDrag() : false;
20636
20671
  if (!canMove) {
20637
20672
  nodeTarget.stopDrag();
20638
20673
  return;
@@ -20684,7 +20719,7 @@ var WeaveNode = class {
20684
20719
  nodesSelectionPlugin?.setSelectedNodes([]);
20685
20720
  requestAnimationFrame(() => {
20686
20721
  nodesSelectionPlugin?.setSelectedNodes(this.instance.getCloningManager().getClones());
20687
- clone?.startDrag(e.evt);
20722
+ if (clone?.getStage()) clone.startDrag(e.evt);
20688
20723
  });
20689
20724
  }
20690
20725
  if (this.getNodesSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.setMutexLock({
@@ -20695,7 +20730,7 @@ var WeaveNode = class {
20695
20730
  const handleDragMove = (e) => {
20696
20731
  const nodeTarget = e.target;
20697
20732
  let isWheelMousePressed = false;
20698
- if (e.evt.button === 1) isWheelMousePressed = true;
20733
+ if (e.evt?.button === 1) isWheelMousePressed = true;
20699
20734
  e.cancelBubble = true;
20700
20735
  if (e.evt?.buttons === 0) {
20701
20736
  nodeTarget.stopDrag();
@@ -20883,12 +20918,12 @@ var WeaveNode = class {
20883
20918
  }
20884
20919
  if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20885
20920
  showHover = true;
20886
- stage.container().style.cursor = realNode?.defineMousePointer() ?? "pointer";
20921
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "pointer";
20887
20922
  cancelBubble = true;
20888
20923
  }
20889
20924
  if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20890
20925
  showHover = true;
20891
- stage.container().style.cursor = realNode?.defineMousePointer() ?? "grab";
20926
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "grab";
20892
20927
  cancelBubble = true;
20893
20928
  }
20894
20929
  if (!isTargetable) cancelBubble = true;
@@ -22152,7 +22187,7 @@ var WeaveRegisterManager = class {
22152
22187
 
22153
22188
  //#endregion
22154
22189
  //#region package.json
22155
- var version = "4.0.0";
22190
+ var version = "4.1.0";
22156
22191
 
22157
22192
  //#endregion
22158
22193
  //#region src/managers/setup.ts
@@ -24293,6 +24328,7 @@ function loadImageSource(image, options) {
24293
24328
  }
24294
24329
  async function downscaleImageFile(file, ratio) {
24295
24330
  const bitmap = await createImageBitmap(file);
24331
+ if (bitmap.width === 0) throw new Error("Invalid image", { cause: "InvalidImage" });
24296
24332
  const width = Math.round(bitmap.width * ratio);
24297
24333
  const height = Math.round(bitmap.height * ratio);
24298
24334
  const canvas = document.createElement("canvas");
@@ -24309,13 +24345,19 @@ function getImageSizeFromFile(file) {
24309
24345
  const img = new Image();
24310
24346
  const url = URL.createObjectURL(file);
24311
24347
  img.onload = () => {
24348
+ if (img.naturalWidth === 0) {
24349
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24350
+ return;
24351
+ }
24312
24352
  resolve({
24313
24353
  width: img.naturalWidth,
24314
24354
  height: img.naturalHeight
24315
24355
  });
24316
24356
  URL.revokeObjectURL(url);
24317
24357
  };
24318
- img.onerror = reject;
24358
+ img.onerror = () => {
24359
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24360
+ };
24319
24361
  img.src = url;
24320
24362
  });
24321
24363
  }
@@ -24339,6 +24381,10 @@ const downscaleImageFromURL = (url, options) => {
24339
24381
  const img = new Image();
24340
24382
  img.crossOrigin = crossOrigin;
24341
24383
  img.onload = () => {
24384
+ if (img.naturalWidth === 0) {
24385
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24386
+ return;
24387
+ }
24342
24388
  const ratio = Math.min(maxWidth / img.width, maxHeight / img.height, 1);
24343
24389
  const width = Math.round(img.width * ratio);
24344
24390
  const height = Math.round(img.height * ratio);
@@ -24349,7 +24395,9 @@ const downscaleImageFromURL = (url, options) => {
24349
24395
  ctx.drawImage(img, 0, 0, width, height);
24350
24396
  resolve(canvas.toDataURL(type));
24351
24397
  };
24352
- img.onerror = reject;
24398
+ img.onerror = () => {
24399
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24400
+ };
24353
24401
  img.src = url;
24354
24402
  });
24355
24403
  };
@@ -27229,15 +27277,24 @@ var WeaveImageNode = class extends WeaveNode {
27229
27277
  const imageURLToLoad = imageURL ?? "http://localhost/false-image";
27230
27278
  this.imageFallback[imageId] = Konva.Util.createImageElement();
27231
27279
  this.imageFallback[imageId].crossOrigin = this.config.crossOrigin;
27232
- this.imageFallback[imageId].onerror = (error) => {
27280
+ this.imageFallback[imageId].onerror = () => {
27233
27281
  this.imageState[imageId] = {
27234
27282
  status: "error-fallback",
27235
27283
  loaded: false,
27236
27284
  error: true
27237
27285
  };
27238
- onError(error);
27286
+ onError(new Error(`Failed to load fallback image from provided URL`, { cause: "ErrorLoadingFallbackImage" }));
27239
27287
  };
27240
27288
  this.imageFallback[imageId].onload = async () => {
27289
+ if (this.imageFallback[imageId].width === 0) {
27290
+ this.imageState[imageId] = {
27291
+ status: "error-fallback",
27292
+ loaded: false,
27293
+ error: true
27294
+ };
27295
+ onError(new Error(`Invalid fallback image provided`, { cause: "InvalidFallbackImage" }));
27296
+ return;
27297
+ }
27241
27298
  this.imageState[imageId] = {
27242
27299
  status: "loading",
27243
27300
  loaded: true,
@@ -27264,15 +27321,19 @@ var WeaveImageNode = class extends WeaveNode {
27264
27321
  }
27265
27322
  this.imageSource[imageId] = Konva.Util.createImageElement();
27266
27323
  this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
27267
- this.imageSource[imageId].onerror = (error) => {
27324
+ this.imageSource[imageId].onerror = () => {
27268
27325
  if (!loadingTryout) {
27269
27326
  const stage = this.instance.getStage();
27270
27327
  const image = stage.findOne(`#${imageId}`);
27271
27328
  if (image) this.setErrorState(imageId, image);
27272
27329
  }
27273
- onError(error);
27330
+ onError(new Error(`Failed to load image from provided URL`, { cause: "ErrorLoadingImage" }));
27274
27331
  };
27275
27332
  this.imageSource[imageId].onload = async () => {
27333
+ if (this.imageSource[imageId].width === 0) {
27334
+ onError(new Error(`Invalid image provided`, { cause: "InvalidImage" }));
27335
+ return;
27336
+ }
27276
27337
  const stage = this.instance.getStage();
27277
27338
  if (!this.instance.isServerSide()) stage.container().style.cursor = "pointer";
27278
27339
  this.imageState[imageId] = {
@@ -27364,14 +27425,16 @@ var WeaveImageNode = class extends WeaveNode {
27364
27425
  }
27365
27426
  },
27366
27427
  onError: (error) => {
27367
- if (!this.config.useFallbackImage) {
27428
+ let isInvalidImage = false;
27429
+ if (error.cause === "InvalidImage") isInvalidImage = true;
27430
+ if (!this.config.useFallbackImage && !isInvalidImage) {
27368
27431
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27369
27432
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27370
27433
  this.loadImageTryout(id);
27371
27434
  return;
27372
27435
  } else this.setErrorState(id, image);
27373
27436
  }
27374
- if (loadTryout) {
27437
+ if (loadTryout && !isInvalidImage) {
27375
27438
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27376
27439
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27377
27440
  this.loadImageTryout(id);
@@ -27384,12 +27447,7 @@ var WeaveImageNode = class extends WeaveNode {
27384
27447
  return;
27385
27448
  }
27386
27449
  this.setErrorState(id, image);
27387
- image.setAttrs({ image: void 0 });
27388
- console.error("Error loading image", error);
27389
27450
  this.resolveAsyncElement(id);
27390
- imagePlaceholder?.setAttrs({ visible: true });
27391
- internalImage?.setAttrs({ visible: false });
27392
- this.cacheNode(image);
27393
27451
  }
27394
27452
  }, loadTryout);
27395
27453
  }
@@ -28384,8 +28442,8 @@ var WeaveStrokeNode = class extends WeaveNode {
28384
28442
  const segLen = Math.hypot(dx, dy) || 1;
28385
28443
  const nx = -dy / segLen;
28386
28444
  const ny = dx / segLen;
28387
- const w0 = baseW * p0.pressure / 2;
28388
- const w1 = baseW * p1.pressure / 2;
28445
+ const w0 = Math.max(baseW * p0.pressure / 2, .5);
28446
+ const w1 = Math.max(baseW * p1.pressure / 2, .5);
28389
28447
  let traveled = 0;
28390
28448
  while (traveled < segLen) {
28391
28449
  const step = Math.min(dashRemaining, segLen - traveled);
@@ -30075,8 +30133,7 @@ var WeaveVideoNode = class extends WeaveNode {
30075
30133
  this.videoPlaceholder[id] = Konva.Util.createImageElement();
30076
30134
  this.videoPlaceholder[id].crossOrigin = this.config.crossOrigin;
30077
30135
  this.videoPlaceholder[id].src = realVideoPlaceholderURL;
30078
- this.videoPlaceholder[id].onerror = (error) => {
30079
- console.error("Error loading video placeholder", realVideoPlaceholderURL, error);
30136
+ this.videoPlaceholder[id].onerror = () => {
30080
30137
  this.resolveAsyncElement(id);
30081
30138
  };
30082
30139
  this.videoPlaceholder[id].onload = () => {
@@ -33115,13 +33172,13 @@ var WeaveZoomOutToolAction = class extends WeaveAction {
33115
33172
  const stageZoomPlugin = this.getStageZoomPlugin();
33116
33173
  if (!stageZoomPlugin.canZoomOut()) return;
33117
33174
  stageZoomPlugin.zoomOut();
33118
- this.previousAction = params.previousAction;
33175
+ this.previousAction = params?.previousAction;
33119
33176
  this.cancelAction = cancelAction;
33120
33177
  this.cancelAction();
33121
33178
  }
33122
33179
  cleanup() {
33123
33180
  const stage = this.instance.getStage();
33124
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33181
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33125
33182
  stage.container().style.cursor = "default";
33126
33183
  }
33127
33184
  };
@@ -33153,13 +33210,13 @@ var WeaveZoomInToolAction = class extends WeaveAction {
33153
33210
  const stageZoomPlugin = this.getStageZoomPlugin();
33154
33211
  if (!stageZoomPlugin.canZoomIn()) return;
33155
33212
  stageZoomPlugin.zoomIn();
33156
- this.previousAction = params.previousAction;
33213
+ this.previousAction = params?.previousAction;
33157
33214
  this.cancelAction = cancelAction;
33158
33215
  this.cancelAction();
33159
33216
  }
33160
33217
  cleanup() {
33161
33218
  const stage = this.instance.getStage();
33162
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33219
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33163
33220
  stage.container().style.cursor = "default";
33164
33221
  }
33165
33222
  };
@@ -33190,21 +33247,17 @@ var WeaveFitToScreenToolAction = class extends WeaveAction {
33190
33247
  trigger(cancelAction, params) {
33191
33248
  const stageZoomPlugin = this.getStageZoomPlugin();
33192
33249
  if (stageZoomPlugin) stageZoomPlugin.fitToScreen({ overrideZoom: params?.overrideZoom ?? true });
33193
- this.previousAction = params.previousAction;
33250
+ this.previousAction = params?.previousAction;
33194
33251
  this.cancelAction = cancelAction;
33195
33252
  this.cancelAction();
33196
33253
  }
33197
33254
  cleanup() {
33198
33255
  const stage = this.instance.getStage();
33199
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33256
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33200
33257
  stage.container().style.cursor = "default";
33201
33258
  }
33202
33259
  };
33203
33260
 
33204
- //#endregion
33205
- //#region src/actions/fit-to-selection-tool/constants.ts
33206
- const FIT_TO_SELECTION_TOOL_ACTION_NAME = "fitToSelectionTool";
33207
-
33208
33261
  //#endregion
33209
33262
  //#region src/actions/fit-to-selection-tool/fit-to-selection-tool.ts
33210
33263
  var WeaveFitToSelectionToolAction = class extends WeaveAction {
@@ -33236,13 +33289,13 @@ var WeaveFitToSelectionToolAction = class extends WeaveAction {
33236
33289
  smartZoom: params?.smartZoom ?? false,
33237
33290
  overrideZoom: params?.overrideZoom ?? true
33238
33291
  });
33239
- this.previousAction = params.previousAction;
33292
+ this.previousAction = params?.previousAction;
33240
33293
  this.cancelAction = cancelAction;
33241
33294
  this.cancelAction();
33242
33295
  }
33243
33296
  cleanup() {
33244
33297
  const stage = this.instance.getStage();
33245
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33298
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33246
33299
  stage.container().style.cursor = "default";
33247
33300
  }
33248
33301
  };
@@ -34468,6 +34521,11 @@ const BRUSH_TOOL_DEFAULT_CONFIG = { interpolationSteps: 10 };
34468
34521
  var WeaveBrushToolAction = class extends WeaveAction {
34469
34522
  initialized = false;
34470
34523
  isSpacePressed = false;
34524
+ penActive = false;
34525
+ lastSmoothedPressure = .5;
34526
+ lastPointerPos = null;
34527
+ lastPointerTime = 0;
34528
+ predictedCount = 0;
34471
34529
  onPropsChange = void 0;
34472
34530
  onInit = void 0;
34473
34531
  constructor(params) {
@@ -34497,11 +34555,29 @@ var WeaveBrushToolAction = class extends WeaveAction {
34497
34555
  };
34498
34556
  }
34499
34557
  getEventPressure(e) {
34500
- if (e.evt.pointerType && e.evt.pointerType === "pen") return e.evt.pressure || .5;
34501
- return .5;
34558
+ const now$2 = performance.now();
34559
+ let velocity = 0;
34560
+ if (this.lastPointerPos && now$2 - this.lastPointerTime > 0) {
34561
+ const dx = e.evt.clientX - this.lastPointerPos.x;
34562
+ const dy = e.evt.clientY - this.lastPointerPos.y;
34563
+ velocity = Math.hypot(dx, dy) / (now$2 - this.lastPointerTime) * 1e3;
34564
+ }
34565
+ this.lastPointerPos = {
34566
+ x: e.evt.clientX,
34567
+ y: e.evt.clientY
34568
+ };
34569
+ this.lastPointerTime = now$2;
34570
+ const alpha = Math.min(Math.max(velocity / 1500, .15), .6);
34571
+ let raw;
34572
+ if (e.evt.pointerType === "pen") raw = e.evt.pressure || .5;
34573
+ else raw = .5;
34574
+ this.lastSmoothedPressure = alpha * raw + (1 - alpha) * this.lastSmoothedPressure;
34575
+ return Math.max(this.lastSmoothedPressure, .15);
34502
34576
  }
34503
34577
  setupEvents() {
34504
34578
  const stage = this.instance.getStage();
34579
+ this.prevTouchAction = stage.container().style.touchAction;
34580
+ stage.container().style.touchAction = "none";
34505
34581
  window.addEventListener("keyup", (e) => {
34506
34582
  if (e.code === "Space" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) this.isSpacePressed = false;
34507
34583
  }, { signal: this.instance.getEventsController()?.signal });
@@ -34526,7 +34602,9 @@ var WeaveBrushToolAction = class extends WeaveAction {
34526
34602
  if (this.state !== BRUSH_TOOL_STATE.IDLE) return;
34527
34603
  if (this.getZoomPlugin()?.isPinching()) return;
34528
34604
  if (this.isSpacePressed) return;
34529
- if (e.evt.button !== 0) return;
34605
+ if (e?.evt?.button !== 0) return;
34606
+ if (e.evt.pointerType === "touch" && this.penActive) return;
34607
+ if (e.evt.pointerType === "pen") this.penActive = true;
34530
34608
  const pointPressure = this.getEventPressure(e);
34531
34609
  this.handleStartStroke(pointPressure);
34532
34610
  e.evt.stopPropagation();
@@ -34537,12 +34615,27 @@ var WeaveBrushToolAction = class extends WeaveAction {
34537
34615
  this.setCursor();
34538
34616
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34539
34617
  if (this.getZoomPlugin()?.isPinching()) return;
34540
- const pointPressure = this.getEventPressure(e);
34541
- this.handleMovement(pointPressure);
34618
+ const coalescedEvents = e.evt.getCoalescedEvents ? e.evt.getCoalescedEvents() : [];
34619
+ if (coalescedEvents.length > 1) {
34620
+ for (const ce of coalescedEvents) {
34621
+ const pointPressure = ce.pointerType === "pen" && typeof ce.pressure === "number" ? ce.pressure : .5;
34622
+ this.handleMovement(pointPressure, void 0, false);
34623
+ }
34624
+ const predictedEvents = e.evt.getPredictedEvents ? e.evt.getPredictedEvents() : [];
34625
+ if (predictedEvents.length > 0) {
34626
+ const last = predictedEvents[predictedEvents.length - 1];
34627
+ const predPressure = last.pointerType === "pen" && typeof last.pressure === "number" ? last.pressure : .5;
34628
+ this.handleMovement(predPressure, last, true);
34629
+ }
34630
+ } else {
34631
+ const pointPressure = this.getEventPressure(e);
34632
+ this.handleMovement(pointPressure, void 0, false);
34633
+ }
34542
34634
  e.evt.stopPropagation();
34543
34635
  };
34544
34636
  stage.on("pointermove", handlePointerMove);
34545
34637
  const handlePointerUp = (e) => {
34638
+ this.penActive = false;
34546
34639
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34547
34640
  if (this.getZoomPlugin()?.isPinching()) return;
34548
34641
  this.handleEndStroke();
@@ -34579,6 +34672,10 @@ var WeaveBrushToolAction = class extends WeaveAction {
34579
34672
  };
34580
34673
  }
34581
34674
  handleStartStroke(pressure) {
34675
+ this.lastSmoothedPressure = .5;
34676
+ this.lastPointerPos = null;
34677
+ this.lastPointerTime = 0;
34678
+ this.predictedCount = 0;
34582
34679
  const { mousePoint, container, measureContainer } = this.instance.getMousePointer();
34583
34680
  this.clickPoint = mousePoint;
34584
34681
  this.container = container;
@@ -34607,17 +34704,25 @@ var WeaveBrushToolAction = class extends WeaveAction {
34607
34704
  }
34608
34705
  this.setState(BRUSH_TOOL_STATE.DEFINE_STROKE);
34609
34706
  }
34610
- handleMovement(pressure) {
34707
+ handleMovement(pressure, predictedEvent, isPredicted = false) {
34611
34708
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34709
+ const stage = this.instance.getStage();
34612
34710
  const tempStroke = this.instance.getStage().findOne(`#${this.strokeId}`);
34613
34711
  if (this.measureContainer && tempStroke) {
34712
+ if (predictedEvent) stage.setPointersPositions(predictedEvent);
34614
34713
  const { mousePoint } = this.instance.getMousePointerRelativeToContainer(this.measureContainer);
34615
34714
  const currentPoint = {
34616
34715
  x: mousePoint.x - tempStroke.x(),
34617
34716
  y: mousePoint.y - tempStroke.y(),
34618
34717
  pressure
34619
34718
  };
34620
- const newStrokeElements = [...tempStroke.getAttrs().strokeElements, currentPoint];
34719
+ let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34720
+ if (!isPredicted && this.predictedCount > 0) {
34721
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34722
+ this.predictedCount = 0;
34723
+ }
34724
+ newStrokeElements.push(currentPoint);
34725
+ if (isPredicted) this.predictedCount++;
34621
34726
  const box = this.getBoundingBox(newStrokeElements);
34622
34727
  tempStroke.setAttrs({
34623
34728
  width: box.width,
@@ -34637,17 +34742,22 @@ var WeaveBrushToolAction = class extends WeaveAction {
34637
34742
  if (nodeHandler) {
34638
34743
  const box = this.getBoundingBox(tempStroke.getAttrs().strokeElements);
34639
34744
  let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34745
+ if (this.predictedCount > 0) {
34746
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34747
+ this.predictedCount = 0;
34748
+ }
34640
34749
  newStrokeElements = newStrokeElements.map((point) => ({
34641
34750
  ...point,
34642
34751
  x: point.x - box.x,
34643
34752
  y: point.y - box.y
34644
34753
  }));
34754
+ const compressedPoints = simplify(newStrokeElements, 1, true);
34645
34755
  tempStroke.setAttrs({
34646
34756
  width: box.width,
34647
34757
  height: box.height,
34648
34758
  x: box.x,
34649
34759
  y: box.y,
34650
- strokeElements: newStrokeElements
34760
+ strokeElements: compressedPoints
34651
34761
  });
34652
34762
  const realNode = this.instance.getStage().findOne(`#${tempStroke.getAttrs().id}`);
34653
34763
  if (realNode) realNode.destroy();
@@ -34683,6 +34793,7 @@ var WeaveBrushToolAction = class extends WeaveAction {
34683
34793
  }
34684
34794
  cleanup() {
34685
34795
  const stage = this.instance.getStage();
34796
+ stage.container().style.touchAction = this.prevTouchAction;
34686
34797
  stage.container().style.cursor = "default";
34687
34798
  this.instance.emitEvent("onAddedBrush");
34688
34799
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -39105,13 +39216,13 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
39105
39216
  });
39106
39217
  stage.on("pointerdown", (e) => {
39107
39218
  const activeAction = this.instance.getActiveAction();
39108
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39109
- if (e && (e.evt.button === 2 || e.evt.buttons === 4)) this.isMouseMiddleButtonPressed = true;
39219
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39220
+ if (e && (e?.evt?.button === 2 || e?.evt?.buttons === 4)) this.isMouseMiddleButtonPressed = true;
39110
39221
  });
39111
39222
  stage.on("pointerup", (e) => {
39112
39223
  const activeAction = this.instance.getActiveAction();
39113
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
39114
- if (e && (e.evt.button === 1 || e.evt.buttons === 0)) this.isMouseMiddleButtonPressed = false;
39224
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
39225
+ if (e && (e?.evt?.button === 1 || e?.evt?.buttons === 0)) this.isMouseMiddleButtonPressed = false;
39115
39226
  });
39116
39227
  const handleMouseMove = () => {
39117
39228
  if (!this.enabled || !(this.isSpaceKeyPressed || this.isMouseMiddleButtonPressed || this.moveToolActive)) return;
@@ -39428,16 +39539,16 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
39428
39539
  let lastPos = null;
39429
39540
  stage.on("pointerdown", (e) => {
39430
39541
  this.pointers.set(e.evt.pointerId, {
39431
- x: e.evt.clientX,
39432
- y: e.evt.clientY
39542
+ x: e?.evt?.clientX ?? 0,
39543
+ y: e?.evt?.clientY ?? 0
39433
39544
  });
39434
39545
  if (this.pointers.size > 1) return;
39435
39546
  const activeAction = this.instance.getActiveAction();
39436
39547
  this.enableMove = false;
39437
39548
  if (activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39438
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 1) this.isMouseLeftButtonPressed = true;
39439
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 4) this.isMouseMiddleButtonPressed = true;
39440
- const isTouchOrPen = ["touch", "pen"].includes(e.evt.pointerType);
39549
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 1) this.isMouseLeftButtonPressed = true;
39550
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 4) this.isMouseMiddleButtonPressed = true;
39551
+ const isTouchOrPen = ["touch", "pen"].includes(e?.evt?.pointerType);
39441
39552
  if (this.enabled && (this.isSpaceKeyPressed || this.moveToolActive && (this.isMouseLeftButtonPressed || isTouchOrPen) || this.isMouseMiddleButtonPressed)) this.enableMove = true;
39442
39553
  if (this.enableMove) {
39443
39554
  this.isDragging = true;
@@ -39446,7 +39557,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
39446
39557
  }
39447
39558
  });
39448
39559
  stage.on("pointercancel", (e) => {
39449
- this.pointers.delete(e.evt.pointerId);
39560
+ if (e?.evt?.pointerId) this.pointers.delete(e.evt.pointerId);
39450
39561
  lastPos = null;
39451
39562
  });
39452
39563
  const handleMouseMove = (e) => {