@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.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 "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;
@@ -22153,7 +22188,7 @@ var WeaveRegisterManager = class {
22153
22188
 
22154
22189
  //#endregion
22155
22190
  //#region package.json
22156
- var version = "4.0.0";
22191
+ var version = "4.1.0";
22157
22192
 
22158
22193
  //#endregion
22159
22194
  //#region src/managers/setup.ts
@@ -24294,6 +24329,7 @@ function loadImageSource(image, options) {
24294
24329
  }
24295
24330
  async function downscaleImageFile(file, ratio) {
24296
24331
  const bitmap = await createImageBitmap(file);
24332
+ if (bitmap.width === 0) throw new Error("Invalid image", { cause: "InvalidImage" });
24297
24333
  const width = Math.round(bitmap.width * ratio);
24298
24334
  const height = Math.round(bitmap.height * ratio);
24299
24335
  const canvas = document.createElement("canvas");
@@ -24310,13 +24346,19 @@ function getImageSizeFromFile(file) {
24310
24346
  const img = new Image();
24311
24347
  const url = URL.createObjectURL(file);
24312
24348
  img.onload = () => {
24349
+ if (img.naturalWidth === 0) {
24350
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24351
+ return;
24352
+ }
24313
24353
  resolve({
24314
24354
  width: img.naturalWidth,
24315
24355
  height: img.naturalHeight
24316
24356
  });
24317
24357
  URL.revokeObjectURL(url);
24318
24358
  };
24319
- img.onerror = reject;
24359
+ img.onerror = () => {
24360
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24361
+ };
24320
24362
  img.src = url;
24321
24363
  });
24322
24364
  }
@@ -24340,6 +24382,10 @@ const downscaleImageFromURL = (url, options) => {
24340
24382
  const img = new Image();
24341
24383
  img.crossOrigin = crossOrigin;
24342
24384
  img.onload = () => {
24385
+ if (img.naturalWidth === 0) {
24386
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24387
+ return;
24388
+ }
24343
24389
  const ratio = Math.min(maxWidth / img.width, maxHeight / img.height, 1);
24344
24390
  const width = Math.round(img.width * ratio);
24345
24391
  const height = Math.round(img.height * ratio);
@@ -24350,7 +24396,9 @@ const downscaleImageFromURL = (url, options) => {
24350
24396
  ctx.drawImage(img, 0, 0, width, height);
24351
24397
  resolve(canvas.toDataURL(type));
24352
24398
  };
24353
- img.onerror = reject;
24399
+ img.onerror = () => {
24400
+ reject(new Error("Invalid image", { cause: "InvalidImage" }));
24401
+ };
24354
24402
  img.src = url;
24355
24403
  });
24356
24404
  };
