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