@inditextech/weave-sdk 3.9.1 → 3.10.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/types.js CHANGED
@@ -4,6 +4,7 @@ import { WEAVE_ASYNC_STATUS, WEAVE_AWARENESS_LAYER_ID, WEAVE_EXPORT_BACKGROUND_C
4
4
  import { getYjsDoc, getYjsValue, observeDeep, syncedStore } from "@syncedstore/core";
5
5
  import * as Y$1 from "yjs";
6
6
  import * as Y from "yjs";
7
+ import simplify from "simplify-js";
7
8
  import "konva/lib/types";
8
9
 
9
10
  //#region rolldown:runtime
@@ -18834,7 +18835,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18834
18835
  const nodesSelected = tr.nodes();
18835
18836
  if (nodesSelected.length === 1) {
18836
18837
  const node = nodesSelected[0];
18837
- stage.container().style.cursor = node.defineMousePointer() ?? "grab";
18838
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "grab";
18838
18839
  } else stage.container().style.cursor = "grab";
18839
18840
  });
18840
18841
  tr.on("mouseout", (e) => {
@@ -18891,8 +18892,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18891
18892
  let selectedNodes = [];
18892
18893
  tr.on("dragstart", (e) => {
18893
18894
  this.dragInProcess = true;
18895
+ if (!e?.evt) return;
18894
18896
  let isWheelMousePressed = false;
18895
- if (e.evt.button === 1) isWheelMousePressed = true;
18897
+ if (e.evt?.button === 1) isWheelMousePressed = true;
18896
18898
  const mainLayer = this.instance.getMainLayer();
18897
18899
  if (!mainLayer) return;
18898
18900
  initialPos = {
@@ -18929,7 +18931,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18929
18931
  y: e.target.y()
18930
18932
  };
18931
18933
  let isWheelMousePressed = false;
18932
- if (e.evt.button === 1) isWheelMousePressed = true;
18934
+ if (e.evt?.button === 1) isWheelMousePressed = true;
18933
18935
  e.cancelBubble = true;
18934
18936
  if (initialPos) {
18935
18937
  const moved = this.checkMovedDrag(initialPos, actualPos);
@@ -19272,8 +19274,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19272
19274
  this.handledClickOrTap = false;
19273
19275
  this.pointers[e.evt.pointerId] = e.evt;
19274
19276
  if (e.evt.pointerType === "touch" && Object.keys(this.pointers).length > 1) return;
19275
- if (e.evt.pointerType === "mouse" && e.evt.button !== 0) return;
19276
- if (e.evt.pointerType === "pen" && e.evt.pressure <= .05) return;
19277
+ if (e.evt.pointerType === "mouse" && e.evt?.button !== 0) return;
19278
+ if (e.evt.pointerType === "pen" && e.evt?.pressure <= .05) return;
19277
19279
  if (!this.initialized) return;
19278
19280
  if (!this.active) return;
19279
19281
  if (stage.mode() !== WEAVE_STAGE_DEFAULT_MODE) return;
@@ -19326,8 +19328,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19326
19328
  this.panLoopId = requestAnimationFrame(() => this.panLoop());
19327
19329
  });
19328
19330
  const handleMouseMove = (e) => {
19331
+ if (!e?.evt) return;
19329
19332
  const moved = this.checkMoved(e);
19330
- if (e.evt.buttons === 0) return;
19333
+ if (e.evt?.buttons === 0) return;
19331
19334
  if (e.evt.pointerType === "touch" && Object.keys(this.pointers).length > 1) return;
19332
19335
  if (!this.initialized) return;
19333
19336
  if (!this.active) return;
@@ -19497,7 +19500,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19497
19500
  this.hideHoverState();
19498
19501
  const selectedGroup = getTargetedNode(this.instance);
19499
19502
  if (!this.initialized) return;
19500
- if (e.evt.pointerType === "mouse" && e.evt.button && e.evt.button !== 0) return;
19503
+ if (e.evt.pointerType === "mouse" && e.evt?.button && e.evt?.button !== 0) return;
19501
19504
  let areNodesSelected = false;
19502
19505
  let nodeTargeted = selectedGroup && !(selectedGroup.getAttrs().active ?? false) ? selectedGroup : e.target;
19503
19506
  if (e.target === this.instance.getStage()) {
@@ -19560,7 +19563,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19560
19563
  if (areNodesSelected) {
19561
19564
  stage.container().tabIndex = 1;
19562
19565
  stage.container().focus();
19563
- stage.container().style.cursor = nodeTargeted.defineMousePointer() ?? "grab";
19566
+ stage.container().style.cursor = (typeof nodeTargeted?.defineMousePointer === "function" ? nodeTargeted.defineMousePointer() : null) ?? "grab";
19564
19567
  }
19565
19568
  this.triggerSelectedNodesEvent();
19566
19569
  }
@@ -19728,6 +19731,10 @@ const WEAVE_COPY_PASTE_CONFIG_DEFAULT = {
19728
19731
  }
19729
19732
  };
19730
19733
 
19734
+ //#endregion
19735
+ //#region src/actions/fit-to-selection-tool/constants.ts
19736
+ const FIT_TO_SELECTION_TOOL_ACTION_NAME = "fitToSelectionTool";
19737
+
19731
19738
  //#endregion
19732
19739
  //#region src/plugins/copy-paste-nodes/copy-paste-nodes.ts
19733
19740
  var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
@@ -19939,8 +19946,8 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
19939
19946
  }
19940
19947
  const nodesSelectionPlugin = this.getNodesSelectionPlugin();
19941
19948
  nodesSelectionPlugin?.setSelectedNodes(realNodes);
19942
- this.instance?.triggerAction("fitToSelectionTool", {
19943
- previousAction: "selectionTool",
19949
+ this.instance?.triggerAction(FIT_TO_SELECTION_TOOL_ACTION_NAME, {
19950
+ previousAction: SELECTION_TOOL_ACTION_NAME,
19944
19951
  smartZoom: true
19945
19952
  });
19946
19953
  this.instance.emitEvent("onPaste", {
@@ -20215,6 +20222,33 @@ const augmentKonvaNodeClass = (config) => {
20215
20222
  Konva.Node.prototype.closeCrop = function() {};
20216
20223
  Konva.Node.prototype.resetCrop = function() {};
20217
20224
  Konva.Node.prototype.dblClick = function() {};
20225
+ Konva.Node.prototype.allowedAnchors = function() {
20226
+ return [];
20227
+ };
20228
+ Konva.Node.prototype.isSelectable = function() {
20229
+ return true;
20230
+ };
20231
+ Konva.Node.prototype.handleMouseover = function() {};
20232
+ Konva.Node.prototype.handleMouseout = function() {};
20233
+ Konva.Node.prototype.handleSelectNode = function() {};
20234
+ Konva.Node.prototype.handleDeselectNode = function() {};
20235
+ Konva.Node.prototype.defineMousePointer = function() {
20236
+ return "default";
20237
+ };
20238
+ Konva.Node.prototype.canBeHovered = function() {
20239
+ return false;
20240
+ };
20241
+ Konva.Node.prototype.canDrag = function() {
20242
+ return false;
20243
+ };
20244
+ Konva.Node.prototype.canMoveToContainer = function() {
20245
+ return false;
20246
+ };
20247
+ Konva.Node.prototype.getNodeAnchors = function() {
20248
+ return [];
20249
+ };
20250
+ Konva.Node.prototype.lockMutex = function() {};
20251
+ Konva.Node.prototype.releaseMutex = function() {};
20218
20252
  };
20219
20253
  var WeaveNode = class {
20220
20254
  async register(instance) {
@@ -20506,10 +20540,11 @@ var WeaveNode = class {
20506
20540
  node.off("dragstart");
20507
20541
  node.on("dragstart", (e) => {
20508
20542
  const nodeTarget = e.target;
20543
+ if (!e.evt) return;
20509
20544
  let isWheelMousePressed = false;
20510
- if (e.evt.button === 1) isWheelMousePressed = true;
20545
+ if (e.evt?.button === 1) isWheelMousePressed = true;
20511
20546
  this.getNodesSelectionFeedbackPlugin()?.hideSelectionHalo(nodeTarget);
20512
- const canMove = nodeTarget?.canDrag() ?? false;
20547
+ const canMove = typeof nodeTarget?.canDrag === "function" ? nodeTarget.canDrag() : false;
20513
20548
  if (!canMove) {
20514
20549
  nodeTarget.stopDrag();
20515
20550
  return;
@@ -20561,7 +20596,7 @@ var WeaveNode = class {
20561
20596
  nodesSelectionPlugin?.setSelectedNodes([]);
20562
20597
  requestAnimationFrame(() => {
20563
20598
  nodesSelectionPlugin?.setSelectedNodes(this.instance.getCloningManager().getClones());
20564
- clone?.startDrag(e.evt);
20599
+ if (clone?.getStage()) clone.startDrag(e.evt);
20565
20600
  });
20566
20601
  }
20567
20602
  if (this.getNodesSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.setMutexLock({
@@ -20572,7 +20607,7 @@ var WeaveNode = class {
20572
20607
  const handleDragMove = (e) => {
20573
20608
  const nodeTarget = e.target;
20574
20609
  let isWheelMousePressed = false;
20575
- if (e.evt.button === 1) isWheelMousePressed = true;
20610
+ if (e.evt?.button === 1) isWheelMousePressed = true;
20576
20611
  e.cancelBubble = true;
20577
20612
  if (e.evt?.buttons === 0) {
20578
20613
  nodeTarget.stopDrag();
@@ -20764,12 +20799,12 @@ var WeaveNode = class {
20764
20799
  }
20765
20800
  if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20766
20801
  showHover = true;
20767
- stage.container().style.cursor = realNode?.defineMousePointer() ?? "pointer";
20802
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "pointer";
20768
20803
  cancelBubble = true;
20769
20804
  }
20770
20805
  if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20771
20806
  showHover = true;
20772
- stage.container().style.cursor = realNode?.defineMousePointer() ?? "grab";
20807
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "grab";
20773
20808
  cancelBubble = true;
20774
20809
  }
20775
20810
  if (!isTargetable) cancelBubble = true;
@@ -22052,7 +22087,7 @@ var WeaveRegisterManager = class {
22052
22087
 
22053
22088
  //#endregion
22054
22089
  //#region package.json
22055
- var version = "3.9.1";
22090
+ var version = "3.10.0";
22056
22091
 
22057
22092
  //#endregion
22058
22093
  //#region src/managers/setup.ts
@@ -24230,6 +24265,7 @@ function loadImageSource(image, options) {
24230
24265
  }
24231
24266
  async function downscaleImageFile(file, ratio) {
24232
24267
  const bitmap = await createImageBitmap(file);
24268
+ if (bitmap.width === 0) throw new Error("Invalid image", { cause: "InvalidImage" });
24233
24269
  const width = Math.round(bitmap.width * ratio);
24234
24270
  const height = Math.round(bitmap.height * ratio);
24235
24271
  const canvas = document.createElement("canvas");
@@ -24246,13 +24282,19 @@ function getImageSizeFromFile(file) {
24246
24282
  const img = new Image();
24247
24283
  const url = URL.createObjectURL(file);
24248
24284
  img.onload = () => {
24285
+ if (img.naturalWidth === 0) {
24286
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24287
+ return;
24288
+ }
24249
24289
  resolve({
24250
24290
  width: img.naturalWidth,
24251
24291
  height: img.naturalHeight
24252
24292
  });
24253
24293
  URL.revokeObjectURL(url);
24254
24294
  };
24255
- img.onerror = reject;
24295
+ img.onerror = () => {
24296
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24297
+ };
24256
24298
  img.src = url;
24257
24299
  });
24258
24300
  }
@@ -24276,6 +24318,10 @@ const downscaleImageFromURL = (url, options) => {
24276
24318
  const img = new Image();
24277
24319
  img.crossOrigin = crossOrigin;
24278
24320
  img.onload = () => {
24321
+ if (img.naturalWidth === 0) {
24322
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24323
+ return;
24324
+ }
24279
24325
  const ratio = Math.min(maxWidth / img.width, maxHeight / img.height, 1);
24280
24326
  const width = Math.round(img.width * ratio);
24281
24327
  const height = Math.round(img.height * ratio);
@@ -24286,7 +24332,9 @@ const downscaleImageFromURL = (url, options) => {
24286
24332
  ctx.drawImage(img, 0, 0, width, height);
24287
24333
  resolve(canvas.toDataURL(type));
24288
24334
  };
24289
- img.onerror = reject;
24335
+ img.onerror = () => {
24336
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24337
+ };
24290
24338
  img.src = url;
24291
24339
  });
24292
24340
  };
@@ -27044,15 +27092,24 @@ var WeaveImageNode = class extends WeaveNode {
27044
27092
  const imageURLToLoad = imageURL ?? "http://localhost/false-image";
27045
27093
  this.imageFallback[imageId] = Konva.Util.createImageElement();
27046
27094
  this.imageFallback[imageId].crossOrigin = this.config.crossOrigin;
27047
- this.imageFallback[imageId].onerror = (error) => {
27095
+ this.imageFallback[imageId].onerror = () => {
27048
27096
  this.imageState[imageId] = {
27049
27097
  status: "error-fallback",
27050
27098
  loaded: false,
27051
27099
  error: true
27052
27100
  };
27053
- onError(error);
27101
+ onError(new Error(`Failed to load fallback image from provided URL`, { cause: "ErrorLoadingFallbackImage" }));
27054
27102
  };
27055
27103
  this.imageFallback[imageId].onload = async () => {
27104
+ if (this.imageFallback[imageId].width === 0) {
27105
+ this.imageState[imageId] = {
27106
+ status: "error-fallback",
27107
+ loaded: false,
27108
+ error: true
27109
+ };
27110
+ onError(new Error(`Invalid fallback image provided`, { cause: "InvalidFallbackImage" }));
27111
+ return;
27112
+ }
27056
27113
  this.imageState[imageId] = {
27057
27114
  status: "loading",
27058
27115
  loaded: true,
@@ -27079,15 +27136,19 @@ var WeaveImageNode = class extends WeaveNode {
27079
27136
  }
27080
27137
  this.imageSource[imageId] = Konva.Util.createImageElement();
27081
27138
  this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
27082
- this.imageSource[imageId].onerror = (error) => {
27139
+ this.imageSource[imageId].onerror = () => {
27083
27140
  if (!loadingTryout) {
27084
27141
  const stage = this.instance.getStage();
27085
27142
  const image = stage.findOne(`#${imageId}`);
27086
27143
  if (image) this.setErrorState(imageId, image);
27087
27144
  }
27088
- onError(error);
27145
+ onError(new Error(`Failed to load image from provided URL`, { cause: "ErrorLoadingImage" }));
27089
27146
  };
27090
27147
  this.imageSource[imageId].onload = async () => {
27148
+ if (this.imageSource[imageId].width === 0) {
27149
+ onError(new Error(`Invalid image provided`, { cause: "InvalidImage" }));
27150
+ return;
27151
+ }
27091
27152
  const stage = this.instance.getStage();
27092
27153
  if (!this.instance.isServerSide()) stage.container().style.cursor = "pointer";
27093
27154
  this.imageState[imageId] = {
@@ -27179,14 +27240,16 @@ var WeaveImageNode = class extends WeaveNode {
27179
27240
  }
27180
27241
  },
27181
27242
  onError: (error) => {
27182
- if (!this.config.useFallbackImage) {
27243
+ let isInvalidImage = false;
27244
+ if (error.cause === "InvalidImage") isInvalidImage = true;
27245
+ if (!this.config.useFallbackImage && !isInvalidImage) {
27183
27246
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27184
27247
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27185
27248
  this.loadImageTryout(id);
27186
27249
  return;
27187
27250
  } else this.setErrorState(id, image);
27188
27251
  }
27189
- if (loadTryout) {
27252
+ if (loadTryout && !isInvalidImage) {
27190
27253
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27191
27254
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27192
27255
  this.loadImageTryout(id);
@@ -27199,12 +27262,7 @@ var WeaveImageNode = class extends WeaveNode {
27199
27262
  return;
27200
27263
  }
27201
27264
  this.setErrorState(id, image);
27202
- image.setAttrs({ image: void 0 });
27203
- console.error("Error loading image", error);
27204
27265
  this.resolveAsyncElement(id);
27205
- imagePlaceholder?.setAttrs({ visible: true });
27206
- internalImage?.setAttrs({ visible: false });
27207
- this.cacheNode(image);
27208
27266
  }
27209
27267
  }, loadTryout);
27210
27268
  }
@@ -28005,8 +28063,8 @@ var WeaveStrokeNode = class extends WeaveNode {
28005
28063
  const segLen = Math.hypot(dx, dy) || 1;
28006
28064
  const nx = -dy / segLen;
28007
28065
  const ny = dx / segLen;
28008
- const w0 = baseW * p0.pressure / 2;
28009
- const w1 = baseW * p1.pressure / 2;
28066
+ const w0 = Math.max(baseW * p0.pressure / 2, .5);
28067
+ const w1 = Math.max(baseW * p1.pressure / 2, .5);
28010
28068
  let traveled = 0;
28011
28069
  while (traveled < segLen) {
28012
28070
  const step = Math.min(dashRemaining, segLen - traveled);
@@ -29696,8 +29754,7 @@ var WeaveVideoNode = class extends WeaveNode {
29696
29754
  this.videoPlaceholder[id] = Konva.Util.createImageElement();
29697
29755
  this.videoPlaceholder[id].crossOrigin = this.config.crossOrigin;
29698
29756
  this.videoPlaceholder[id].src = realVideoPlaceholderURL;
29699
- this.videoPlaceholder[id].onerror = (error) => {
29700
- console.error("Error loading video placeholder", realVideoPlaceholderURL, error);
29757
+ this.videoPlaceholder[id].onerror = () => {
29701
29758
  this.resolveAsyncElement(id);
29702
29759
  };
29703
29760
  this.videoPlaceholder[id].onload = () => {
@@ -32735,13 +32792,13 @@ var WeaveZoomOutToolAction = class extends WeaveAction {
32735
32792
  const stageZoomPlugin = this.getStageZoomPlugin();
32736
32793
  if (!stageZoomPlugin.canZoomOut()) return;
32737
32794
  stageZoomPlugin.zoomOut();
32738
- this.previousAction = params.previousAction;
32795
+ this.previousAction = params?.previousAction;
32739
32796
  this.cancelAction = cancelAction;
32740
32797
  this.cancelAction();
32741
32798
  }
32742
32799
  cleanup() {
32743
32800
  const stage = this.instance.getStage();
32744
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
32801
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
32745
32802
  stage.container().style.cursor = "default";
32746
32803
  }
32747
32804
  };
@@ -32773,13 +32830,13 @@ var WeaveZoomInToolAction = class extends WeaveAction {
32773
32830
  const stageZoomPlugin = this.getStageZoomPlugin();
32774
32831
  if (!stageZoomPlugin.canZoomIn()) return;
32775
32832
  stageZoomPlugin.zoomIn();
32776
- this.previousAction = params.previousAction;
32833
+ this.previousAction = params?.previousAction;
32777
32834
  this.cancelAction = cancelAction;
32778
32835
  this.cancelAction();
32779
32836
  }
32780
32837
  cleanup() {
32781
32838
  const stage = this.instance.getStage();
32782
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
32839
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
32783
32840
  stage.container().style.cursor = "default";
32784
32841
  }
32785
32842
  };
@@ -32810,21 +32867,17 @@ var WeaveFitToScreenToolAction = class extends WeaveAction {
32810
32867
  trigger(cancelAction, params) {
32811
32868
  const stageZoomPlugin = this.getStageZoomPlugin();
32812
32869
  if (stageZoomPlugin) stageZoomPlugin.fitToScreen({ overrideZoom: params?.overrideZoom ?? true });
32813
- this.previousAction = params.previousAction;
32870
+ this.previousAction = params?.previousAction;
32814
32871
  this.cancelAction = cancelAction;
32815
32872
  this.cancelAction();
32816
32873
  }
32817
32874
  cleanup() {
32818
32875
  const stage = this.instance.getStage();
32819
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
32876
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
32820
32877
  stage.container().style.cursor = "default";
32821
32878
  }
32822
32879
  };
32823
32880
 
32824
- //#endregion
32825
- //#region src/actions/fit-to-selection-tool/constants.ts
32826
- const FIT_TO_SELECTION_TOOL_ACTION_NAME = "fitToSelectionTool";
32827
-
32828
32881
  //#endregion
32829
32882
  //#region src/actions/fit-to-selection-tool/fit-to-selection-tool.ts
32830
32883
  var WeaveFitToSelectionToolAction = class extends WeaveAction {
@@ -32856,13 +32909,13 @@ var WeaveFitToSelectionToolAction = class extends WeaveAction {
32856
32909
  smartZoom: params?.smartZoom ?? false,
32857
32910
  overrideZoom: params?.overrideZoom ?? true
32858
32911
  });
32859
- this.previousAction = params.previousAction;
32912
+ this.previousAction = params?.previousAction;
32860
32913
  this.cancelAction = cancelAction;
32861
32914
  this.cancelAction();
32862
32915
  }
32863
32916
  cleanup() {
32864
32917
  const stage = this.instance.getStage();
32865
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
32918
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
32866
32919
  stage.container().style.cursor = "default";
32867
32920
  }
32868
32921
  };
@@ -34088,6 +34141,11 @@ const BRUSH_TOOL_DEFAULT_CONFIG = { interpolationSteps: 10 };
34088
34141
  var WeaveBrushToolAction = class extends WeaveAction {
34089
34142
  initialized = false;
34090
34143
  isSpacePressed = false;
34144
+ penActive = false;
34145
+ lastSmoothedPressure = .5;
34146
+ lastPointerPos = null;
34147
+ lastPointerTime = 0;
34148
+ predictedCount = 0;
34091
34149
  onPropsChange = void 0;
34092
34150
  onInit = void 0;
34093
34151
  constructor(params) {
@@ -34117,11 +34175,29 @@ var WeaveBrushToolAction = class extends WeaveAction {
34117
34175
  };
34118
34176
  }
34119
34177
  getEventPressure(e) {
34120
- if (e.evt.pointerType && e.evt.pointerType === "pen") return e.evt.pressure || .5;
34121
- return .5;
34178
+ const now$2 = performance.now();
34179
+ let velocity = 0;
34180
+ if (this.lastPointerPos && now$2 - this.lastPointerTime > 0) {
34181
+ const dx = e.evt.clientX - this.lastPointerPos.x;
34182
+ const dy = e.evt.clientY - this.lastPointerPos.y;
34183
+ velocity = Math.hypot(dx, dy) / (now$2 - this.lastPointerTime) * 1e3;
34184
+ }
34185
+ this.lastPointerPos = {
34186
+ x: e.evt.clientX,
34187
+ y: e.evt.clientY
34188
+ };
34189
+ this.lastPointerTime = now$2;
34190
+ const alpha = Math.min(Math.max(velocity / 1500, .15), .6);
34191
+ let raw;
34192
+ if (e.evt.pointerType === "pen") raw = e.evt.pressure || .5;
34193
+ else raw = .5;
34194
+ this.lastSmoothedPressure = alpha * raw + (1 - alpha) * this.lastSmoothedPressure;
34195
+ return Math.max(this.lastSmoothedPressure, .15);
34122
34196
  }
34123
34197
  setupEvents() {
34124
34198
  const stage = this.instance.getStage();
34199
+ this.prevTouchAction = stage.container().style.touchAction;
34200
+ stage.container().style.touchAction = "none";
34125
34201
  window.addEventListener("keyup", (e) => {
34126
34202
  if (e.code === "Space" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) this.isSpacePressed = false;
34127
34203
  }, { signal: this.instance.getEventsController()?.signal });
@@ -34146,7 +34222,9 @@ var WeaveBrushToolAction = class extends WeaveAction {
34146
34222
  if (this.state !== BRUSH_TOOL_STATE.IDLE) return;
34147
34223
  if (this.getZoomPlugin()?.isPinching()) return;
34148
34224
  if (this.isSpacePressed) return;
34149
- if (e.evt.button !== 0) return;
34225
+ if (e?.evt?.button !== 0) return;
34226
+ if (e.evt.pointerType === "touch" && this.penActive) return;
34227
+ if (e.evt.pointerType === "pen") this.penActive = true;
34150
34228
  const pointPressure = this.getEventPressure(e);
34151
34229
  this.handleStartStroke(pointPressure);
34152
34230
  e.evt.stopPropagation();
@@ -34157,12 +34235,27 @@ var WeaveBrushToolAction = class extends WeaveAction {
34157
34235
  this.setCursor();
34158
34236
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34159
34237
  if (this.getZoomPlugin()?.isPinching()) return;
34160
- const pointPressure = this.getEventPressure(e);
34161
- this.handleMovement(pointPressure);
34238
+ const coalescedEvents = e.evt.getCoalescedEvents ? e.evt.getCoalescedEvents() : [];
34239
+ if (coalescedEvents.length > 1) {
34240
+ for (const ce of coalescedEvents) {
34241
+ const pointPressure = ce.pointerType === "pen" && typeof ce.pressure === "number" ? ce.pressure : .5;
34242
+ this.handleMovement(pointPressure, void 0, false);
34243
+ }
34244
+ const predictedEvents = e.evt.getPredictedEvents ? e.evt.getPredictedEvents() : [];
34245
+ if (predictedEvents.length > 0) {
34246
+ const last = predictedEvents[predictedEvents.length - 1];
34247
+ const predPressure = last.pointerType === "pen" && typeof last.pressure === "number" ? last.pressure : .5;
34248
+ this.handleMovement(predPressure, last, true);
34249
+ }
34250
+ } else {
34251
+ const pointPressure = this.getEventPressure(e);
34252
+ this.handleMovement(pointPressure, void 0, false);
34253
+ }
34162
34254
  e.evt.stopPropagation();
34163
34255
  };
34164
34256
  stage.on("pointermove", handlePointerMove);
34165
34257
  const handlePointerUp = (e) => {
34258
+ this.penActive = false;
34166
34259
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34167
34260
  if (this.getZoomPlugin()?.isPinching()) return;
34168
34261
  this.handleEndStroke();
@@ -34199,6 +34292,10 @@ var WeaveBrushToolAction = class extends WeaveAction {
34199
34292
  };
34200
34293
  }
34201
34294
  handleStartStroke(pressure) {
34295
+ this.lastSmoothedPressure = .5;
34296
+ this.lastPointerPos = null;
34297
+ this.lastPointerTime = 0;
34298
+ this.predictedCount = 0;
34202
34299
  const { mousePoint, container, measureContainer } = this.instance.getMousePointer();
34203
34300
  this.clickPoint = mousePoint;
34204
34301
  this.container = container;
@@ -34227,17 +34324,25 @@ var WeaveBrushToolAction = class extends WeaveAction {
34227
34324
  }
34228
34325
  this.setState(BRUSH_TOOL_STATE.DEFINE_STROKE);
34229
34326
  }
34230
- handleMovement(pressure) {
34327
+ handleMovement(pressure, predictedEvent, isPredicted = false) {
34231
34328
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34329
+ const stage = this.instance.getStage();
34232
34330
  const tempStroke = this.instance.getStage().findOne(`#${this.strokeId}`);
34233
34331
  if (this.measureContainer && tempStroke) {
34332
+ if (predictedEvent) stage.setPointersPositions(predictedEvent);
34234
34333
  const { mousePoint } = this.instance.getMousePointerRelativeToContainer(this.measureContainer);
34235
34334
  const currentPoint = {
34236
34335
  x: mousePoint.x - tempStroke.x(),
34237
34336
  y: mousePoint.y - tempStroke.y(),
34238
34337
  pressure
34239
34338
  };
34240
- const newStrokeElements = [...tempStroke.getAttrs().strokeElements, currentPoint];
34339
+ let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34340
+ if (!isPredicted && this.predictedCount > 0) {
34341
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34342
+ this.predictedCount = 0;
34343
+ }
34344
+ newStrokeElements.push(currentPoint);
34345
+ if (isPredicted) this.predictedCount++;
34241
34346
  const box = this.getBoundingBox(newStrokeElements);
34242
34347
  tempStroke.setAttrs({
34243
34348
  width: box.width,
@@ -34257,17 +34362,22 @@ var WeaveBrushToolAction = class extends WeaveAction {
34257
34362
  if (nodeHandler) {
34258
34363
  const box = this.getBoundingBox(tempStroke.getAttrs().strokeElements);
34259
34364
  let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34365
+ if (this.predictedCount > 0) {
34366
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34367
+ this.predictedCount = 0;
34368
+ }
34260
34369
  newStrokeElements = newStrokeElements.map((point) => ({
34261
34370
  ...point,
34262
34371
  x: point.x - box.x,
34263
34372
  y: point.y - box.y
34264
34373
  }));
34374
+ const compressedPoints = simplify(newStrokeElements, 1, true);
34265
34375
  tempStroke.setAttrs({
34266
34376
  width: box.width,
34267
34377
  height: box.height,
34268
34378
  x: box.x,
34269
34379
  y: box.y,
34270
- strokeElements: newStrokeElements
34380
+ strokeElements: compressedPoints
34271
34381
  });
34272
34382
  const realNode = this.instance.getStage().findOne(`#${tempStroke.getAttrs().id}`);
34273
34383
  if (realNode) realNode.destroy();
@@ -34303,6 +34413,7 @@ var WeaveBrushToolAction = class extends WeaveAction {
34303
34413
  }
34304
34414
  cleanup() {
34305
34415
  const stage = this.instance.getStage();
34416
+ stage.container().style.touchAction = this.prevTouchAction;
34306
34417
  stage.container().style.cursor = "default";
34307
34418
  this.instance.emitEvent("onAddedBrush");
34308
34419
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -38003,13 +38114,13 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
38003
38114
  });
38004
38115
  stage.on("pointerdown", (e) => {
38005
38116
  const activeAction = this.instance.getActiveAction();
38006
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
38007
- if (e && (e.evt.button === 2 || e.evt.buttons === 4)) this.isMouseMiddleButtonPressed = true;
38117
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
38118
+ if (e && (e?.evt?.button === 2 || e?.evt?.buttons === 4)) this.isMouseMiddleButtonPressed = true;
38008
38119
  });
38009
38120
  stage.on("pointerup", (e) => {
38010
38121
  const activeAction = this.instance.getActiveAction();
38011
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
38012
- if (e && (e.evt.button === 1 || e.evt.buttons === 0)) this.isMouseMiddleButtonPressed = false;
38122
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
38123
+ if (e && (e?.evt?.button === 1 || e?.evt?.buttons === 0)) this.isMouseMiddleButtonPressed = false;
38013
38124
  });
38014
38125
  const handleMouseMove = () => {
38015
38126
  if (!this.enabled || !(this.isSpaceKeyPressed || this.isMouseMiddleButtonPressed || this.moveToolActive)) return;
@@ -38330,16 +38441,16 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
38330
38441
  let lastPos = null;
38331
38442
  stage.on("pointerdown", (e) => {
38332
38443
  this.pointers.set(e.evt.pointerId, {
38333
- x: e.evt.clientX,
38334
- y: e.evt.clientY
38444
+ x: e?.evt?.clientX ?? 0,
38445
+ y: e?.evt?.clientY ?? 0
38335
38446
  });
38336
38447
  if (this.pointers.size > 1) return;
38337
38448
  const activeAction = this.instance.getActiveAction();
38338
38449
  this.enableMove = false;
38339
38450
  if (activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
38340
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 1) this.isMouseLeftButtonPressed = true;
38341
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 4) this.isMouseMiddleButtonPressed = true;
38342
- const isTouchOrPen = ["touch", "pen"].includes(e.evt.pointerType);
38451
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 1) this.isMouseLeftButtonPressed = true;
38452
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 4) this.isMouseMiddleButtonPressed = true;
38453
+ const isTouchOrPen = ["touch", "pen"].includes(e?.evt?.pointerType);
38343
38454
  if (this.enabled && (this.isSpaceKeyPressed || this.moveToolActive && (this.isMouseLeftButtonPressed || isTouchOrPen) || this.isMouseMiddleButtonPressed)) this.enableMove = true;
38344
38455
  if (this.enableMove) {
38345
38456
  this.isDragging = true;
@@ -38348,7 +38459,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
38348
38459
  }
38349
38460
  });
38350
38461
  stage.on("pointercancel", (e) => {
38351
- this.pointers.delete(e.evt.pointerId);
38462
+ if (e?.evt?.pointerId) this.pointers.delete(e.evt.pointerId);
38352
38463
  lastPos = null;
38353
38464
  });
38354
38465
  const handleMouseMove = (e) => {