@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/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
  import { Stage } from "konva/lib/Stage";
9
10
 
@@ -18953,7 +18954,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18953
18954
  const nodesSelected = tr.nodes();
18954
18955
  if (nodesSelected.length === 1) {
18955
18956
  const node = nodesSelected[0];
18956
- stage.container().style.cursor = node.defineMousePointer?.() ?? "grab";
18957
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "grab";
18957
18958
  } else stage.container().style.cursor = "grab";
18958
18959
  });
18959
18960
  tr.on("mouseout", (e) => {
@@ -19016,8 +19017,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19016
19017
  let selectedNodes = [];
19017
19018
  tr.on("dragstart", (e) => {
19018
19019
  this.dragInProcess = true;
19020
+ if (!e?.evt) return;
19019
19021
  let isWheelMousePressed = false;
19020
- if (e.evt.button === 1) isWheelMousePressed = true;
19022
+ if (e.evt?.button === 1) isWheelMousePressed = true;
19021
19023
  const mainLayer = this.instance.getMainLayer();
19022
19024
  if (!mainLayer) return;
19023
19025
  initialPos = {
@@ -19058,7 +19060,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19058
19060
  y: e.target.y()
19059
19061
  };
19060
19062
  let isWheelMousePressed = false;
19061
- if (e.evt.button === 1) isWheelMousePressed = true;
19063
+ if (e.evt?.button === 1) isWheelMousePressed = true;
19062
19064
  e.cancelBubble = true;
19063
19065
  this.instance.getHooks().callHook("weave:onTransformerDragMove", {
19064
19066
  e,
@@ -19415,8 +19417,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19415
19417
  this.handledClickOrTap = false;
19416
19418
  this.pointers[e.evt.pointerId] = e.evt;
19417
19419
  if (e.evt.pointerType === "touch" && Object.keys(this.pointers).length > 1) return;
19418
- if (e.evt.pointerType === "mouse" && e.evt.button !== 0) return;
19419
- if (e.evt.pointerType === "pen" && e.evt.pressure <= .05) return;
19420
+ if (e.evt.pointerType === "mouse" && e.evt?.button !== 0) return;
19421
+ if (e.evt.pointerType === "pen" && e.evt?.pressure <= .05) return;
19420
19422
  if (!this.initialized) return;
19421
19423
  if (!this.active) return;
19422
19424
  if (stage.mode() !== WEAVE_STAGE_DEFAULT_MODE) return;
@@ -19469,8 +19471,9 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19469
19471
  this.panLoopId = requestAnimationFrame(() => this.panLoop());
19470
19472
  });
19471
19473
  const handleMouseMove = (e) => {
19474
+ if (!e?.evt) return;
19472
19475
  const moved = this.checkMoved(e);
19473
- if (e.evt.buttons === 0) return;
19476
+ if (e.evt?.buttons === 0) return;
19474
19477
  if (e.evt.pointerType === "touch" && Object.keys(this.pointers).length > 1) return;
19475
19478
  if (!this.initialized) return;
19476
19479
  if (!this.active) return;
@@ -19636,7 +19639,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19636
19639
  this.hideHoverState();
19637
19640
  const selectedGroup = getTargetedNode(this.instance);
19638
19641
  if (!this.initialized) return;
19639
- if (e.evt.pointerType === "mouse" && e.evt.button && e.evt.button !== 0) return;
19642
+ if (e.evt.pointerType === "mouse" && e.evt?.button && e.evt?.button !== 0) return;
19640
19643
  let areNodesSelected = false;
19641
19644
  let nodeTargeted = selectedGroup && !(selectedGroup.getAttrs().active ?? false) ? selectedGroup : e.target;
19642
19645
  if (e.target === this.instance.getStage()) {
@@ -19699,7 +19702,7 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19699
19702
  if (areNodesSelected) {
19700
19703
  stage.container().tabIndex = 1;
19701
19704
  stage.container().focus();
19702
- stage.container().style.cursor = nodeTargeted.defineMousePointer?.() ?? "grab";
19705
+ stage.container().style.cursor = (typeof nodeTargeted?.defineMousePointer === "function" ? nodeTargeted.defineMousePointer() : null) ?? "grab";
19703
19706
  }
19704
19707
  this.triggerSelectedNodesEvent();
19705
19708
  }
@@ -19859,6 +19862,10 @@ const WEAVE_COPY_PASTE_CONFIG_DEFAULT = {
19859
19862
  }
19860
19863
  };
19861
19864
 
19865
+ //#endregion
19866
+ //#region src/actions/fit-to-selection-tool/constants.ts
19867
+ const FIT_TO_SELECTION_TOOL_ACTION_NAME = "fitToSelectionTool";
19868
+
19862
19869
  //#endregion
19863
19870
  //#region src/plugins/copy-paste-nodes/copy-paste-nodes.ts
19864
19871
  var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
@@ -20070,8 +20077,8 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
20070
20077
  }
20071
20078
  const nodesSelectionPlugin = this.getNodesSelectionPlugin();
20072
20079
  nodesSelectionPlugin?.setSelectedNodes(realNodes);
20073
- this.instance?.triggerAction("fitToSelectionTool", {
20074
- previousAction: "selectionTool",
20080
+ this.instance?.triggerAction(FIT_TO_SELECTION_TOOL_ACTION_NAME, {
20081
+ previousAction: SELECTION_TOOL_ACTION_NAME,
20075
20082
  smartZoom: true
20076
20083
  });
20077
20084
  this.instance.emitEvent("onPaste", {
@@ -20346,6 +20353,33 @@ const augmentKonvaNodeClass = (config) => {
20346
20353
  Konva.Node.prototype.closeCrop = function() {};
20347
20354
  Konva.Node.prototype.resetCrop = function() {};
20348
20355
  Konva.Node.prototype.dblClick = function() {};
20356
+ Konva.Node.prototype.allowedAnchors = function() {
20357
+ return [];
20358
+ };
20359
+ Konva.Node.prototype.isSelectable = function() {
20360
+ return true;
20361
+ };
20362
+ Konva.Node.prototype.handleMouseover = function() {};
20363
+ Konva.Node.prototype.handleMouseout = function() {};
20364
+ Konva.Node.prototype.handleSelectNode = function() {};
20365
+ Konva.Node.prototype.handleDeselectNode = function() {};
20366
+ Konva.Node.prototype.defineMousePointer = function() {
20367
+ return "default";
20368
+ };
20369
+ Konva.Node.prototype.canBeHovered = function() {
20370
+ return false;
20371
+ };
20372
+ Konva.Node.prototype.canDrag = function() {
20373
+ return false;
20374
+ };
20375
+ Konva.Node.prototype.canMoveToContainer = function() {
20376
+ return false;
20377
+ };
20378
+ Konva.Node.prototype.getNodeAnchors = function() {
20379
+ return [];
20380
+ };
20381
+ Konva.Node.prototype.lockMutex = function() {};
20382
+ Konva.Node.prototype.releaseMutex = function() {};
20349
20383
  };
20350
20384
  var WeaveNode = class {
20351
20385
  async register(instance) {
@@ -20630,10 +20664,11 @@ var WeaveNode = class {
20630
20664
  node.off("dragstart");
20631
20665
  node.on("dragstart", (e) => {
20632
20666
  const nodeTarget = e.target;
20667
+ if (!e.evt) return;
20633
20668
  let isWheelMousePressed = false;
20634
- if (e.evt.button === 1) isWheelMousePressed = true;
20669
+ if (e.evt?.button === 1) isWheelMousePressed = true;
20635
20670
  this.getNodesSelectionFeedbackPlugin()?.hideSelectionHalo(nodeTarget);
20636
- const canMove = nodeTarget?.canDrag() ?? false;
20671
+ const canMove = typeof nodeTarget?.canDrag === "function" ? nodeTarget.canDrag() : false;
20637
20672
  if (!canMove) {
20638
20673
  nodeTarget.stopDrag();
20639
20674
  return;
@@ -20685,7 +20720,7 @@ var WeaveNode = class {
20685
20720
  nodesSelectionPlugin?.setSelectedNodes([]);
20686
20721
  requestAnimationFrame(() => {
20687
20722
  nodesSelectionPlugin?.setSelectedNodes(this.instance.getCloningManager().getClones());
20688
- clone?.startDrag(e.evt);
20723
+ if (clone?.getStage()) clone.startDrag(e.evt);
20689
20724
  });
20690
20725
  }
20691
20726
  if (this.getNodesSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.setMutexLock({
@@ -20696,7 +20731,7 @@ var WeaveNode = class {
20696
20731
  const handleDragMove = (e) => {
20697
20732
  const nodeTarget = e.target;
20698
20733
  let isWheelMousePressed = false;
20699
- if (e.evt.button === 1) isWheelMousePressed = true;
20734
+ if (e.evt?.button === 1) isWheelMousePressed = true;
20700
20735
  e.cancelBubble = true;
20701
20736
  if (e.evt?.buttons === 0) {
20702
20737
  nodeTarget.stopDrag();
@@ -20884,12 +20919,12 @@ var WeaveNode = class {
20884
20919
  }
20885
20920
  if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20886
20921
  showHover = true;
20887
- stage.container().style.cursor = realNode?.defineMousePointer() ?? "pointer";
20922
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "pointer";
20888
20923
  cancelBubble = true;
20889
20924
  }
20890
20925
  if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20891
20926
  showHover = true;
20892
- stage.container().style.cursor = realNode?.defineMousePointer() ?? "grab";
20927
+ stage.container().style.cursor = (typeof node?.defineMousePointer === "function" ? node.defineMousePointer() : null) ?? "grab";
20893
20928
  cancelBubble = true;
20894
20929
  }
20895
20930
  if (!isTargetable) cancelBubble = true;
@@ -22164,7 +22199,7 @@ var WeaveRegisterManager = class {
22164
22199
 
22165
22200
  //#endregion
22166
22201
  //#region package.json
22167
- var version = "4.0.0";
22202
+ var version = "4.1.0";
22168
22203
 
22169
22204
  //#endregion
22170
22205
  //#region src/managers/setup.ts
@@ -24305,6 +24340,7 @@ function loadImageSource(image, options) {
24305
24340
  }
24306
24341
  async function downscaleImageFile(file, ratio) {
24307
24342
  const bitmap = await createImageBitmap(file);
24343
+ if (bitmap.width === 0) throw new Error("Invalid image", { cause: "InvalidImage" });
24308
24344
  const width = Math.round(bitmap.width * ratio);
24309
24345
  const height = Math.round(bitmap.height * ratio);
24310
24346
  const canvas = document.createElement("canvas");
@@ -24321,13 +24357,19 @@ function getImageSizeFromFile(file) {
24321
24357
  const img = new Image();
24322
24358
  const url = URL.createObjectURL(file);
24323
24359
  img.onload = () => {
24360
+ if (img.naturalWidth === 0) {
24361
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24362
+ return;
24363
+ }
24324
24364
  resolve({
24325
24365
  width: img.naturalWidth,
24326
24366
  height: img.naturalHeight
24327
24367
  });
24328
24368
  URL.revokeObjectURL(url);
24329
24369
  };
24330
- img.onerror = reject;
24370
+ img.onerror = () => {
24371
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24372
+ };
24331
24373
  img.src = url;
24332
24374
  });
24333
24375
  }
@@ -24351,6 +24393,10 @@ const downscaleImageFromURL = (url, options) => {
24351
24393
  const img = new Image();
24352
24394
  img.crossOrigin = crossOrigin;
24353
24395
  img.onload = () => {
24396
+ if (img.naturalWidth === 0) {
24397
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24398
+ return;
24399
+ }
24354
24400
  const ratio = Math.min(maxWidth / img.width, maxHeight / img.height, 1);
24355
24401
  const width = Math.round(img.width * ratio);
24356
24402
  const height = Math.round(img.height * ratio);
@@ -24361,7 +24407,9 @@ const downscaleImageFromURL = (url, options) => {
24361
24407
  ctx.drawImage(img, 0, 0, width, height);
24362
24408
  resolve(canvas.toDataURL(type));
24363
24409
  };
24364
- img.onerror = reject;
24410
+ img.onerror = () => {
24411
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24412
+ };
24365
24413
  img.src = url;
24366
24414
  });
24367
24415
  };
@@ -27241,15 +27289,24 @@ var WeaveImageNode = class extends WeaveNode {
27241
27289
  const imageURLToLoad = imageURL ?? "http://localhost/false-image";
27242
27290
  this.imageFallback[imageId] = Konva.Util.createImageElement();
27243
27291
  this.imageFallback[imageId].crossOrigin = this.config.crossOrigin;
27244
- this.imageFallback[imageId].onerror = (error) => {
27292
+ this.imageFallback[imageId].onerror = () => {
27245
27293
  this.imageState[imageId] = {
27246
27294
  status: "error-fallback",
27247
27295
  loaded: false,
27248
27296
  error: true
27249
27297
  };
27250
- onError(error);
27298
+ onError(new Error(`Failed to load fallback image from provided URL`, { cause: "ErrorLoadingFallbackImage" }));
27251
27299
  };
27252
27300
  this.imageFallback[imageId].onload = async () => {
27301
+ if (this.imageFallback[imageId].width === 0) {
27302
+ this.imageState[imageId] = {
27303
+ status: "error-fallback",
27304
+ loaded: false,
27305
+ error: true
27306
+ };
27307
+ onError(new Error(`Invalid fallback image provided`, { cause: "InvalidFallbackImage" }));
27308
+ return;
27309
+ }
27253
27310
  this.imageState[imageId] = {
27254
27311
  status: "loading",
27255
27312
  loaded: true,
@@ -27276,15 +27333,19 @@ var WeaveImageNode = class extends WeaveNode {
27276
27333
  }
27277
27334
  this.imageSource[imageId] = Konva.Util.createImageElement();
27278
27335
  this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
27279
- this.imageSource[imageId].onerror = (error) => {
27336
+ this.imageSource[imageId].onerror = () => {
27280
27337
  if (!loadingTryout) {
27281
27338
  const stage = this.instance.getStage();
27282
27339
  const image = stage.findOne(`#${imageId}`);
27283
27340
  if (image) this.setErrorState(imageId, image);
27284
27341
  }
27285
- onError(error);
27342
+ onError(new Error(`Failed to load image from provided URL`, { cause: "ErrorLoadingImage" }));
27286
27343
  };
27287
27344
  this.imageSource[imageId].onload = async () => {
27345
+ if (this.imageSource[imageId].width === 0) {
27346
+ onError(new Error(`Invalid image provided`, { cause: "InvalidImage" }));
27347
+ return;
27348
+ }
27288
27349
  const stage = this.instance.getStage();
27289
27350
  if (!this.instance.isServerSide()) stage.container().style.cursor = "pointer";
27290
27351
  this.imageState[imageId] = {
@@ -27376,14 +27437,16 @@ var WeaveImageNode = class extends WeaveNode {
27376
27437
  }
27377
27438
  },
27378
27439
  onError: (error) => {
27379
- if (!this.config.useFallbackImage) {
27440
+ let isInvalidImage = false;
27441
+ if (error.cause === "InvalidImage") isInvalidImage = true;
27442
+ if (!this.config.useFallbackImage && !isInvalidImage) {
27380
27443
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27381
27444
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27382
27445
  this.loadImageTryout(id);
27383
27446
  return;
27384
27447
  } else this.setErrorState(id, image);
27385
27448
  }
27386
- if (loadTryout) {
27449
+ if (loadTryout && !isInvalidImage) {
27387
27450
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27388
27451
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27389
27452
  this.loadImageTryout(id);
@@ -27396,12 +27459,7 @@ var WeaveImageNode = class extends WeaveNode {
27396
27459
  return;
27397
27460
  }
27398
27461
  this.setErrorState(id, image);
27399
- image.setAttrs({ image: void 0 });
27400
- console.error("Error loading image", error);
27401
27462
  this.resolveAsyncElement(id);
27402
- imagePlaceholder?.setAttrs({ visible: true });
27403
- internalImage?.setAttrs({ visible: false });
27404
- this.cacheNode(image);
27405
27463
  }
27406
27464
  }, loadTryout);
27407
27465
  }
@@ -28396,8 +28454,8 @@ var WeaveStrokeNode = class extends WeaveNode {
28396
28454
  const segLen = Math.hypot(dx, dy) || 1;
28397
28455
  const nx = -dy / segLen;
28398
28456
  const ny = dx / segLen;
28399
- const w0 = baseW * p0.pressure / 2;
28400
- const w1 = baseW * p1.pressure / 2;
28457
+ const w0 = Math.max(baseW * p0.pressure / 2, .5);
28458
+ const w1 = Math.max(baseW * p1.pressure / 2, .5);
28401
28459
  let traveled = 0;
28402
28460
  while (traveled < segLen) {
28403
28461
  const step = Math.min(dashRemaining, segLen - traveled);
@@ -30087,8 +30145,7 @@ var WeaveVideoNode = class extends WeaveNode {
30087
30145
  this.videoPlaceholder[id] = Konva.Util.createImageElement();
30088
30146
  this.videoPlaceholder[id].crossOrigin = this.config.crossOrigin;
30089
30147
  this.videoPlaceholder[id].src = realVideoPlaceholderURL;
30090
- this.videoPlaceholder[id].onerror = (error) => {
30091
- console.error("Error loading video placeholder", realVideoPlaceholderURL, error);
30148
+ this.videoPlaceholder[id].onerror = () => {
30092
30149
  this.resolveAsyncElement(id);
30093
30150
  };
30094
30151
  this.videoPlaceholder[id].onload = () => {
@@ -33127,13 +33184,13 @@ var WeaveZoomOutToolAction = class extends WeaveAction {
33127
33184
  const stageZoomPlugin = this.getStageZoomPlugin();
33128
33185
  if (!stageZoomPlugin.canZoomOut()) return;
33129
33186
  stageZoomPlugin.zoomOut();
33130
- this.previousAction = params.previousAction;
33187
+ this.previousAction = params?.previousAction;
33131
33188
  this.cancelAction = cancelAction;
33132
33189
  this.cancelAction();
33133
33190
  }
33134
33191
  cleanup() {
33135
33192
  const stage = this.instance.getStage();
33136
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33193
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33137
33194
  stage.container().style.cursor = "default";
33138
33195
  }
33139
33196
  };
@@ -33165,13 +33222,13 @@ var WeaveZoomInToolAction = class extends WeaveAction {
33165
33222
  const stageZoomPlugin = this.getStageZoomPlugin();
33166
33223
  if (!stageZoomPlugin.canZoomIn()) return;
33167
33224
  stageZoomPlugin.zoomIn();
33168
- this.previousAction = params.previousAction;
33225
+ this.previousAction = params?.previousAction;
33169
33226
  this.cancelAction = cancelAction;
33170
33227
  this.cancelAction();
33171
33228
  }
33172
33229
  cleanup() {
33173
33230
  const stage = this.instance.getStage();
33174
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33231
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33175
33232
  stage.container().style.cursor = "default";
33176
33233
  }
33177
33234
  };
@@ -33202,21 +33259,17 @@ var WeaveFitToScreenToolAction = class extends WeaveAction {
33202
33259
  trigger(cancelAction, params) {
33203
33260
  const stageZoomPlugin = this.getStageZoomPlugin();
33204
33261
  if (stageZoomPlugin) stageZoomPlugin.fitToScreen({ overrideZoom: params?.overrideZoom ?? true });
33205
- this.previousAction = params.previousAction;
33262
+ this.previousAction = params?.previousAction;
33206
33263
  this.cancelAction = cancelAction;
33207
33264
  this.cancelAction();
33208
33265
  }
33209
33266
  cleanup() {
33210
33267
  const stage = this.instance.getStage();
33211
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33268
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33212
33269
  stage.container().style.cursor = "default";
33213
33270
  }
33214
33271
  };
33215
33272
 
33216
- //#endregion
33217
- //#region src/actions/fit-to-selection-tool/constants.ts
33218
- const FIT_TO_SELECTION_TOOL_ACTION_NAME = "fitToSelectionTool";
33219
-
33220
33273
  //#endregion
33221
33274
  //#region src/actions/fit-to-selection-tool/fit-to-selection-tool.ts
33222
33275
  var WeaveFitToSelectionToolAction = class extends WeaveAction {
@@ -33248,13 +33301,13 @@ var WeaveFitToSelectionToolAction = class extends WeaveAction {
33248
33301
  smartZoom: params?.smartZoom ?? false,
33249
33302
  overrideZoom: params?.overrideZoom ?? true
33250
33303
  });
33251
- this.previousAction = params.previousAction;
33304
+ this.previousAction = params?.previousAction;
33252
33305
  this.cancelAction = cancelAction;
33253
33306
  this.cancelAction();
33254
33307
  }
33255
33308
  cleanup() {
33256
33309
  const stage = this.instance.getStage();
33257
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33310
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33258
33311
  stage.container().style.cursor = "default";
33259
33312
  }
33260
33313
  };
@@ -34480,6 +34533,11 @@ const BRUSH_TOOL_DEFAULT_CONFIG = { interpolationSteps: 10 };
34480
34533
  var WeaveBrushToolAction = class extends WeaveAction {
34481
34534
  initialized = false;
34482
34535
  isSpacePressed = false;
34536
+ penActive = false;
34537
+ lastSmoothedPressure = .5;
34538
+ lastPointerPos = null;
34539
+ lastPointerTime = 0;
34540
+ predictedCount = 0;
34483
34541
  onPropsChange = void 0;
34484
34542
  onInit = void 0;
34485
34543
  constructor(params) {
@@ -34509,11 +34567,29 @@ var WeaveBrushToolAction = class extends WeaveAction {
34509
34567
  };
34510
34568
  }
34511
34569
  getEventPressure(e) {
34512
- if (e.evt.pointerType && e.evt.pointerType === "pen") return e.evt.pressure || .5;
34513
- return .5;
34570
+ const now$2 = performance.now();
34571
+ let velocity = 0;
34572
+ if (this.lastPointerPos && now$2 - this.lastPointerTime > 0) {
34573
+ const dx = e.evt.clientX - this.lastPointerPos.x;
34574
+ const dy = e.evt.clientY - this.lastPointerPos.y;
34575
+ velocity = Math.hypot(dx, dy) / (now$2 - this.lastPointerTime) * 1e3;
34576
+ }
34577
+ this.lastPointerPos = {
34578
+ x: e.evt.clientX,
34579
+ y: e.evt.clientY
34580
+ };
34581
+ this.lastPointerTime = now$2;
34582
+ const alpha = Math.min(Math.max(velocity / 1500, .15), .6);
34583
+ let raw;
34584
+ if (e.evt.pointerType === "pen") raw = e.evt.pressure || .5;
34585
+ else raw = .5;
34586
+ this.lastSmoothedPressure = alpha * raw + (1 - alpha) * this.lastSmoothedPressure;
34587
+ return Math.max(this.lastSmoothedPressure, .15);
34514
34588
  }
34515
34589
  setupEvents() {
34516
34590
  const stage = this.instance.getStage();
34591
+ this.prevTouchAction = stage.container().style.touchAction;
34592
+ stage.container().style.touchAction = "none";
34517
34593
  window.addEventListener("keyup", (e) => {
34518
34594
  if (e.code === "Space" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) this.isSpacePressed = false;
34519
34595
  }, { signal: this.instance.getEventsController()?.signal });
@@ -34538,7 +34614,9 @@ var WeaveBrushToolAction = class extends WeaveAction {
34538
34614
  if (this.state !== BRUSH_TOOL_STATE.IDLE) return;
34539
34615
  if (this.getZoomPlugin()?.isPinching()) return;
34540
34616
  if (this.isSpacePressed) return;
34541
- if (e.evt.button !== 0) return;
34617
+ if (e?.evt?.button !== 0) return;
34618
+ if (e.evt.pointerType === "touch" && this.penActive) return;
34619
+ if (e.evt.pointerType === "pen") this.penActive = true;
34542
34620
  const pointPressure = this.getEventPressure(e);
34543
34621
  this.handleStartStroke(pointPressure);
34544
34622
  e.evt.stopPropagation();
@@ -34549,12 +34627,27 @@ var WeaveBrushToolAction = class extends WeaveAction {
34549
34627
  this.setCursor();
34550
34628
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34551
34629
  if (this.getZoomPlugin()?.isPinching()) return;
34552
- const pointPressure = this.getEventPressure(e);
34553
- this.handleMovement(pointPressure);
34630
+ const coalescedEvents = e.evt.getCoalescedEvents ? e.evt.getCoalescedEvents() : [];
34631
+ if (coalescedEvents.length > 1) {
34632
+ for (const ce of coalescedEvents) {
34633
+ const pointPressure = ce.pointerType === "pen" && typeof ce.pressure === "number" ? ce.pressure : .5;
34634
+ this.handleMovement(pointPressure, void 0, false);
34635
+ }
34636
+ const predictedEvents = e.evt.getPredictedEvents ? e.evt.getPredictedEvents() : [];
34637
+ if (predictedEvents.length > 0) {
34638
+ const last = predictedEvents[predictedEvents.length - 1];
34639
+ const predPressure = last.pointerType === "pen" && typeof last.pressure === "number" ? last.pressure : .5;
34640
+ this.handleMovement(predPressure, last, true);
34641
+ }
34642
+ } else {
34643
+ const pointPressure = this.getEventPressure(e);
34644
+ this.handleMovement(pointPressure, void 0, false);
34645
+ }
34554
34646
  e.evt.stopPropagation();
34555
34647
  };
34556
34648
  stage.on("pointermove", handlePointerMove);
34557
34649
  const handlePointerUp = (e) => {
34650
+ this.penActive = false;
34558
34651
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34559
34652
  if (this.getZoomPlugin()?.isPinching()) return;
34560
34653
  this.handleEndStroke();
@@ -34591,6 +34684,10 @@ var WeaveBrushToolAction = class extends WeaveAction {
34591
34684
  };
34592
34685
  }
34593
34686
  handleStartStroke(pressure) {
34687
+ this.lastSmoothedPressure = .5;
34688
+ this.lastPointerPos = null;
34689
+ this.lastPointerTime = 0;
34690
+ this.predictedCount = 0;
34594
34691
  const { mousePoint, container, measureContainer } = this.instance.getMousePointer();
34595
34692
  this.clickPoint = mousePoint;
34596
34693
  this.container = container;
@@ -34619,17 +34716,25 @@ var WeaveBrushToolAction = class extends WeaveAction {
34619
34716
  }
34620
34717
  this.setState(BRUSH_TOOL_STATE.DEFINE_STROKE);
34621
34718
  }
34622
- handleMovement(pressure) {
34719
+ handleMovement(pressure, predictedEvent, isPredicted = false) {
34623
34720
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34721
+ const stage = this.instance.getStage();
34624
34722
  const tempStroke = this.instance.getStage().findOne(`#${this.strokeId}`);
34625
34723
  if (this.measureContainer && tempStroke) {
34724
+ if (predictedEvent) stage.setPointersPositions(predictedEvent);
34626
34725
  const { mousePoint } = this.instance.getMousePointerRelativeToContainer(this.measureContainer);
34627
34726
  const currentPoint = {
34628
34727
  x: mousePoint.x - tempStroke.x(),
34629
34728
  y: mousePoint.y - tempStroke.y(),
34630
34729
  pressure
34631
34730
  };
34632
- const newStrokeElements = [...tempStroke.getAttrs().strokeElements, currentPoint];
34731
+ let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34732
+ if (!isPredicted && this.predictedCount > 0) {
34733
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34734
+ this.predictedCount = 0;
34735
+ }
34736
+ newStrokeElements.push(currentPoint);
34737
+ if (isPredicted) this.predictedCount++;
34633
34738
  const box = this.getBoundingBox(newStrokeElements);
34634
34739
  tempStroke.setAttrs({
34635
34740
  width: box.width,
@@ -34649,17 +34754,22 @@ var WeaveBrushToolAction = class extends WeaveAction {
34649
34754
  if (nodeHandler) {
34650
34755
  const box = this.getBoundingBox(tempStroke.getAttrs().strokeElements);
34651
34756
  let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34757
+ if (this.predictedCount > 0) {
34758
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34759
+ this.predictedCount = 0;
34760
+ }
34652
34761
  newStrokeElements = newStrokeElements.map((point) => ({
34653
34762
  ...point,
34654
34763
  x: point.x - box.x,
34655
34764
  y: point.y - box.y
34656
34765
  }));
34766
+ const compressedPoints = simplify(newStrokeElements, 1, true);
34657
34767
  tempStroke.setAttrs({
34658
34768
  width: box.width,
34659
34769
  height: box.height,
34660
34770
  x: box.x,
34661
34771
  y: box.y,
34662
- strokeElements: newStrokeElements
34772
+ strokeElements: compressedPoints
34663
34773
  });
34664
34774
  const realNode = this.instance.getStage().findOne(`#${tempStroke.getAttrs().id}`);
34665
34775
  if (realNode) realNode.destroy();
@@ -34695,6 +34805,7 @@ var WeaveBrushToolAction = class extends WeaveAction {
34695
34805
  }
34696
34806
  cleanup() {
34697
34807
  const stage = this.instance.getStage();
34808
+ stage.container().style.touchAction = this.prevTouchAction;
34698
34809
  stage.container().style.cursor = "default";
34699
34810
  this.instance.emitEvent("onAddedBrush");
34700
34811
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -39147,13 +39258,13 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
39147
39258
  });
39148
39259
  stage.on("pointerdown", (e) => {
39149
39260
  const activeAction = this.instance.getActiveAction();
39150
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39151
- if (e && (e.evt.button === 2 || e.evt.buttons === 4)) this.isMouseMiddleButtonPressed = true;
39261
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39262
+ if (e && (e?.evt?.button === 2 || e?.evt?.buttons === 4)) this.isMouseMiddleButtonPressed = true;
39152
39263
  });
39153
39264
  stage.on("pointerup", (e) => {
39154
39265
  const activeAction = this.instance.getActiveAction();
39155
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
39156
- if (e && (e.evt.button === 1 || e.evt.buttons === 0)) this.isMouseMiddleButtonPressed = false;
39266
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
39267
+ if (e && (e?.evt?.button === 1 || e?.evt?.buttons === 0)) this.isMouseMiddleButtonPressed = false;
39157
39268
  });
39158
39269
  const handleMouseMove = () => {
39159
39270
  if (!this.enabled || !(this.isSpaceKeyPressed || this.isMouseMiddleButtonPressed || this.moveToolActive)) return;
@@ -39470,16 +39581,16 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
39470
39581
  let lastPos = null;
39471
39582
  stage.on("pointerdown", (e) => {
39472
39583
  this.pointers.set(e.evt.pointerId, {
39473
- x: e.evt.clientX,
39474
- y: e.evt.clientY
39584
+ x: e?.evt?.clientX ?? 0,
39585
+ y: e?.evt?.clientY ?? 0
39475
39586
  });
39476
39587
  if (this.pointers.size > 1) return;
39477
39588
  const activeAction = this.instance.getActiveAction();
39478
39589
  this.enableMove = false;
39479
39590
  if (activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39480
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 1) this.isMouseLeftButtonPressed = true;
39481
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 4) this.isMouseMiddleButtonPressed = true;
39482
- const isTouchOrPen = ["touch", "pen"].includes(e.evt.pointerType);
39591
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 1) this.isMouseLeftButtonPressed = true;
39592
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 4) this.isMouseMiddleButtonPressed = true;
39593
+ const isTouchOrPen = ["touch", "pen"].includes(e?.evt?.pointerType);
39483
39594
  if (this.enabled && (this.isSpaceKeyPressed || this.moveToolActive && (this.isMouseLeftButtonPressed || isTouchOrPen) || this.isMouseMiddleButtonPressed)) this.enableMove = true;
39484
39595
  if (this.enableMove) {
39485
39596
  this.isDragging = true;
@@ -39488,7 +39599,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
39488
39599
  }
39489
39600
  });
39490
39601
  stage.on("pointercancel", (e) => {
39491
- this.pointers.delete(e.evt.pointerId);
39602
+ if (e?.evt?.pointerId) this.pointers.delete(e.evt.pointerId);
39492
39603
  lastPos = null;
39493
39604
  });
39494
39605
  const handleMouseMove = (e) => {