@inditextech/weave-sdk 2.12.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk.node.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import Konva from "konva";
2
2
  import { randomFillSync, randomUUID } from "crypto";
3
3
  import pino from "pino";
4
- import { WEAVE_AWARENESS_LAYER_ID, WEAVE_EXPORT_BACKGROUND_COLOR, WEAVE_EXPORT_FORMATS, WEAVE_INSTANCE_STATUS, WEAVE_KONVA_BACKEND, WEAVE_NODE_CUSTOM_EVENTS, WEAVE_NODE_LAYER_ID, WEAVE_NODE_POSITION, WEAVE_STORE_CONNECTION_STATUS, WEAVE_UTILITY_LAYER_ID } from "@inditextech/weave-types";
4
+ import { WEAVE_ASYNC_STATUS, WEAVE_AWARENESS_LAYER_ID, WEAVE_EXPORT_BACKGROUND_COLOR, WEAVE_EXPORT_FORMATS, WEAVE_INSTANCE_STATUS, WEAVE_KONVA_BACKEND, WEAVE_NODE_CUSTOM_EVENTS, WEAVE_NODE_LAYER_ID, WEAVE_NODE_POSITION, WEAVE_STORE_CONNECTION_STATUS, WEAVE_UTILITY_LAYER_ID } from "@inditextech/weave-types";
5
5
  import { getYjsDoc, getYjsValue, observeDeep, syncedStore } from "@syncedstore/core";
6
6
  import * as Y from "yjs";
7
7
  import React from "react";
@@ -18562,6 +18562,7 @@ const WEAVE_GRID_LAYER_ID = "gridLayer";
18562
18562
  //#endregion
18563
18563
  //#region src/plugins/stage-panning/constants.ts
18564
18564
  const WEAVE_STAGE_PANNING_KEY = "stagePanning";
18565
+ const WEAVE_STAGE_PANNING_THROTTLE_MS = 20;
18565
18566
  const WEAVE_STAGE_PANNING_DEFAULT_CONFIG = {
18566
18567
  edgePanOffset: 50,
18567
18568
  edgePanSpeed: 10
@@ -18577,6 +18578,16 @@ const WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG = { style: {
18577
18578
  fill: "transparent"
18578
18579
  } };
18579
18580
 
18581
+ //#endregion
18582
+ //#region src/constants.ts
18583
+ const DEFAULT_THROTTLE_MS = 50;
18584
+
18585
+ //#endregion
18586
+ //#region src/plugins/users-presence/constants.ts
18587
+ const WEAVE_USER_PRESENCE_KEY = "userPresence";
18588
+ const WEAVE_USERS_PRESENCE_PLUGIN_KEY = "usersPresence";
18589
+ const WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS = { awarenessThrottleMs: DEFAULT_THROTTLE_MS };
18590
+
18580
18591
  //#endregion
18581
18592
  //#region src/plugins/nodes-selection/nodes-selection.ts
18582
18593
  var WeaveNodesSelectionPlugin = class extends WeavePlugin {
@@ -18703,6 +18714,15 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18703
18714
  });
18704
18715
  tr.on("transformstart", () => {
18705
18716
  this.triggerSelectedNodesEvent();
18717
+ const selectedNodes = tr.nodes();
18718
+ for (const node of selectedNodes) if (node.getAttrs().strokeScaleEnabled !== false) {
18719
+ node.setAttr("strokeScaleEnabled", false);
18720
+ node.setAttr("_revertStrokeScaleEnabled", true);
18721
+ }
18722
+ if (this.getSelectedNodes().length > 1) this.instance.setMutexLock({
18723
+ nodeIds: selectedNodes.map((node) => node.id()),
18724
+ operation: "nodes-transform"
18725
+ });
18706
18726
  });
18707
18727
  let nodeHovered = void 0;
18708
18728
  tr.on("mousemove", () => {
@@ -18740,9 +18760,26 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18740
18760
  const moved = this.checkMoved(e);
18741
18761
  if (moved) this.getContextMenuPlugin()?.cancelLongPressTimer();
18742
18762
  this.triggerSelectedNodesEvent();
18763
+ if (this.getUsersPresencePlugin()) for (const node of tr.nodes()) this.getUsersPresencePlugin()?.setPresence(node.id(), {
18764
+ x: node.x(),
18765
+ y: node.y(),
18766
+ width: node.width(),
18767
+ height: node.height(),
18768
+ scaleX: node.scaleX(),
18769
+ scaleY: node.scaleY(),
18770
+ rotation: node.rotation(),
18771
+ strokeScaleEnabled: false
18772
+ });
18743
18773
  };
18744
- tr.on("transform", (0, import_throttle.default)(handleTransform, 50));
18774
+ tr.on("transform", (0, import_throttle.default)(handleTransform, DEFAULT_THROTTLE_MS));
18745
18775
  tr.on("transformend", () => {
18776
+ if (this.getSelectedNodes().length > 1) this.instance.releaseMutexLock();
18777
+ const selectedNodes = tr.nodes();
18778
+ for (const node of selectedNodes) {
18779
+ if (node.getAttrs()._revertStrokeScaleEnabled === true) node.setAttr("strokeScaleEnabled", true);
18780
+ node.setAttr("_revertStrokeScaleEnabled", void 0);
18781
+ if (this.getUsersPresencePlugin()) this.getUsersPresencePlugin()?.removePresence(node.id());
18782
+ }
18746
18783
  this.triggerSelectedNodesEvent();
18747
18784
  });
18748
18785
  let initialPos = null;
@@ -18776,6 +18813,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18776
18813
  }
18777
18814
  e.cancelBubble = true;
18778
18815
  tr.forceUpdate();
18816
+ if (this.getSelectedNodes().length > 1) this.instance.setMutexLock({
18817
+ nodeIds: selectedNodes.map((node) => node.id()),
18818
+ operation: "nodes-drag"
18819
+ });
18779
18820
  });