@@ -27230,15 +27278,24 @@ var WeaveImageNode = class extends WeaveNode {
27230
27278
  const imageURLToLoad = imageURL ?? "http://localhost/false-image";
27231
27279
  this.imageFallback[imageId] = Konva.Util.createImageElement();
27232
27280
  this.imageFallback[imageId].crossOrigin = this.config.crossOrigin;
27233
- this.imageFallback[imageId].onerror = (error) => {
27281
+ this.imageFallback[imageId].onerror = () => {
27234
27282
  this.imageState[imageId] = {
27235
27283
  status: "error-fallback",
27236
27284
  loaded: false,
27237
27285
  error: true
27238
27286
  };
27239
- onError(error);
27287
+ onError(new Error(`Failed to load fallback image from provided URL`, { cause: "ErrorLoadingFallbackImage" }));
27240
27288
  };
27241
27289
  this.imageFallback[imageId].onload = async () => {
27290
+ if (this.imageFallback[imageId].width === 0) {
27291
+ this.imageState[imageId] = {
27292
+ status: "error-fallback",
27293
+ loaded: false,
27294
+ error: true
27295
+ };
27296
+ onError(new Error(`Invalid fallback image provided`, { cause: "InvalidFallbackImage" }));
27297
+ return;
27298
+ }
27242
27299
  this.imageState[imageId] = {
27243
27300
  status: "loading",
27244
27301
  loaded: true,
@@ -27265,15 +27322,19 @@ var WeaveImageNode = class extends WeaveNode {
27265
27322
  }
27266
27323
  this.imageSource[imageId] = Konva.Util.createImageElement();
27267
27324
  this.imageSource[imageId].crossOrigin = this.config.crossOrigin;
27268
- this.imageSource[imageId].onerror = (error) => {
27325
+ this.imageSource[imageId].onerror = () => {
27269
27326
  if (!loadingTryout) {
27270
27327
  const stage = this.instance.getStage();
27271
27328
  const image = stage.findOne(`#${imageId}`);
27272
27329
  if (image) this.setErrorState(imageId, image);
27273
27330
  }
27274
- onError(error);
27331
+ onError(new Error(`Failed to load image from provided URL`, { cause: "ErrorLoadingImage" }));
27275
27332
  };
27276
27333
  this.imageSource[imageId].onload = async () => {
27334
+ if (this.imageSource[imageId].width === 0) {
27335
+ onError(new Error(`Invalid image provided`, { cause: "InvalidImage" }));
27336
+ return;
27337
+ }
27277
27338
  const stage = this.instance.getStage();
27278
27339
  if (!this.instance.isServerSide()) stage.container().style.cursor = "pointer";
27279
27340
  this.imageState[imageId] = {
@@ -27365,14 +27426,16 @@ var WeaveImageNode = class extends WeaveNode {
27365
27426
  }
27366
27427
  },
27367
27428
  onError: (error) => {
27368
- if (!this.config.useFallbackImage) {
27429
+ let isInvalidImage = false;
27430
+ if (error.cause === "InvalidImage") isInvalidImage = true;
27431
+ if (!this.config.useFallbackImage && !isInvalidImage) {
27369
27432
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27370
27433
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27371
27434
  this.loadImageTryout(id);
27372
27435
  return;
27373
27436
  } else this.setErrorState(id, image);
27374
27437
  }
27375
- if (loadTryout) {
27438
+ if (loadTryout && !isInvalidImage) {
27376
27439
  const tryoutAttempts = this.imageTryoutAttempts[id] ?? 0;
27377
27440
  if (tryoutAttempts - 1 < this.config.imageLoading.maxRetryAttempts) {
27378
27441
  this.loadImageTryout(id);
@@ -27385,12 +27448,7 @@ var WeaveImageNode = class extends WeaveNode {
27385
27448
  return;
27386
27449
  }
27387
27450
  this.setErrorState(id, image);
27388
- image.setAttrs({ image: void 0 });
27389
- console.error("Error loading image", error);
27390
27451
  this.resolveAsyncElement(id);
27391
- imagePlaceholder?.setAttrs({ visible: true });
27392
- internalImage?.setAttrs({ visible: false });
27393
- this.cacheNode(image);
27394
27452
  }
27395
27453
  }, loadTryout);
27396
27454
  }
@@ -28385,8 +28443,8 @@ var WeaveStrokeNode = class extends WeaveNode {
28385
28443
  const segLen = Math.hypot(dx, dy) || 1;
28386
28444
  const nx = -dy / segLen;
28387
28445
  const ny = dx / segLen;
28388
- const w0 = baseW * p0.pressure / 2;
28389
- const w1 = baseW * p1.pressure / 2;
28446
+ const w0 = Math.max(baseW * p0.pressure / 2, .5);
28447
+ const w1 = Math.max(baseW * p1.pressure / 2, .5);
28390
28448
  let traveled = 0;
28391
28449
  while (traveled < segLen) {
28392
28450
  const step = Math.min(dashRemaining, segLen - traveled);
@@ -30076,8 +30134,7 @@ var WeaveVideoNode = class extends WeaveNode {
30076
30134
  this.videoPlaceholder[id] = Konva.Util.createImageElement();
30077
30135
  this.videoPlaceholder[id].crossOrigin = this.config.crossOrigin;
30078
30136
  this.videoPlaceholder[id].src = realVideoPlaceholderURL;
30079
- this.videoPlaceholder[id].onerror = (error) => {
30080
- console.error("Error loading video placeholder", realVideoPlaceholderURL, error);
30137
+ this.videoPlaceholder[id].onerror = () => {
30081
30138
  this.resolveAsyncElement(id);
30082
30139
  };
30083
30140
  this.videoPlaceholder[id].onload = () => {
@@ -33116,13 +33173,13 @@ var WeaveZoomOutToolAction = class extends WeaveAction {
33116
33173
  const stageZoomPlugin = this.getStageZoomPlugin();
33117
33174
  if (!stageZoomPlugin.canZoomOut()) return;
33118
33175
  stageZoomPlugin.zoomOut();
33119
- this.previousAction = params.previousAction;
33176
+ this.previousAction = params?.previousAction;
33120
33177
  this.cancelAction = cancelAction;
33121
33178
  this.cancelAction();
33122
33179
  }
33123
33180
  cleanup() {
33124
33181
  const stage = this.instance.getStage();
33125
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33182
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33126
33183
  stage.container().style.cursor = "default";
33127
33184
  }
33128
33185
  };
@@ -33154,13 +33211,13 @@ var WeaveZoomInToolAction = class extends WeaveAction {
33154
33211
  const stageZoomPlugin = this.getStageZoomPlugin();
33155
33212
  if (!stageZoomPlugin.canZoomIn()) return;
33156
33213
  stageZoomPlugin.zoomIn();
33157
- this.previousAction = params.previousAction;
33214
+ this.previousAction = params?.previousAction;
33158
33215
  this.cancelAction = cancelAction;
33159
33216
  this.cancelAction();
33160
33217
  }
33161
33218
  cleanup() {
33162
33219
  const stage = this.instance.getStage();
33163
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33220
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33164
33221
  stage.container().style.cursor = "default";
33165
33222
  }
33166
33223
  };
@@ -33191,21 +33248,17 @@ var WeaveFitToScreenToolAction = class extends WeaveAction {
33191
33248
  trigger(cancelAction, params) {
33192
33249
  const stageZoomPlugin = this.getStageZoomPlugin();
33193
33250
  if (stageZoomPlugin) stageZoomPlugin.fitToScreen({ overrideZoom: params?.overrideZoom ?? true });
33194
- this.previousAction = params.previousAction;
33251
+ this.previousAction = params?.previousAction;
33195
33252
  this.cancelAction = cancelAction;
33196
33253
  this.cancelAction();
33197
33254
  }
33198
33255
  cleanup() {
33199
33256
  const stage = this.instance.getStage();
33200
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33257
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33201
33258
  stage.container().style.cursor = "default";
33202
33259
  }
33203
33260
  };
33204
33261
 
33205
- //#endregion
33206
- //#region src/actions/fit-to-selection-tool/constants.ts
33207
- const FIT_TO_SELECTION_TOOL_ACTION_NAME = "fitToSelectionTool";
33208
-
33209
33262
  //#endregion
33210
33263
  //#region src/actions/fit-to-selection-tool/fit-to-selection-tool.ts
33211
33264
  var WeaveFitToSelectionToolAction = class extends WeaveAction {
@@ -33237,13 +33290,13 @@ var WeaveFitToSelectionToolAction = class extends WeaveAction {
33237
33290
  smartZoom: params?.smartZoom ?? false,
33238
33291
  overrideZoom: params?.overrideZoom ?? true
33239
33292
  });
33240
- this.previousAction = params.previousAction;
33293
+ this.previousAction = params?.previousAction;
33241
33294
  this.cancelAction = cancelAction;
33242
33295
  this.cancelAction();
33243
33296
  }
33244
33297
  cleanup() {
33245
33298
  const stage = this.instance.getStage();
33246
- if (this.previousAction !== void 0) this.instance.triggerAction(this.previousAction);
33299
+ if (this.previousAction) this.instance.triggerAction(this.previousAction);
33247
33300
  stage.container().style.cursor = "default";
33248
33301
  }
33249
33302
  };
@@ -34469,6 +34522,11 @@ const BRUSH_TOOL_DEFAULT_CONFIG = { interpolationSteps: 10 };
34469
34522
  var WeaveBrushToolAction = class extends WeaveAction {
34470
34523
  initialized = false;
34471
34524
  isSpacePressed = false;
34525
+ penActive = false;
34526
+ lastSmoothedPressure = .5;
34527
+ lastPointerPos = null;
34528
+ lastPointerTime = 0;
34529
+ predictedCount = 0;
34472
34530
  onPropsChange = void 0;
34473
34531
  onInit = void 0;
34474
34532
  constructor(params) {
@@ -34498,11 +34556,29 @@ var WeaveBrushToolAction = class extends WeaveAction {
34498
34556
  };
34499
34557
  }
34500
34558
  getEventPressure(e) {
34501
- if (e.evt.pointerType && e.evt.pointerType === "pen") return e.evt.pressure || .5;
34502
- return .5;
34559
+ const now$2 = performance.now();
34560
+ let velocity = 0;
34561
+ if (this.lastPointerPos && now$2 - this.lastPointerTime > 0) {
34562
+ const dx = e.evt.clientX - this.lastPointerPos.x;
34563
+ const dy = e.evt.clientY - this.lastPointerPos.y;
34564
+ velocity = Math.hypot(dx, dy) / (now$2 - this.lastPointerTime) * 1e3;
34565
+ }
34566
+ this.lastPointerPos = {
34567
+ x: e.evt.clientX,
34568
+ y: e.evt.clientY
34569
+ };
34570
+ this.lastPointerTime = now$2;
34571
+ const alpha = Math.min(Math.max(velocity / 1500, .15), .6);
34572
+ let raw;
34573
+ if (e.evt.pointerType === "pen") raw = e.evt.pressure || .5;
34574
+ else raw = .5;
34575
+ this.lastSmoothedPressure = alpha * raw + (1 - alpha) * this.lastSmoothedPressure;
34576
+ return Math.max(this.lastSmoothedPressure, .15);
34503
34577
  }
34504
34578
  setupEvents() {
34505
34579
  const stage = this.instance.getStage();
34580
+ this.prevTouchAction = stage.container().style.touchAction;
34581
+ stage.container().style.touchAction = "none";
34506
34582
  window.addEventListener("keyup", (e) => {
34507
34583
  if (e.code === "Space" && this.instance.getActiveAction() === BRUSH_TOOL_ACTION_NAME) this.isSpacePressed = false;
34508
34584
  }, { signal: this.instance.getEventsController()?.signal });
@@ -34527,7 +34603,9 @@ var WeaveBrushToolAction = class extends WeaveAction {
34527
34603
  if (this.state !== BRUSH_TOOL_STATE.IDLE) return;
34528
34604
  if (this.getZoomPlugin()?.isPinching()) return;
34529
34605
  if (this.isSpacePressed) return;
34530
- if (e.evt.button !== 0) return;
34606
+ if (e?.evt?.button !== 0) return;
34607
+ if (e.evt.pointerType === "touch" && this.penActive) return;
34608
+ if (e.evt.pointerType === "pen") this.penActive = true;
34531
34609
  const pointPressure = this.getEventPressure(e);
34532
34610
  this.handleStartStroke(pointPressure);
34533
34611
  e.evt.stopPropagation();
@@ -34538,12 +34616,27 @@ var WeaveBrushToolAction = class extends WeaveAction {
34538
34616
  this.setCursor();
34539
34617
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34540
34618
  if (this.getZoomPlugin()?.isPinching()) return;
34541
- const pointPressure = this.getEventPressure(e);
34542
- this.handleMovement(pointPressure);
34619
+ const coalescedEvents = e.evt.getCoalescedEvents ? e.evt.getCoalescedEvents() : [];
34620
+ if (coalescedEvents.length > 1) {
34621
+ for (const ce of coalescedEvents) {
34622
+ const pointPressure = ce.pointerType === "pen" && typeof ce.pressure === "number" ? ce.pressure : .5;
34623
+ this.handleMovement(pointPressure, void 0, false);
34624
+ }
34625
+ const predictedEvents = e.evt.getPredictedEvents ? e.evt.getPredictedEvents() : [];
34626
+ if (predictedEvents.length > 0) {
34627
+ const last = predictedEvents[predictedEvents.length - 1];
34628
+ const predPressure = last.pointerType === "pen" && typeof last.pressure === "number" ? last.pressure : .5;
34629
+ this.handleMovement(predPressure, last, true);
34630
+ }
34631
+ } else {
34632
+ const pointPressure = this.getEventPressure(e);
34633
+ this.handleMovement(pointPressure, void 0, false);
34634
+ }
34543
34635
  e.evt.stopPropagation();
34544
34636
  };
34545
34637
  stage.on("pointermove", handlePointerMove);
34546
34638
  const handlePointerUp = (e) => {
34639
+ this.penActive = false;
34547
34640
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34548
34641
  if (this.getZoomPlugin()?.isPinching()) return;
34549
34642
  this.handleEndStroke();
@@ -34580,6 +34673,10 @@ var WeaveBrushToolAction = class extends WeaveAction {
34580
34673
  };
34581
34674
  }
34582
34675
  handleStartStroke(pressure) {
34676
+ this.lastSmoothedPressure = .5;
34677
+ this.lastPointerPos = null;
34678
+ this.lastPointerTime = 0;
34679
+ this.predictedCount = 0;
34583
34680
  const { mousePoint, container, measureContainer } = this.instance.getMousePointer();
34584
34681
  this.clickPoint = mousePoint;
34585
34682
  this.container = container;
@@ -34608,17 +34705,25 @@ var WeaveBrushToolAction = class extends WeaveAction {
34608
34705
  }
34609
34706
  this.setState(BRUSH_TOOL_STATE.DEFINE_STROKE);
34610
34707
  }
34611
- handleMovement(pressure) {
34708
+ handleMovement(pressure, predictedEvent, isPredicted = false) {
34612
34709
  if (this.state !== BRUSH_TOOL_STATE.DEFINE_STROKE) return;
34710
+ const stage = this.instance.getStage();
34613
34711
  const tempStroke = this.instance.getStage().findOne(`#${this.strokeId}`);
34614
34712
  if (this.measureContainer && tempStroke) {
34713
+ if (predictedEvent) stage.setPointersPositions(predictedEvent);
34615
34714
  const { mousePoint } = this.instance.getMousePointerRelativeToContainer(this.measureContainer);
34616
34715
  const currentPoint = {
34617
34716
  x: mousePoint.x - tempStroke.x(),
34618
34717
  y: mousePoint.y - tempStroke.y(),
34619
34718
  pressure
34620
34719
  };
34621
- const newStrokeElements = [...tempStroke.getAttrs().strokeElements, currentPoint];
34720
+ let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34721
+ if (!isPredicted && this.predictedCount > 0) {
34722
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34723
+ this.predictedCount = 0;
34724
+ }
34725
+ newStrokeElements.push(currentPoint);
34726
+ if (isPredicted) this.predictedCount++;
34622
34727
  const box = this.getBoundingBox(newStrokeElements);
34623
34728
  tempStroke.setAttrs({
34624
34729
  width: box.width,
@@ -34638,17 +34743,22 @@ var WeaveBrushToolAction = class extends WeaveAction {
34638
34743
  if (nodeHandler) {
34639
34744
  const box = this.getBoundingBox(tempStroke.getAttrs().strokeElements);
34640
34745
  let newStrokeElements = [...tempStroke.getAttrs().strokeElements];
34746
+ if (this.predictedCount > 0) {
34747
+ newStrokeElements = newStrokeElements.slice(0, -1 * this.predictedCount);
34748
+ this.predictedCount = 0;
34749
+ }
34641
34750
  newStrokeElements = newStrokeElements.map((point) => ({
34642
34751
  ...point,
34643
34752
  x: point.x - box.x,
34644
34753
  y: point.y - box.y
34645
34754
  }));
34755
+ const compressedPoints = simplify(newStrokeElements, 1, true);
34646
34756
  tempStroke.setAttrs({
34647
34757
  width: box.width,
34648
34758
  height: box.height,
34649
34759
  x: box.x,
34650
34760
  y: box.y,
34651
- strokeElements: newStrokeElements
34761
+ strokeElements: compressedPoints
34652
34762
  });
34653
34763
  const realNode = this.instance.getStage().findOne(`#${tempStroke.getAttrs().id}`);
34654
34764
  if (realNode) realNode.destroy();
@@ -34684,6 +34794,7 @@ var WeaveBrushToolAction = class extends WeaveAction {
34684
34794
  }
34685
34795
  cleanup() {
34686
34796
  const stage = this.instance.getStage();
34797
+ stage.container().style.touchAction = this.prevTouchAction;
34687
34798
  stage.container().style.cursor = "default";
34688
34799
  this.instance.emitEvent("onAddedBrush");
34689
34800
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -39090,13 +39201,13 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
39090
39201
  });
39091
39202
  stage.on("pointerdown", (e) => {
39092
39203
  const activeAction = this.instance.getActiveAction();
39093
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39094
- if (e && (e.evt.button === 2 || e.evt.buttons === 4)) this.isMouseMiddleButtonPressed = true;
39204
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39205
+ if (e && (e?.evt?.button === 2 || e?.evt?.buttons === 4)) this.isMouseMiddleButtonPressed = true;
39095
39206
  });
39096
39207
  stage.on("pointerup", (e) => {
39097
39208
  const activeAction = this.instance.getActiveAction();
39098
- if (e && e.evt.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
39099
- if (e && (e.evt.button === 1 || e.evt.buttons === 0)) this.isMouseMiddleButtonPressed = false;
39209
+ if (e && e?.evt?.button === 0 && activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = false;
39210
+ if (e && (e?.evt?.button === 1 || e?.evt?.buttons === 0)) this.isMouseMiddleButtonPressed = false;
39100
39211
  });
39101
39212
  const handleMouseMove = () => {
39102
39213
  if (!this.enabled || !(this.isSpaceKeyPressed || this.isMouseMiddleButtonPressed || this.moveToolActive)) return;
@@ -39413,16 +39524,16 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
39413
39524
  let lastPos = null;
39414
39525
  stage.on("pointerdown", (e) => {
39415
39526
  this.pointers.set(e.evt.pointerId, {
39416
- x: e.evt.clientX,
39417
- y: e.evt.clientY
39527
+ x: e?.evt?.clientX ?? 0,
39528
+ y: e?.evt?.clientY ?? 0
39418
39529
  });
39419
39530
  if (this.pointers.size > 1) return;
39420
39531
  const activeAction = this.instance.getActiveAction();
39421
39532
  this.enableMove = false;
39422
39533
  if (activeAction === MOVE_TOOL_ACTION_NAME) this.moveToolActive = true;
39423
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 1) this.isMouseLeftButtonPressed = true;
39424
- if (e.evt.pointerType === "mouse" && e.evt.buttons === 4) this.isMouseMiddleButtonPressed = true;
39425
- const isTouchOrPen = ["touch", "pen"].includes(e.evt.pointerType);
39534
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 1) this.isMouseLeftButtonPressed = true;
39535
+ if (e.evt.pointerType === "mouse" && e?.evt?.buttons === 4) this.isMouseMiddleButtonPressed = true;
39536
+ const isTouchOrPen = ["touch", "pen"].includes(e?.evt?.pointerType);
39426
39537
  if (this.enabled && (this.isSpaceKeyPressed || this.moveToolActive && (this.isMouseLeftButtonPressed || isTouchOrPen) || this.isMouseMiddleButtonPressed)) this.enableMove = true;
39427
39538
  if (this.enableMove) {
39428
39539
  this.isDragging = true;
@@ -39431,7 +39542,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
39431
39542
  }
39432
39543
  });
39433
39544
  stage.on("pointercancel", (e) => {
39434
- this.pointers.delete(e.evt.pointerId);
39545
+ if (e?.evt?.pointerId) this.pointers.delete(e.evt.pointerId);
39435
39546
  lastPos = null;
39436
39547
  });
39437
39548
  const handleMouseMove = (e) => {