18780
18821
  const handleDragMove = (e) => {
18781
18822
  const actualPos = {
@@ -18808,6 +18849,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18808
18849
  if (this.isSelecting() && selectedNodes.length > 1) {
18809
18850
  clearContainerTargets(this.instance);
18810
18851
  const layerToMove = containerOverCursor(this.instance, selectedNodes);
18852
+ if (this.getUsersPresencePlugin()) for (const node of selectedNodes) this.getUsersPresencePlugin()?.setPresence(node.id(), {
18853
+ x: node.x(),
18854
+ y: node.y()
18855
+ });
18811
18856
  if (layerToMove && !selectionContainsFrames) layerToMove.fire(WEAVE_NODE_CUSTOM_EVENTS.onTargetEnter, { bubbles: true });
18812
18857
  }
18813
18858
  tr.forceUpdate();
@@ -18815,12 +18860,14 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18815
18860
  tr.on("dragmove", handleDragMove);
18816
18861
  tr.on("dragend", (e) => {
18817
18862
  if (!this.didMove) return;
18863
+ if (this.getSelectedNodes().length > 1) this.instance.releaseMutexLock();
18818
18864
  e.cancelBubble = true;
18819
18865
  if (tr.nodes().length > 1) {
18820
18866
  const nodes$1 = tr.nodes();
18821
18867
  for (const node of nodes$1) {
18822
18868
  this.getNodesSelectionFeedbackPlugin()?.showSelectionHalo(node);
18823
18869
  this.getNodesSelectionFeedbackPlugin()?.updateSelectionHalo(node);
18870
+ this.getUsersPresencePlugin()?.removePresence(node.id());
18824
18871
  }
18825
18872
  }
18826
18873
  this.instance.getCloningManager().cleanupClones();
@@ -19194,6 +19241,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19194
19241
  stage.on("pointermove", handleMouseMove);
19195
19242
  this.panLoop();
19196
19243
  stage.on("pointerup", (e) => {
19244
+ const store = this.instance.getStore();
19245
+ const actUser = store.getUser();
19197
19246
  this.tr.setAttrs({ listening: true });
19198
19247
  this.selecting = false;
19199
19248
  this.stopPanLoop();
@@ -19258,6 +19307,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19258
19307
  const box = this.selectionRectangle.getClientRect();
19259
19308
  this.selectionRectangle.visible(false);
19260
19309
  const selected = shapes.filter((shape) => {
19310
+ const shapeMutex = this.instance.getNodeMutexLock(shape.id());
19311
+ if (shapeMutex && shapeMutex.user.id !== actUser.id) return false;
19261
19312
  let parent = this.instance.getInstanceRecursive(shape.getParent());
19262
19313
  if (parent.getAttrs().nodeId) parent = this.instance.getStage().findOne(`#${parent.getAttrs().nodeId}`);
19263
19314
  if (shape.getAttrs().nodeType && shape.getAttrs().nodeType === "frame") {
@@ -19360,7 +19411,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19360
19411
  return node.getAttrs().id === nodeTargeted.getAttrs().id;
19361
19412
  });
19362
19413
  const isSelected = nodeSelectedIndex !== -1;
19363
- if (nodeTargeted.getAttrs().locked) return;
19414
+ const user = this.instance.getStore().getUser();
19415
+ const isLocked = nodeTargeted.getAttrs().locked ?? false;
19416
+ const isMutexLocked = nodeTargeted.getAttrs().mutexLocked && nodeTargeted.getAttrs().mutexUserId !== user.id;
19417
+ if (isLocked || isMutexLocked) return;
19364
19418
  if (nodeTargeted.getAttrs().nodeId) {
19365
19419
  const realNode = stage.findOne(`#${nodeTargeted.getAttrs().nodeId}`);
19366
19420
  if (realNode) nodeTargeted = realNode;
@@ -19491,6 +19545,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19491
19545
  const stagePanning = this.instance.getPlugin(WEAVE_STAGE_PANNING_KEY);
19492
19546
  return stagePanning;
19493
19547
  }
19548
+ getUsersPresencePlugin() {
19549
+ const usersPresencePlugin = this.instance.getPlugin(WEAVE_USERS_PRESENCE_PLUGIN_KEY);
19550
+ return usersPresencePlugin;
19551
+ }
19494
19552
  getSelectorConfig() {
19495
19553
  return this.config.selection;
19496
19554
  }
@@ -20112,6 +20170,25 @@ var WeaveNode = class {
20112
20170
  });
20113
20171
  return anchors;
20114
20172
  };
20173
+ node.lockMutex = function(user) {
20174
+ const actUser = actInstance.getStore().getUser();
20175
+ this.setAttrs({
20176
+ mutexLocked: true,
20177
+ mutexUserId: user.id
20178
+ });
20179
+ const selectionPlugin = actInstance.getPlugin("nodesSelection");
20180
+ if (selectionPlugin && actUser.id !== user.id) {
20181
+ const selectedNodes = selectionPlugin.getSelectedNodes();
20182
+ const filteredNodes = selectedNodes.filter((n) => n.getAttrs().id !== this.getAttrs().id);
20183
+ selectionPlugin.setSelectedNodes(filteredNodes);
20184
+ }
20185
+ };
20186
+ node.releaseMutex = function() {
20187
+ this.setAttrs({
20188
+ mutexLocked: false,
20189
+ mutexUserId: void 0
20190
+ });
20191
+ };
20115
20192
  }
20116
20193
  isNodeSelected(ele) {
20117
20194
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -20165,8 +20242,16 @@ var WeaveNode = class {
20165
20242
  let transforming = false;
20166
20243
  node.on("transformstart", (e) => {
20167
20244
  transforming = true;
20245
+ if (e.target.getAttrs().strokeScaleEnabled !== false) {
20246
+ e.target.setAttr("strokeScaleEnabled", false);
20247
+ e.target.setAttr("_revertStrokeScaleEnabled", true);
20248
+ }
20168
20249
  this.getNodesSelectionFeedbackPlugin()?.hideSelectionHalo(node);
20169
20250
  this.instance.emitEvent("onTransform", e.target);
20251
+ if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.setMutexLock({
20252
+ nodeIds: [e.target.id()],
20253
+ operation: "node-transform"
20254
+ });
20170
20255
  });
20171
20256
  const handleTransform = (e) => {
20172
20257
  const node$1 = e.target;
@@ -20174,11 +20259,24 @@ var WeaveNode = class {
20174
20259
  const nodesEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
20175
20260
  if (nodesSelectionPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSelectionPlugin.getTransformer().forceUpdate();
20176
20261
  if (nodesEdgeSnappingPlugin && transforming && this.isSelecting() && this.isNodeSelected(node$1)) nodesEdgeSnappingPlugin.evaluateGuidelines(e);
20262
+ this.getUsersPresencePlugin()?.setPresence(node$1.id(), {
20263
+ x: node$1.x(),
20264
+ y: node$1.y(),
20265
+ width: node$1.width(),
20266
+ height: node$1.height(),
20267
+ scaleX: node$1.scaleX(),
20268
+ scaleY: node$1.scaleY(),
20269
+ rotation: node$1.rotation(),
20270
+ strokeScaleEnabled: false
20271
+ });
20177
20272
  };
20178
- node.on("transform", (0, import_lodash.throttle)(handleTransform, 100));
20273
+ node.on("transform", (0, import_lodash.throttle)(handleTransform, DEFAULT_THROTTLE_MS));
20179
20274
  node.on("transformend", (e) => {
20180
20275
  const node$1 = e.target;
20181
- e.target.setAttr("strokeScaleEnabled", true);
20276
+ if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.releaseMutexLock();
20277
+ this.getUsersPresencePlugin()?.removePresence(node$1.id());
20278
+ if (e.target.getAttrs()._revertStrokeScaleEnabled === true) e.target.setAttr("strokeScaleEnabled", true);
20279
+ e.target.setAttr("_revertStrokeScaleEnabled", void 0);
20182
20280
  this.instance.emitEvent("onTransform", null);
20183
20281
  transforming = false;
20184
20282
  const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -20258,6 +20356,10 @@ var WeaveNode = class {
20258
20356
  clone?.startDrag(e.evt);
20259
20357
  });
20260
20358
  }
20359
+ if (this.getNodesSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.setMutexLock({
20360
+ nodeIds: [e.target.id()],
20361
+ operation: "node-drag"
20362
+ });
20261
20363
  });
20262
20364
  const handleDragMove = (e) => {
20263
20365
  const nodeTarget = e.target;
@@ -20281,14 +20383,19 @@ var WeaveNode = class {
20281
20383
  const realNodeTarget = this.getRealSelectedNode(nodeTarget);
20282
20384
  if (this.isSelecting() && this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
20283
20385
  clearContainerTargets(this.instance);
20386
+ this.getUsersPresencePlugin()?.setPresence(realNodeTarget.id(), {
20387
+ x: realNodeTarget.x(),
20388
+ y: realNodeTarget.y()
20389
+ });
20284
20390
  const layerToMove = containerOverCursor(this.instance, [realNodeTarget]);
20285
20391
  if (layerToMove && !hasFrames(realNodeTarget) && realNodeTarget.isDragging() && !realNodeTarget.getAttrs().lockToContainer) layerToMove.fire(WEAVE_NODE_CUSTOM_EVENTS.onTargetEnter, { node: realNodeTarget });
20286
20392
  }
20287
20393
  };
20288
- node.on("dragmove", (0, import_lodash.throttle)(handleDragMove, 100));
20394
+ node.on("dragmove", (0, import_lodash.throttle)(handleDragMove, DEFAULT_THROTTLE_MS));
20289
20395
  node.on("dragend", (e) => {
20290
20396
  const nodeTarget = e.target;
20291
20397
  if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
20398
+ this.instance.releaseMutexLock();
20292
20399
  this.getNodesSelectionFeedbackPlugin()?.showSelectionHalo(nodeTarget);
20293
20400
  this.getNodesSelectionFeedbackPlugin()?.updateSelectionHalo(nodeTarget);
20294
20401
  }
@@ -20308,6 +20415,7 @@ var WeaveNode = class {
20308
20415
  }
20309
20416
  this.instance.emitEvent("onDrag", null);
20310
20417
  const realNodeTarget = this.getRealSelectedNode(nodeTarget);
20418
+ this.getUsersPresencePlugin()?.removePresence(realNodeTarget.id());
20311
20419
  if (this.getNodesSelectionPlugin()?.getSelectedNodes().length === 1 && realNodeTarget.getAttr("dragStartOpacity") !== void 0) {
20312
20420
  const originalNodeOpacity = realNodeTarget.getAttr("dragStartOpacity") ?? 1;
20313
20421
  realNodeTarget.setAttrs({ opacity: originalNodeOpacity });
@@ -20376,35 +20484,33 @@ var WeaveNode = class {
20376
20484
  }
20377
20485
  handleMouseOver(node) {
20378
20486
  const stage = this.instance.getStage();
20487
+ const user = this.instance.getStore().getUser();
20379
20488
  const activeAction = this.instance.getActiveAction();
20380
20489
  const isNodeSelectionEnabled = this.getSelectionPlugin()?.isEnabled();
20381
20490
  const realNode = this.instance.getInstanceRecursive(node);
20382
20491
  const isTargetable = node.getAttrs().isTargetable !== false;
20383
20492
  const isLocked = node.getAttrs().locked ?? false;
20493
+ const isMutexLocked = realNode.getAttrs().mutexLocked && realNode.getAttrs().mutexUserId !== user.id;
20384
20494
  if ([MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "")) return false;
20385
20495
  let showHover = false;
20386
20496
  let cancelBubble = false;
20387
- if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isLocked) {
20388
- const stage$1 = this.instance.getStage();
20389
- stage$1.container().style.cursor = "default";
20497
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && (isLocked || isMutexLocked)) {
20498
+ stage.container().style.cursor = "default";
20390
20499
  cancelBubble = true;
20391
20500
  }
20392
- if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !isLocked && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20393
- const stage$1 = this.instance.getStage();
20501
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20394
20502
  showHover = true;
20395
- stage$1.container().style.cursor = "pointer";
20503
+ stage.container().style.cursor = "pointer";
20396
20504
  cancelBubble = true;
20397
20505
  }
20398
- if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !isLocked && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20399
- const stage$1 = this.instance.getStage();
20506
+ if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20400
20507
  showHover = true;
20401
- stage$1.container().style.cursor = "grab";
20508
+ stage.container().style.cursor = "grab";
20402
20509
  cancelBubble = true;
20403
20510
  }
20404
20511
  if (!isTargetable) cancelBubble = true;
20405
20512
  if (this.isPasting()) {
20406
- const stage$1 = this.instance.getStage();
20407
- stage$1.container().style.cursor = "crosshair";
20513
+ stage.container().style.cursor = "crosshair";
20408
20514
  cancelBubble = true;
20409
20515
  }
20410
20516
  if (showHover) this.setHoverState(realNode);
@@ -20435,6 +20541,8 @@ var WeaveNode = class {
20435
20541
  serialize(instance) {
20436
20542
  const attrs = instance.getAttrs();
20437
20543
  const cleanedAttrs = { ...attrs };
20544
+ delete cleanedAttrs.mutexLocked;
20545
+ delete cleanedAttrs.mutexUserId;
20438
20546
  delete cleanedAttrs.draggable;
20439
20547
  return {
20440
20548
  key: attrs.id ?? "",
@@ -20555,6 +20663,10 @@ var WeaveNode = class {
20555
20663
  const selectionFeedbackPlugin = this.instance.getPlugin(WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY);
20556
20664
  return selectionFeedbackPlugin;
20557
20665
  }
20666
+ getUsersPresencePlugin() {
20667
+ const usersPresencePlugin = this.instance.getPlugin(WEAVE_USERS_PRESENCE_PLUGIN_KEY);
20668
+ return usersPresencePlugin;
20669
+ }
20558
20670
  };
20559
20671
 
20560
20672
  //#endregion
@@ -21991,7 +22103,7 @@ var WeaveRegisterManager = class {
21991
22103
 
21992
22104
  //#endregion
21993
22105
  //#region package.json
21994
- var version = "2.12.0";
22106
+ var version = "2.13.0";
21995
22107
 
21996
22108
  //#endregion
21997
22109
  //#region src/managers/setup.ts
@@ -22470,7 +22582,163 @@ var WeavePluginsManager = class {
22470
22582
  };
22471
22583
 
22472
22584
  //#endregion
22473
- //#region src/watch-map.ts
22585
+ //#region src/plugins/connected-users/constants.ts
22586
+ const WEAVE_CONNECTED_USERS_KEY = "connectedUsers";
22587
+ const WEAVE_CONNECTED_USER_INFO_KEY = "userInfo";
22588
+
22589
+ //#endregion
22590
+ //#region src/managers/mutex/mutex.ts
22591
+ var WeaveMutexManager = class {
22592
+ userMutexLocked = new Map();
22593
+ nodeMutexLocked = new Map();
22594
+ WEAVE_USER_MUTEX_LOCK_KEY = "userMutexLock";
22595
+ constructor(instance) {
22596
+ this.instance = instance;
22597
+ this.logger = this.instance.getChildLogger("mutex-manager");
22598
+ this.logger.debug("Mutex manager created");
22599
+ this.init();
22600
+ }
22601
+ init() {
22602
+ this.setupMutexManager();
22603
+ }
22604
+ setupMutexManager() {
22605
+ this.instance.addEventListener("onConnectedUsersChange", (users) => {
22606
+ const actUser = this.instance.getStore().getUser();
22607
+ const userMutexKeys = Array.from(this.userMutexLocked.keys());
22608
+ for (const userMutexKey of userMutexKeys) if (actUser.id !== userMutexKey && !users[userMutexKey]) {
22609
+ const info = this.userMutexLocked.get(userMutexKey);
22610
+ if (info) {
22611
+ const user = info.user;
22612
+ this.releaseMutexLockRemote(user);
22613
+ }
22614
+ }
22615
+ });
22616
+ this.instance.addEventListener(
22617
+ "onAwarenessChange",
22618
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22619
+ (changes) => {
22620
+ const actUser = this.instance.getStore().getUser();
22621
+ for (const change of changes) {
22622
+ if (!change[this.WEAVE_USER_MUTEX_LOCK_KEY] && change[WEAVE_CONNECTED_USER_INFO_KEY] && actUser.id !== change[WEAVE_CONNECTED_USER_INFO_KEY].id) {
22623
+ const user = change[WEAVE_CONNECTED_USER_INFO_KEY];
22624
+ this.releaseMutexLockRemote(user);
22625
+ continue;
22626
+ }
22627
+ if (change[WEAVE_CONNECTED_USER_INFO_KEY] && actUser.id !== change[WEAVE_CONNECTED_USER_INFO_KEY].id) {
22628
+ const user = change[WEAVE_CONNECTED_USER_INFO_KEY];
22629
+ const mutexInfo = change[this.WEAVE_USER_MUTEX_LOCK_KEY];
22630
+ this.setMutexLockRemote({
22631
+ nodeIds: mutexInfo.nodeIds,
22632
+ operation: mutexInfo.operation,
22633
+ metadata: mutexInfo.metadata
22634
+ }, user);
22635
+ }
22636
+ }
22637
+ }
22638
+ );
22639
+ }
22640
+ async acquireMutexLock({ nodeIds, operation }, action) {
22641
+ const lockAcquired = this.setMutexLock({
22642
+ nodeIds,
22643
+ operation
22644
+ });
22645
+ if (lockAcquired) {
22646
+ await Promise.resolve(action());
22647
+ this.releaseMutexLock();
22648
+ }
22649
+ }
22650
+ getUserMutexLock(userMutexKey) {
22651
+ if (this.userMutexLocked.get(userMutexKey)) return this.userMutexLocked.get(userMutexKey);
22652
+ return void 0;
22653
+ }
22654
+ getNodeMutexLock(nodeMutexKey) {
22655
+ if (this.nodeMutexLocked.get(nodeMutexKey)) return this.nodeMutexLocked.get(nodeMutexKey);
22656
+ return void 0;
22657
+ }
22658
+ getUserMutexKey(user) {
22659
+ const store = this.instance.getStore();
22660
+ let userInfo = store.getUser();
22661
+ if (user !== void 0) userInfo = user;
22662
+ return userInfo.id;
22663
+ }
22664
+ getNodeMutexKey(nodeId) {
22665
+ return nodeId;
22666
+ }
22667
+ setMutexLockRemote({ nodeIds, operation, metadata }, user) {
22668
+ return this.setMutexLock({
22669
+ nodeIds,
22670
+ operation,
22671
+ metadata
22672
+ }, user, false);
22673
+ }
22674
+ setMutexLock({ nodeIds, operation, metadata }, userInfo = void 0, sendAwareness = true) {
22675
+ const store = this.instance.getStore();
22676
+ let user = store.getUser();
22677
+ if (userInfo !== void 0) user = userInfo;
22678
+ const userMutexKey = this.getUserMutexKey(user);
22679
+ if (this.userMutexLocked.has(userMutexKey)) return false;
22680
+ const preLockedNodes = [];
22681
+ for (const nodeId of nodeIds) {
22682
+ const nodeMutexKey = this.getNodeMutexKey(nodeId);
22683
+ if (this.nodeMutexLocked.has(nodeMutexKey)) break;
22684
+ else {
22685
+ this.nodeMutexLocked.set(nodeMutexKey, {
22686
+ user,
22687
+ operation,
22688
+ metadata
22689
+ });
22690
+ const nodeInstance = this.instance.getStage().findOne(`#${nodeId}`);
22691
+ if (nodeInstance) nodeInstance.lockMutex(user);
22692
+ preLockedNodes.push(nodeMutexKey);
22693
+ }
22694
+ }
22695
+ if (preLockedNodes.length === nodeIds.length && !this.userMutexLocked.has(userMutexKey)) {
22696
+ this.userMutexLocked.set(userMutexKey, {
22697
+ user,
22698
+ nodeIds,
22699
+ operation,
22700
+ metadata
22701
+ });
22702
+ if (sendAwareness) store.setAwarenessInfo(this.WEAVE_USER_MUTEX_LOCK_KEY, {
22703
+ user,
22704
+ nodeIds,
22705
+ operation,
22706
+ metadata
22707
+ });
22708
+ this.instance.emitEvent("onMutexLockChange", { locks: [...this.userMutexLocked.keys()] });
22709
+ return true;
22710
+ }
22711
+ if (preLockedNodes.length !== nodeIds.length) {
22712
+ this.userMutexLocked.delete(userMutexKey);
22713
+ for (const nodeMutexKey of preLockedNodes) this.nodeMutexLocked.delete(nodeMutexKey);
22714
+ }
22715
+ return false;
22716
+ }
22717
+ releaseMutexLockRemote(user) {
22718
+ this.releaseMutexLock(user, false);
22719
+ }
22720
+ releaseMutexLock(userInfo = void 0, sendAwareness = true) {
22721
+ const store = this.instance.getStore();
22722
+ let user = store.getUser();
22723
+ if (userInfo !== void 0) user = userInfo;
22724
+ const userMutexKey = this.getUserMutexKey(user);
22725
+ if (this.userMutexLocked.has(userMutexKey)) {
22726
+ const nodeIds = this.userMutexLocked.get(userMutexKey).nodeIds;
22727
+ for (const nodeId of nodeIds) {
22728
+ const nodeMutexKey = this.getNodeMutexKey(nodeId);
22729
+ this.nodeMutexLocked.delete(nodeMutexKey);
22730
+ const nodeInstance = this.instance.getStage().findOne(`#${nodeId}`);
22731
+ if (nodeInstance) nodeInstance.releaseMutex();
22732
+ }
22733
+ this.userMutexLocked.delete(userMutexKey);
22734
+ if (sendAwareness) store.setAwarenessInfo(this.WEAVE_USER_MUTEX_LOCK_KEY, void 0);
22735
+ this.instance.emitEvent("onMutexLockChange", { locks: [...this.userMutexLocked.keys()] });
22736
+ }
22737
+ }
22738
+ };
22739
+
22740
+ //#endregion
22741
+ //#region src/managers/async/watch-map.ts
22474
22742
  function watchMap(onChange, map = new Map()) {
22475
22743
  const handler = { get(target, prop, receiver) {
22476
22744
  if (prop === "set") return (key, value$1) => {
@@ -22514,12 +22782,70 @@ function watchMap(onChange, map = new Map()) {
22514
22782
  return new Proxy(map, handler);
22515
22783
  }
22516
22784
 
22785
+ //#endregion
22786
+ //#region src/managers/async/async.ts
22787
+ var WeaveAsyncManager = class {
22788
+ constructor(instance) {
22789
+ this.instance = instance;
22790
+ this.logger = this.instance.getChildLogger("async-manager");
22791
+ this.logger.debug("Async manager created");
22792
+ this.asyncElements = watchMap(() => {
22793
+ this.instance.emitEvent("onAsyncElementChange");
22794
+ }, new Map());
22795
+ }
22796
+ asyncElementsLoaded() {
22797
+ return [...this.asyncElements.values()].every((el) => el.status === WEAVE_ASYNC_STATUS.LOADED);
22798
+ }
22799
+ loadAsyncElement(nodeId, type) {
22800
+ let element = this.asyncElements.get(nodeId);
22801
+ if (element) element.status = WEAVE_ASYNC_STATUS.LOADING;
22802
+ else element = {
22803
+ type,
22804
+ status: WEAVE_ASYNC_STATUS.LOADING
22805
+ };
22806
+ this.asyncElements.set(nodeId, element);
22807
+ }
22808
+ resolveAsyncElement(nodeId, type) {
22809
+ let element = this.asyncElements.get(nodeId);
22810
+ if (element) element.status = WEAVE_ASYNC_STATUS.LOADED;
22811
+ else element = {
22812
+ type,
22813
+ status: WEAVE_ASYNC_STATUS.LOADED
22814
+ };
22815
+ this.asyncElements.set(nodeId, element);
22816
+ }
22817
+ };
22818
+
22819
+ //#endregion
22820
+ //#region src/managers/hooks.ts
22821
+ var WeaveHooksManager = class {
22822
+ registeredHooks = new Map();
22823
+ constructor(instance) {
22824
+ this.instance = instance;
22825
+ this.logger = this.instance.getChildLogger("hooks-manager");
22826
+ this.logger.debug("Hooks manager created");
22827
+ }
22828
+ registerHook(hookName, hook) {
22829
+ const exists = this.registeredHooks.has(hookName);
22830
+ if (!exists) this.registeredHooks.set(hookName, hook);
22831
+ }
22832
+ runPhaseHooks(phaseName, execution) {
22833
+ const hooks = [...this.registeredHooks.keys()].filter((key) => key.startsWith(`${phaseName}:`)).map((key) => this.registeredHooks.get(key));
22834
+ for (const hook of hooks) execution(hook);
22835
+ }
22836
+ getHook(hookName) {
22837
+ return this.registeredHooks.get(hookName);
22838
+ }
22839
+ unregisterHook(hookName) {
22840
+ this.registeredHooks.delete(hookName);
22841
+ }
22842
+ };
22843
+
22517
22844
  //#endregion
22518
22845
  //#region src/weave.ts
22519
22846
  var Weave = class {
22520
22847
  initialized = false;
22521
22848
  status = WEAVE_INSTANCE_STATUS.IDLE;
22522
- registeredHooks = new Map();
22523
22849
  constructor(weaveConfig, stageConfig) {
22524
22850
  globalThis._weave_isServerSide = false;
22525
22851
  if (typeof window === "undefined") globalThis._weave_isServerSide = true;
@@ -22527,9 +22853,6 @@ var Weave = class {
22527
22853
  Konva.showWarnings = false;
22528
22854
  this.id = v4_default();
22529
22855
  this.initialized = false;
22530
- this.asyncElements = watchMap(() => {
22531
- this.emitEvent("onAsyncElementChange");
22532
- }, new Map());
22533
22856
  this.config = mergeExceptArrays({}, weaveConfig);
22534
22857
  this.logger = new WeaveLogger(this.config?.logger ?? {
22535
22858
  disabled: false,
@@ -22552,6 +22875,9 @@ var Weave = class {
22552
22875
  this.exportManager = new WeaveExportManager(this);
22553
22876
  this.actionsManager = new WeaveActionsManager(this);
22554
22877
  this.pluginsManager = new WeavePluginsManager(this);
22878
+ this.mutexManager = new WeaveMutexManager(this);
22879
+ this.asyncManager = new WeaveAsyncManager(this);
22880
+ this.hooksManager = new WeaveHooksManager(this);
22555
22881
  this.setupManager.welcomeLog();
22556
22882
  }
22557
22883
  getRenderer() {
@@ -23041,42 +23367,50 @@ var Weave = class {
23041
23367
  }
23042
23368
  }
23043
23369
  asyncElementsLoaded() {
23044
- return [...this.asyncElements.values()].every((el) => el.status === "loaded");
23370
+ return this.asyncManager.asyncElementsLoaded();
23045
23371
  }
23046
23372
  loadAsyncElement(nodeId, type) {
23047
- let element = this.asyncElements.get(nodeId);
23048
- if (element) element.status = "loading";
23049
- else element = {
23050
- type,
23051
- status: "loading"
23052
- };
23053
- this.asyncElements.set(nodeId, element);
23373
+ this.asyncManager.loadAsyncElement(nodeId, type);
23054
23374
  }
23055
23375
  resolveAsyncElement(nodeId, type) {
23056
- let element = this.asyncElements.get(nodeId);
23057
- if (element) element.status = "loaded";
23058
- else element = {
23059
- type,
23060
- status: "loaded"
23061
- };
23062
- this.asyncElements.set(nodeId, element);
23376
+ this.asyncManager.resolveAsyncElement(nodeId, type);
23063
23377
  }
23064
23378
  isServerSide() {
23065
23379
  return globalThis._weave_isServerSide === true;
23066
23380
  }
23067
23381
  registerHook(hookName, hook) {
23068
- const exists = this.registeredHooks.has(hookName);
23069
- if (!exists) this.registeredHooks.set(hookName, hook);
23382
+ this.hooksManager.registerHook(hookName, hook);
23070
23383
  }
23071
23384
  runPhaseHooks(phaseName, execution) {
23072
- const hooks = [...this.registeredHooks.keys()].filter((key) => key.startsWith(`${phaseName}:`)).map((key) => this.registeredHooks.get(key));
23073
- for (const hook of hooks) execution(hook);
23385
+ this.hooksManager.runPhaseHooks(phaseName, execution);
23074
23386
  }
23075
23387
  getHook(hookName) {
23076
- return this.registeredHooks.get(hookName);
23388
+ return this.hooksManager.getHook(hookName);
23077
23389
  }
23078
23390
  unregisterHook(hookName) {
23079
- this.registeredHooks.delete(hookName);
23391
+ this.hooksManager.unregisterHook(hookName);
23392
+ }
23393
+ async acquireMutexLock({ nodeIds, operation }, action) {
23394
+ return await this.mutexManager.acquireMutexLock({
23395
+ nodeIds,
23396
+ operation
23397
+ }, action);
23398
+ }
23399
+ setMutexLock({ nodeIds, operation, metadata }) {
23400
+ return this.mutexManager.setMutexLock({
23401
+ nodeIds,
23402
+ operation,
23403
+ metadata
23404
+ });
23405
+ }
23406
+ releaseMutexLock() {
23407
+ this.mutexManager.releaseMutexLock();
23408
+ }
23409
+ getLockDetails(lockId) {
23410
+ return this.mutexManager.getUserMutexLock(lockId);
23411
+ }
23412
+ getNodeMutexLock(nodeId) {
23413
+ return this.mutexManager.getNodeMutexLock(nodeId);
23080
23414
  }
23081
23415
  };
23082
23416
 
@@ -23225,11 +23559,15 @@ var WeaveLayerNode = class extends WeaveNode {
23225
23559
  if (!handler) continue;
23226
23560
  childrenMapped.push(handler.serialize(node));
23227
23561
  }
23562
+ const cleanedAttrs = { ...attrs };
23563
+ delete cleanedAttrs.mutexLocked;
23564
+ delete cleanedAttrs.mutexUserId;
23565
+ delete cleanedAttrs.draggable;
23228
23566
  return {
23229
23567
  key: attrs.id ?? "",
23230
23568
  type: attrs.nodeType,
23231
23569
  props: {
23232
- ...attrs,
23570
+ ...cleanedAttrs,
23233
23571
  id: attrs.id ?? "",
23234
23572
  nodeType: attrs.nodeType,
23235
23573
  children: childrenMapped
@@ -23302,11 +23640,15 @@ var WeaveGroupNode = class extends WeaveNode {
23302
23640
  if (!handler) continue;
23303
23641
  childrenMapped.push(handler.serialize(node));
23304
23642
  }
23643
+ const cleanedAttrs = { ...attrs };
23644
+ delete cleanedAttrs.mutexLocked;
23645
+ delete cleanedAttrs.mutexUserId;
23646
+ delete cleanedAttrs.draggable;
23305
23647
  return {
23306
23648
  key: attrs.id ?? "",
23307
23649
  type: attrs.nodeType,
23308
23650
  props: {
23309
- ...attrs,
23651
+ ...cleanedAttrs,
23310
23652
  id: attrs.id ?? "",
23311
23653
  nodeType: attrs.nodeType,
23312
23654
  sceneFunc: void 0,
@@ -23847,10 +24189,14 @@ var WeaveTextNode = class extends WeaveNode {
23847
24189
  this.textArea = null;
23848
24190
  }
23849
24191
  updateNode(nodeInstance) {
23850
- const clonedText = nodeInstance.clone();
23851
- clonedText.setAttr("triggerEditMode", void 0);
23852
- this.instance.updateNode(this.serialize(clonedText));
23853
- clonedText.destroy();
24192
+ const actNode = this.instance.getStage().findOne(`#${nodeInstance.id()}`);
24193
+ if (actNode) {
24194
+ const clonedText = actNode.clone();
24195
+ clonedText.setAttr("triggerEditMode", void 0);
24196
+ clonedText.setAttr("cancelEditMode", void 0);
24197
+ this.instance.updateNode(this.serialize(clonedText));
24198
+ clonedText.destroy();
24199
+ }
23854
24200
  }
23855
24201
  handleKeyPress = (e) => {
23856
24202
  if (e.code === "Enter" && this.instance.getActiveAction() === SELECTION_TOOL_ACTION_NAME && !this.editing && e.target !== this.textArea) {
@@ -23914,7 +24260,7 @@ var WeaveTextNode = class extends WeaveNode {
23914
24260
  text.on("transformstart", (e) => {
23915
24261
  this.instance.emitEvent("onTransform", e.target);
23916
24262
  });
23917
- text.on("transform", (0, import_lodash.throttle)(handleTextTransform, 50));
24263
+ text.on("transform", (0, import_lodash.throttle)(handleTextTransform, DEFAULT_THROTTLE_MS));
23918
24264
  text.on("transformend", () => {
23919
24265
  this.instance.emitEvent("onTransform", null);
23920
24266
  });
@@ -23941,6 +24287,9 @@ var WeaveTextNode = class extends WeaveNode {
23941
24287
  }
23942
24288
  });
23943
24289
  text.setAttr("triggerEditMode", this.triggerEditMode.bind(this));
24290
+ this.instance.addEventListener("onNodeRenderedAdded", (node) => {
24291
+ if (node.id() === text.id() && node.getParent() !== text.getParent()) text.getAttr("cancelEditMode")?.();
24292
+ });
23944
24293
  return text;
23945
24294
  }
23946
24295
  onUpdate(nodeInstance, nextProps) {
@@ -23980,8 +24329,11 @@ var WeaveTextNode = class extends WeaveNode {
23980
24329
  serialize(instance) {
23981
24330
  const attrs = instance.getAttrs();
23982
24331
  const cleanedAttrs = { ...attrs };
24332
+ delete cleanedAttrs.mutexLocked;
24333
+ delete cleanedAttrs.mutexUserId;
23983
24334
  delete cleanedAttrs.draggable;
23984
24335
  delete cleanedAttrs.triggerEditMode;
24336
+ delete cleanedAttrs.cancelEditMode;
23985
24337
  delete cleanedAttrs.measureMultilineText;
23986
24338
  return {
23987
24339
  key: attrs.id ?? "",
@@ -24137,6 +24489,13 @@ var WeaveTextNode = class extends WeaveNode {
24137
24489
  const correctionY = (actualFont === void 0 ? 0 : actualFont.offsetY ?? 0) * stage.scaleX();
24138
24490
  this.textArea.style.left = `${correctionX - 1}px`;
24139
24491
  this.textArea.style.top = `${correctionY}px`;
24492
+ const updateTextNode = () => {
24493
+ if (!this.textArea) return;
24494
+ updateTextNodeSize();
24495
+ textNode.text(this.textArea.value);
24496
+ textNode.visible(true);
24497
+ this.instance.updateNode(this.serialize(textNode));
24498
+ };
24140
24499
  this.textArea.onfocus = () => {
24141
24500
  this.textAreaDomResize(textNode);
24142
24501
  };
@@ -24148,9 +24507,11 @@ var WeaveTextNode = class extends WeaveNode {
24148
24507
  };
24149
24508
  this.textArea.onpaste = () => {
24150
24509
  this.textAreaDomResize(textNode);
24510
+ updateTextNode();
24151
24511
  };
24152
24512
  this.textArea.oninput = () => {
24153
24513
  this.textAreaDomResize(textNode);
24514
+ updateTextNode();
24154
24515
  };
24155
24516
  this.textAreaSuperContainer.addEventListener("scroll", () => {
24156
24517
  if (this.textAreaSuperContainer) {
@@ -24194,6 +24555,15 @@ var WeaveTextNode = class extends WeaveNode {
24194
24555
  return;
24195
24556
  }
24196
24557
  };
24558
+ const cancelEditMode = () => {
24559
+ textNode.setAttr("cancelEditMode", void 0);
24560
+ this.removeTextAreaDOM(textNode);
24561
+ this.instance.removeEventListener("onZoomChange", this.onZoomChangeHandler(textNode).bind(this));
24562
+ this.instance.removeEventListener("onStageMove", this.onStageMoveHandler(textNode).bind(this));
24563
+ window.removeEventListener("pointerup", handleOutsideClick);
24564
+ window.removeEventListener("pointerdown", handleOutsideClick);
24565
+ };
24566
+ textNode.setAttr("cancelEditMode", cancelEditMode.bind(this));
24197
24567
  const handleKeyUp = () => {
24198
24568
  if (!this.textArea) return;
24199
24569
  textNode.text(this.textArea.value);
@@ -24270,6 +24640,7 @@ var WeaveTextNode = class extends WeaveNode {
24270
24640
  else textNode.visible(true);
24271
24641
  }
24272
24642
  removeTextAreaDOM(textNode) {
24643
+ this.instance.releaseMutexLock();
24273
24644
  this.editing = false;
24274
24645
  const stage = this.instance.getStage();
24275
24646
  delete window.weaveTextEditing[textNode.id()];
@@ -24292,6 +24663,11 @@ var WeaveTextNode = class extends WeaveNode {
24292
24663
  this.instance.emitEvent("onExitTextNodeEditMode", { node: textNode });
24293
24664
  }
24294
24665
  triggerEditMode(textNode) {
24666
+ const lockAcquired = this.instance.setMutexLock({
24667
+ nodeIds: [textNode.id()],
24668
+ operation: "text-edit"
24669
+ });
24670
+ if (!lockAcquired) return;
24295
24671
  this.editing = true;
24296
24672
  textNode.visible(false);
24297
24673
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -24516,6 +24892,7 @@ var WeaveImageCrop = class WeaveImageCrop {
24516
24892
  const nodesSelectionPlugin = this.getNodesSelectionPlugin();
24517
24893
  if (nodesSelectionPlugin) nodesSelectionPlugin.enable();
24518
24894
  stage.mode(WEAVE_STAGE_DEFAULT_MODE);
24895
+ this.instance.releaseMutexLock();
24519
24896
  this.instance.emitEvent("onImageCropEnd", { instance: this.image });
24520
24897
  }
24521
24898
  drawGridLines(x, y, width, height) {
@@ -24697,6 +25074,11 @@ var WeaveImageNode = class extends WeaveNode {
24697
25074
  const stage = this.instance.getStage();
24698
25075
  if (imageNode.getAttrs().cropping ?? false) return;
24699
25076
  if (!(this.isSelecting() && this.isNodeSelected(imageNode))) return;
25077
+ const lockAcquired = this.instance.setMutexLock({
25078
+ nodeIds: [imageNode.id()],
25079
+ operation: "image-crop"
25080
+ });
25081
+ if (!lockAcquired) return;
24700
25082
  stage.mode("cropping");
24701
25083
  const image = stage.findOne(`#${imageNode.getAttrs().id}`);
24702
25084
  const internalImage = image?.findOne(`#${image.getAttrs().id}-image`);
@@ -24863,6 +25245,11 @@ var WeaveImageNode = class extends WeaveNode {
24863
25245
  this.loadImage(imageProps, image);
24864
25246
  }
24865
25247
  image.setAttr("imageURL", imageProps.imageURL);
25248
+ this.instance.addEventListener("onNodeRenderedAdded", (node) => {
25249
+ if (node.id() === image.id() && node.getParent() !== image.getParent()) {
25250
+ if (this.imageCrop) this.closeCrop(image, WEAVE_IMAGE_CROP_END_TYPE.CANCEL);
25251
+ }
25252
+ });
24866
25253
  return image;
24867
25254
  }
24868
25255
  onUpdate(nodeInstance, nextProps) {
@@ -25666,6 +26053,8 @@ var WeaveFrameNode = class extends WeaveNode {
25666
26053
  }
25667
26054
  const realAttrs = mainNode?.getAttrs();
25668
26055
  const cleanedAttrs = { ...realAttrs };
26056
+ delete cleanedAttrs.mutexLocked;
26057
+ delete cleanedAttrs.mutexUserId;
25669
26058
  delete cleanedAttrs.draggable;
25670
26059
  delete cleanedAttrs.onTargetEnter;
25671
26060
  return {
@@ -25898,6 +26287,8 @@ var WeaveStrokeNode = class extends WeaveNode {
25898
26287
  serialize(instance) {
25899
26288
  const attrs = instance.getAttrs();
25900
26289
  const cleanedAttrs = { ...attrs };
26290
+ delete cleanedAttrs.mutexLocked;
26291
+ delete cleanedAttrs.mutexUserId;
25901
26292
  delete cleanedAttrs.draggable;
25902
26293
  delete cleanedAttrs.sceneFunc;
25903
26294
  delete cleanedAttrs.hitFunc;
@@ -29070,6 +29461,8 @@ var WeaveConnectorNode = class extends WeaveNode {
29070
29461
  serialize(instance) {
29071
29462
  const attrs = instance.getAttrs();
29072
29463
  const cleanedAttrs = { ...attrs };
29464
+ delete cleanedAttrs.mutexLocked;
29465
+ delete cleanedAttrs.mutexUserId;
29073
29466
  delete cleanedAttrs.draggable;
29074
29467
  delete cleanedAttrs.sceneFunc;
29075
29468
  delete cleanedAttrs.hitFunc;
@@ -29250,7 +29643,7 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29250
29643
  this.config.zoomSteps = [minimumZoom, ...this.config.zoomSteps];
29251
29644
  }
29252
29645
  };
29253
- mainLayer?.on("draw", (0, import_lodash.throttle)(handleDraw, 50));
29646
+ mainLayer?.on("draw", (0, import_lodash.throttle)(handleDraw, DEFAULT_THROTTLE_MS));
29254
29647
  this.setZoom(this.config.zoomSteps[this.actualStep]);
29255
29648
  }
29256
29649
  setZoom(scale, centered = true, pointer) {
@@ -29416,15 +29809,8 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29416
29809
  });
29417
29810
  this.setZoom(scale, false);
29418
29811
  }
29419
- fitToSelection(smartZoom = false) {
29420
- if (!this.enabled) return;
29812
+ fitToElements(box, smartZoom = false) {
29421
29813
  const stage = this.instance.getStage();
29422
- const selectionPlugin = this.getNodesSelectionPlugin();
29423
- if (!selectionPlugin) return;
29424
- const nodes = selectionPlugin.getTransformer().getNodes();
29425
- if (nodes.length === 0) return;
29426
- const box = getBoundingBox(selectionPlugin.getTransformer().getNodes(), { relativeTo: stage });
29427
- if (box.width === 0 || box.height === 0) return;
29428
29814
  const container = stage.container();
29429
29815
  const scale = stage.scale();
29430
29816
  const containerWidth = container.clientWidth;
@@ -29475,6 +29861,26 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29475
29861
  });
29476
29862
  this.setZoom(finalScale, false);
29477
29863
  }
29864
+ fitToNodes(nodes, smartZoom = false) {
29865
+ if (!this.enabled) return;
29866
+ const stage = this.instance.getStage();
29867
+ if (nodes.length === 0) return;
29868
+ const nodesInstances = nodes.map((nodeId) => this.instance.getStage().findOne(`#${nodeId}`)).filter((node) => node !== null);
29869
+ const box = getBoundingBox(nodesInstances, { relativeTo: stage });
29870
+ if (box.width === 0 || box.height === 0) return;
29871
+ this.fitToElements(box, smartZoom);
29872
+ }
29873
+ fitToSelection(smartZoom = false) {
29874
+ if (!this.enabled) return;
29875
+ const stage = this.instance.getStage();
29876
+ const selectionPlugin = this.getNodesSelectionPlugin();
29877
+ if (!selectionPlugin) return;
29878
+ const nodes = selectionPlugin.getTransformer().getNodes();
29879
+ if (nodes.length === 0) return;
29880
+ const box = getBoundingBox(selectionPlugin.getTransformer().getNodes(), { relativeTo: stage });
29881
+ if (box.width === 0 || box.height === 0) return;
29882
+ this.fitToElements(box, smartZoom);
29883
+ }
29478
29884
  enable() {
29479
29885
  this.enabled = true;
29480
29886
  }
@@ -29596,7 +30002,7 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29596
30002
  requestAnimationFrame(this.zoomTick.bind(this));
29597
30003
  }
29598
30004
  };
29599
- const throttledHandleWheel = (0, import_lodash.throttle)(handleWheel, 30);
30005
+ const throttledHandleWheel = (0, import_lodash.throttle)(handleWheel, DEFAULT_THROTTLE_MS);
29600
30006
  window.addEventListener("wheel", throttledHandleWheel, { passive: true });
29601
30007
  }
29602
30008
  getInertiaScale() {
@@ -32053,12 +32459,12 @@ var WeaveArrowToolAction = class extends WeaveAction {
32053
32459
  this.instance.addNode(finalArrow, this.container?.getAttrs().id);
32054
32460
  this.instance.emitEvent("onAddedArrow");
32055
32461
  }
32056
- }
32057
- const selectionPlugin = this.instance.getPlugin("nodesSelection");
32058
- if (selectionPlugin) {
32059
- const node = stage.findOne(`#${this.arrowId}`);
32060
- if (node) selectionPlugin.setSelectedNodes([node]);
32061
- this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
32462
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
32463
+ if (selectionPlugin) {
32464
+ const node = stage.findOne(`#${this.arrowId}`);
32465
+ if (node) selectionPlugin.setSelectedNodes([node]);
32466
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
32467
+ }
32062
32468
  }
32063
32469
  stage.container().style.cursor = "default";
32064
32470
  this.initialCursor = null;
@@ -33931,7 +34337,7 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
33931
34337
  if (!this.enabled || !(this.isSpaceKeyPressed || this.isMouseMiddleButtonPressed || this.moveToolActive)) return;
33932
34338
  this.onRender();
33933
34339
  };
33934
- stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, 50));
34340
+ stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, DEFAULT_THROTTLE_MS));
33935
34341
  stage.on("pointermove", () => {
33936
34342
  if (this.enabled) this.onRender();
33937
34343
  });
@@ -34238,7 +34644,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
34238
34644
  lastPos = pos;
34239
34645
  this.instance.emitEvent("onStageMove");
34240
34646
  };
34241
- stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, 50));
34647
+ stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, DEFAULT_THROTTLE_MS));
34242
34648
  stage.on("pointerup", (e) => {
34243
34649
  this.pointers.delete(e.evt.pointerId);
34244
34650
  this.isMouseLeftButtonPressed = false;
@@ -34264,7 +34670,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
34264
34670
  stage.y(stage.y() - e.deltaY);
34265
34671
  this.instance.emitEvent("onStageMove");
34266
34672
  };
34267
- const handleWheelThrottled = (0, import_lodash.throttle)(handleWheel, 20);
34673
+ const handleWheelThrottled = (0, import_lodash.throttle)(handleWheel, WEAVE_STAGE_PANNING_THROTTLE_MS);
34268
34674
  window.addEventListener("wheel", handleWheelThrottled, { passive: true });
34269
34675
  stage.on("dragstart", (e) => {
34270
34676
  const duration = 1e3 / 60;
@@ -34506,7 +34912,7 @@ var WeaveStageMinimapPlugin = class extends WeavePlugin {
34506
34912
  const throttledUpdateMinimap = (0, import_lodash.throttle)(async () => {
34507
34913
  await this.updateMinimapContent();
34508
34914
  this.updateMinimapViewportReference();
34509
- }, 100);
34915
+ }, DEFAULT_THROTTLE_MS);
34510
34916
  this.instance.addEventListener("onStateChange", throttledUpdateMinimap);
34511
34917
  if (this.instance.isServerSide()) return;
34512
34918
  const workerPath = new URL("./stage-minimap.worker.js", import.meta.url);
@@ -34600,7 +35006,7 @@ var WeaveStageResizePlugin = class extends WeavePlugin {
34600
35006
  onInit() {
34601
35007
  const throttledResize = (0, import_lodash.throttle)(() => {
34602
35008
  this.resizeStage();
34603
- }, 100);
35009
+ }, DEFAULT_THROTTLE_MS);
34604
35010
  window.addEventListener("resize", () => {
34605
35011
  throttledResize();
34606
35012
  });
@@ -34787,11 +35193,6 @@ var WeaveNodesMultiSelectionFeedbackPlugin = class extends WeavePlugin {
34787
35193
  }
34788
35194
  };
34789
35195
 
34790
- //#endregion
34791
- //#region src/plugins/connected-users/constants.ts
34792
- const WEAVE_CONNECTED_USERS_KEY = "connectedUsers";
34793
- const WEAVE_CONNECTED_USER_INFO_KEY = "userInfo";
34794
-
34795
35196
  //#endregion
34796
35197
  //#region src/plugins/connected-users/connected-users.ts
34797
35198
  var WeaveConnectedUsersPlugin = class extends WeavePlugin {
@@ -35007,7 +35408,7 @@ const WEAVE_DEFAULT_USER_INFO_FUNCTION = () => ({
35007
35408
  email: "unknown@domain.com"
35008
35409
  });
35009
35410
  const WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS = {
35010
- awarenessThrottleMs: 100,
35411
+ awarenessThrottleMs: DEFAULT_THROTTLE_MS,
35011
35412
  ui: {
35012
35413
  separation: 8,
35013
35414
  pointer: {
@@ -35020,8 +35421,10 @@ const WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS = {
35020
35421
  backgroundCornerRadius: 0,
35021
35422
  backgroundPaddingX: 8,
35022
35423
  backgroundPaddingY: 4
35023
- }
35024
- }
35424
+ },
35425
+ operationSeparation: 4
35426
+ },
35427
+ getOperationName: (operation) => operation
35025
35428
  };
35026
35429
 
35027
35430
  //#endregion
@@ -35035,6 +35438,7 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35035
35438
  this.config.getUserBackgroundColor = memoize(this.config.getUserBackgroundColor);
35036
35439
  this.config.getUserForegroundColor = memoize(this.config.getUserForegroundColor);
35037
35440
  this.usersPointers = {};
35441
+ this.usersOperations = {};
35038
35442
  }
35039
35443
  getName() {
35040
35444
  return WEAVE_USERS_POINTERS_KEY;
@@ -35091,6 +35495,16 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35091
35495
  };
35092
35496
  const throttledHandleOnPointerMove = (0, import_lodash.throttle)(handleOnPointerMove, this.config.awarenessThrottleMs);
35093
35497
  stage.on("pointermove", throttledHandleOnPointerMove);
35498
+ const handleUsersLocksChange = ({ locks }) => {
35499
+ const actUsersLocks = {};
35500
+ for (const lockKey of locks) {
35501
+ const mutexInfo = this.instance?.getLockDetails(lockKey);
35502
+ if (mutexInfo) actUsersLocks[lockKey] = mutexInfo;
35503
+ }
35504
+ this.usersOperations = actUsersLocks;
35505
+ this.renderPointers();
35506
+ };
35507
+ this.instance.addEventListener("onMutexLockChange", handleUsersLocksChange);
35094
35508
  this.renderPointers();
35095
35509
  }
35096
35510
  sendAwarenessUpdate(mousePos) {
@@ -35124,7 +35538,8 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35124
35538
  scaleY: 1 / stage.scaleY()
35125
35539
  });
35126
35540
  userPointerNode.moveToTop();
35127
- const { separation, pointer: { circleRadius, circleStrokeWidth }, name: { fontFamily, fontSize, backgroundCornerRadius, backgroundPaddingX, backgroundPaddingY } } = this.config.ui;
35541
+ const { separation, pointer: { circleRadius, circleStrokeWidth }, name: { fontFamily, fontSize, backgroundCornerRadius, backgroundPaddingX, backgroundPaddingY }, operationSeparation } = this.config.ui;
35542
+ const getOperationName = this.config.getOperationName;
35128
35543
  const userBackgroundColor = this.config.getUserBackgroundColor(userPointer.rawUser);
35129
35544
  const userForegroundColor = this.config.getUserForegroundColor(userPointer.rawUser);
35130
35545
  const userPointNode = new Konva.Circle({
@@ -35174,6 +35589,41 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35174
35589
  userPointerNode.add(userPointNode);
35175
35590
  userPointerNode.add(userNameBackground);
35176
35591
  userPointerNode.add(userNameNode);
35592
+ if (this.usersOperations[userPointer.user]) {
35593
+ const userOperationNode = new Konva.Text({
35594
+ id: `pointer_${userPointer.user}_userPointOperation`,
35595
+ x: separation,
35596
+ y: -circleRadius * 2 + backgroundPaddingY + operationSeparation + textHeight + backgroundPaddingY * 2,
35597
+ text: getOperationName(this.usersOperations[userPointer.user].operation),
35598
+ fontSize,
35599
+ fontFamily,
35600
+ lineHeight: .9,
35601
+ fill: userForegroundColor,
35602
+ align: "center",
35603
+ verticalAlign: "middle",
35604
+ draggable: false,
35605
+ listening: false,
35606
+ strokeScaleEnabled: false,
35607
+ ellipsis: true
35608
+ });
35609
+ const textOperationWidth = userOperationNode.getTextWidth();
35610
+ const textOperationHeight = userOperationNode.getTextHeight();
35611
+ userOperationNode.width(textOperationWidth + backgroundPaddingX * 2);
35612
+ userOperationNode.height(textOperationHeight + backgroundPaddingY * 2);
35613
+ const userOperationBackground = new Konva.Rect({
35614
+ id: `pointer_${userPointer.user}_userPointOperationRect`,
35615
+ x: separation,
35616
+ y: -backgroundPaddingY + 4 + userNameBackground.height(),
35617
+ width: textOperationWidth + backgroundPaddingX * 2,
35618
+ height: textOperationHeight + backgroundPaddingY * 2,
35619
+ cornerRadius: backgroundCornerRadius,
35620
+ fill: userBackgroundColor,
35621
+ draggable: false,
35622
+ listening: false
35623
+ });
35624
+ userPointerNode.add(userOperationBackground);
35625
+ userPointerNode.add(userOperationNode);
35626
+ }
35177
35627
  pointersLayer?.add(userPointerNode);
35178
35628
  }
35179
35629
  const selectors = pointersLayer?.find(".selector") ?? [];
@@ -35189,6 +35639,78 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35189
35639
  }
35190
35640
  };
35191
35641
 
35642
+ //#endregion
35643
+ //#region src/plugins/users-presence/users-presence.ts
35644
+ var WeaveUsersPresencePlugin = class extends WeavePlugin {
35645
+ userPresence = {};
35646
+ onRender = void 0;
35647
+ constructor(params) {
35648
+ super();
35649
+ const { config } = params;
35650
+ this.config = mergeExceptArrays(WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, config);
35651
+ this.userPresence = {};
35652
+ }
35653
+ getName() {
35654
+ return WEAVE_USERS_PRESENCE_PLUGIN_KEY;
35655
+ }
35656
+ registerHooks() {
35657
+ this.instance.registerHook("onPresenceUpdate:usersPresencePlugin", ({ node, presenceData }) => {
35658
+ const nodeHandler = this.instance.getNodeHandler(node.getAttrs().nodeType);
35659
+ const newProps = {
35660
+ ...node.getAttrs(),
35661
+ ...presenceData
35662
+ };
35663
+ nodeHandler?.onUpdate(node, newProps);
35664
+ });
35665
+ }
35666
+ onInit() {
35667
+ const stage = this.instance.getStage();
35668
+ this.registerHooks();
35669
+ this.instance.addEventListener("onAwarenessChange", (changes) => {
35670
+ for (const change of changes) {
35671
+ if (!change[WEAVE_USER_PRESENCE_KEY]) continue;
35672
+ const userPresence = change[WEAVE_USER_PRESENCE_KEY];
35673
+ const nodes = Object.keys(userPresence);
35674
+ if (nodes.length === 0) continue;
35675
+ for (const nodeId of nodes) {
35676
+ const presenceInfo = userPresence[nodeId];
35677
+ if (this.config.getUser().id === presenceInfo.userId) continue;
35678
+ const nodeInstance = stage.findOne(`#${presenceInfo.nodeId}`);
35679
+ if (nodeInstance) this.instance.runPhaseHooks("onPresenceUpdate", (hook) => {
35680
+ hook({
35681
+ node: nodeInstance,
35682
+ presenceData: presenceInfo.attrs
35683
+ });
35684
+ });
35685
+ }
35686
+ }
35687
+ });
35688
+ }
35689
+ sendPresence() {
35690
+ const store = this.instance.getStore();
35691
+ store.setAwarenessInfo(WEAVE_USER_PRESENCE_KEY, this.userPresence);
35692
+ }
35693
+ setPresence(nodeId, attrs) {
35694
+ const userInfo = this.config.getUser();
35695
+ this.userPresence[nodeId] = {
35696
+ userId: userInfo.id,
35697
+ nodeId,
35698
+ attrs
35699
+ };
35700
+ this.sendPresence();
35701
+ }
35702
+ removePresence(nodeId) {
35703
+ if (this.userPresence[nodeId]) delete this.userPresence[nodeId];
35704
+ this.sendPresence();
35705
+ }
35706
+ enable() {
35707
+ this.enabled = true;
35708
+ }
35709
+ disable() {
35710
+ this.enabled = false;
35711
+ }
35712
+ };
35713
+
35192
35714
  //#endregion
35193
35715
  //#region src/plugins/stage-drop-area/constants.ts
35194
35716
  const WEAVE_STAGE_DROP_AREA_KEY = "stageDropArea";
@@ -36336,5 +36858,5 @@ const setupCanvasBackend = async () => {
36336
36858
  };
36337
36859
 
36338
36860
  //#endregion
36339
- export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, ARROW_TOOL_ACTION_NAME, ARROW_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_LINE_DEFAULT_CONFIG, GUIDE_ENTER_SNAPPING_TOLERANCE, GUIDE_EXIT_SNAPPING_TOLERANCE, GUIDE_HORIZONTAL_LINE_NAME, GUIDE_LINE_DEFAULT_CONFIG, GUIDE_LINE_DRAG_SNAPPING_THRESHOLD, GUIDE_LINE_NAME, GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD, GUIDE_ORIENTATION, GUIDE_VERTICAL_LINE_NAME, IMAGE_TOOL_ACTION_NAME, IMAGE_TOOL_STATE, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, NODE_SNAP, NODE_SNAP_HORIZONTAL, NODE_SNAP_VERTICAL, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_COLOR, WEAVE_GRID_DEFAULT_DOT_MAX_DOTS_PER_AXIS, WEAVE_GRID_DEFAULT_MAJOR_DOT_RATIO, WEAVE_GRID_DEFAULT_MAJOR_EVERY, WEAVE_GRID_DEFAULT_MAJOR_LINE_RATIO, WEAVE_GRID_DEFAULT_ORIGIN_COLOR, WEAVE_GRID_DEFAULT_RADIUS, WEAVE_GRID_DEFAULT_SIZE, WEAVE_GRID_DEFAULT_STROKE, WEAVE_GRID_DEFAULT_TYPE, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveImageNode, WeaveImageToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesDistanceSnappingPlugin, WeaveNodesEdgeSnappingPlugin, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStore, WeaveStrokeNode, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, getBoundingBox, getExportBoundingBox, getPositionRelativeToContainerOnPosition, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isIOS, isInShadowDOM, isNodeInSelection, isServer, memoize, mergeExceptArrays, moveNodeToContainer, resetScale, setupCanvasBackend, setupSkiaBackend };
36861
+ export { ALIGN_NODES_ALIGN_TO, ALIGN_NODES_TOOL_ACTION_NAME, ALIGN_NODES_TOOL_STATE, ARROW_TOOL_ACTION_NAME, ARROW_TOOL_STATE, BRUSH_TOOL_ACTION_NAME, BRUSH_TOOL_DEFAULT_CONFIG, BRUSH_TOOL_STATE, CONNECTOR_TOOL_ACTION_NAME, CONNECTOR_TOOL_DEFAULT_CONFIG, CONNECTOR_TOOL_STATE, COPY_PASTE_NODES_PLUGIN_STATE, ELLIPSE_TOOL_ACTION_NAME, ELLIPSE_TOOL_STATE, ERASER_TOOL_ACTION_NAME, ERASER_TOOL_STATE, FRAME_TOOL_ACTION_NAME, FRAME_TOOL_STATE, GUIDE_DISTANCE_LINE_DEFAULT_CONFIG, GUIDE_ENTER_SNAPPING_TOLERANCE, GUIDE_EXIT_SNAPPING_TOLERANCE, GUIDE_HORIZONTAL_LINE_NAME, GUIDE_LINE_DEFAULT_CONFIG, GUIDE_LINE_DRAG_SNAPPING_THRESHOLD, GUIDE_LINE_NAME, GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD, GUIDE_ORIENTATION, GUIDE_VERTICAL_LINE_NAME, IMAGE_TOOL_ACTION_NAME, IMAGE_TOOL_STATE, LINE_TOOL_ACTION_NAME, LINE_TOOL_DEFAULT_CONFIG, LINE_TOOL_STATE, MEASURE_TOOL_ACTION_NAME, MEASURE_TOOL_STATE, MOVE_TOOL_ACTION_NAME, MOVE_TOOL_STATE, NODE_SNAP, NODE_SNAP_HORIZONTAL, NODE_SNAP_VERTICAL, PEN_TOOL_ACTION_NAME, PEN_TOOL_STATE, RECTANGLE_TOOL_ACTION_NAME, RECTANGLE_TOOL_STATE, REGULAR_POLYGON_TOOL_ACTION_NAME, REGULAR_POLYGON_TOOL_STATE, SELECTION_TOOL_ACTION_NAME, SELECTION_TOOL_STATE, STAGE_MINIMAP_DEFAULT_CONFIG, STAR_TOOL_ACTION_NAME, STAR_TOOL_STATE, TEXT_LAYOUT, TEXT_TOOL_ACTION_NAME, TEXT_TOOL_STATE, VIDEO_TOOL_ACTION_NAME, VIDEO_TOOL_STATE, WEAVE_ARROW_NODE_TYPE, WEAVE_COMMENTS_RENDERER_KEY, WEAVE_COMMENTS_TOOL_LAYER_ID, WEAVE_COMMENT_CREATE_ACTION, WEAVE_COMMENT_NODE_ACTION, WEAVE_COMMENT_NODE_DEFAULTS, WEAVE_COMMENT_NODE_TYPE, WEAVE_COMMENT_STATUS, WEAVE_COMMENT_TOOL_ACTION_NAME, WEAVE_COMMENT_TOOL_DEFAULT_CONFIG, WEAVE_COMMENT_TOOL_STATE, WEAVE_COMMENT_VIEW_ACTION, WEAVE_CONNECTOR_NODE_ANCHOR_ORIGIN, WEAVE_CONNECTOR_NODE_DECORATOR_TYPE, WEAVE_CONNECTOR_NODE_DEFAULT_CONFIG, WEAVE_CONNECTOR_NODE_LINE_ORIGIN, WEAVE_CONNECTOR_NODE_LINE_TYPE, WEAVE_CONNECTOR_NODE_TYPE, WEAVE_COPY_PASTE_CONFIG_DEFAULT, WEAVE_COPY_PASTE_NODES_KEY, WEAVE_COPY_PASTE_PASTE_CATCHER_ID, WEAVE_COPY_PASTE_PASTE_MODES, WEAVE_DEFAULT_USER_INFO_FUNCTION, WEAVE_ELLIPSE_NODE_TYPE, WEAVE_FRAME_DEFAULT_BACKGROUND_COLOR, WEAVE_FRAME_NODE_DEFAULT_CONFIG, WEAVE_FRAME_NODE_DEFAULT_PROPS, WEAVE_FRAME_NODE_TYPE, WEAVE_GRID_DEFAULT_COLOR, WEAVE_GRID_DEFAULT_DOT_MAX_DOTS_PER_AXIS, WEAVE_GRID_DEFAULT_MAJOR_DOT_RATIO, WEAVE_GRID_DEFAULT_MAJOR_EVERY, WEAVE_GRID_DEFAULT_MAJOR_LINE_RATIO, WEAVE_GRID_DEFAULT_ORIGIN_COLOR, WEAVE_GRID_DEFAULT_RADIUS, WEAVE_GRID_DEFAULT_SIZE, WEAVE_GRID_DEFAULT_STROKE, WEAVE_GRID_DEFAULT_TYPE, WEAVE_GRID_LAYER_ID, WEAVE_GRID_TYPES, WEAVE_GROUP_NODE_TYPE, WEAVE_IMAGE_CROP_END_TYPE, WEAVE_IMAGE_DEFAULT_CONFIG, WEAVE_IMAGE_NODE_TYPE, WEAVE_LAYER_NODE_TYPE, WEAVE_LINE_NODE_DEFAULT_CONFIG, WEAVE_LINE_NODE_TYPE, WEAVE_MEASURE_NODE_DEFAULT_CONFIG, WEAVE_MEASURE_NODE_TYPE, WEAVE_MEASURE_TOOL_DEFAULT_CONFIG, WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY, WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_LAYER_ID, WEAVE_NODES_SELECTION_DEFAULT_CONFIG, WEAVE_NODES_SELECTION_KEY, WEAVE_NODES_SELECTION_LAYER_ID, WEAVE_RECTANGLE_NODE_TYPE, WEAVE_REGULAR_POLYGON_NODE_TYPE, WEAVE_STAGE_DEFAULT_MODE, WEAVE_STAGE_GRID_PLUGIN_KEY, WEAVE_STAGE_KEYBOARD_MOVE_DEFAULT_CONFIG, WEAVE_STAGE_KEYBOARD_MOVE_KEY, WEAVE_STAGE_MINIMAP_KEY, WEAVE_STAGE_NODE_TYPE, WEAVE_STAGE_PANNING_DEFAULT_CONFIG, WEAVE_STAGE_PANNING_KEY, WEAVE_STAGE_PANNING_THROTTLE_MS, WEAVE_STAR_NODE_TYPE, WEAVE_STROKE_NODE_DEFAULT_CONFIG, WEAVE_STROKE_NODE_TYPE, WEAVE_TEXT_NODE_TYPE, WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS, WEAVE_USERS_POINTERS_KEY, WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, WEAVE_USERS_PRESENCE_PLUGIN_KEY, WEAVE_USERS_SELECTION_KEY, WEAVE_USER_POINTER_KEY, WEAVE_USER_PRESENCE_KEY, WEAVE_USER_SELECTION_KEY, WEAVE_VIDEO_DEFAULT_CONFIG, WEAVE_VIDEO_NODE_TYPE, Weave, WeaveAction, WeaveAlignNodesToolAction, WeaveArrowNode, WeaveArrowToolAction, WeaveBrushToolAction, WeaveCommentNode, WeaveCommentToolAction, WeaveCommentsRendererPlugin, WeaveConnectedUsersPlugin, WeaveConnectorNode, WeaveConnectorToolAction, WeaveContextMenuPlugin, WeaveCopyPasteNodesPlugin, WeaveEllipseNode, WeaveEllipseToolAction, WeaveEraserToolAction, WeaveExportNodesToolAction, WeaveExportStageToolAction, WeaveFitToScreenToolAction, WeaveFitToSelectionToolAction, WeaveFrameNode, WeaveFrameToolAction, WeaveGroupNode, WeaveImageNode, WeaveImageToolAction, WeaveLayerNode, WeaveLineNode, WeaveLineToolAction, WeaveMeasureNode, WeaveMeasureToolAction, WeaveMoveToolAction, WeaveNode, WeaveNodesDistanceSnappingPlugin, WeaveNodesEdgeSnappingPlugin, WeaveNodesMultiSelectionFeedbackPlugin, WeaveNodesSelectionPlugin, WeavePenToolAction, WeavePlugin, WeaveRectangleNode, WeaveRectangleToolAction, WeaveRegularPolygonNode, WeaveRegularPolygonToolAction, WeaveSelectionToolAction, WeaveStageDropAreaPlugin, WeaveStageGridPlugin, WeaveStageKeyboardMovePlugin, WeaveStageMinimapPlugin, WeaveStageNode, WeaveStagePanningPlugin, WeaveStageResizePlugin, WeaveStageZoomPlugin, WeaveStarNode, WeaveStarToolAction, WeaveStore, WeaveStrokeNode, WeaveTextNode, WeaveTextToolAction, WeaveUsersPointersPlugin, WeaveUsersPresencePlugin, WeaveUsersSelectionPlugin, WeaveVideoNode, WeaveVideoToolAction, WeaveZoomInToolAction, WeaveZoomOutToolAction, canComposite, clearContainerTargets, containerOverCursor, containsNodeDeep, defaultInitialState, getBoundingBox, getExportBoundingBox, getPositionRelativeToContainerOnPosition, getSelectedNodesMetadata, getStageClickPoint, getTargetAndSkipNodes, getTargetedNode, getTopmostShadowHost, getVisibleNodes, getVisibleNodesInViewport, hasFrames, hasImages, intersectArrays, isIOS, isInShadowDOM, isNodeInSelection, isServer, memoize, mergeExceptArrays, moveNodeToContainer, resetScale, setupCanvasBackend, setupSkiaBackend };
36340
36862
  //# sourceMappingURL=sdk.node.js.map