@inditextech/weave-sdk 2.12.1 → 2.13.1

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";
@@ -17998,6 +17998,16 @@ var WeaveContextMenuPlugin = class extends WeavePlugin {
17998
17998
  };
17999
17999
  });
18000
18000
  if (this.contextMenuVisible) this.closeContextMenu();
18001
+ let allNodesUnlocked = true;
18002
+ const actUser = this.instance.getStore().getUser();
18003
+ for (const node of nodes) {
18004
+ const mutexInfo = this.instance.getNodeMutexLock(node.node?.key ?? "");
18005
+ if (mutexInfo && mutexInfo.user.id !== actUser.id) {
18006
+ allNodesUnlocked = false;
18007
+ break;
18008
+ }
18009
+ }
18010
+ if (!allNodesUnlocked) return;
18001
18011
  if (selectionPlugin && !(eventTarget.getParent() instanceof Konva.Transformer && selectionPlugin.getSelectedNodes().length > 0)) {
18002
18012
  selectionPlugin.setSelectedNodes([...nodes.map((node) => node.instance)]);
18003
18013
  selectionPlugin.getHoverTransformer().nodes([]);
@@ -18005,7 +18015,7 @@ var WeaveContextMenuPlugin = class extends WeavePlugin {
18005
18015
  const containerRect = stage.container().getBoundingClientRect();
18006
18016
  const pointerPos = stage.getPointerPosition();
18007
18017
  const relativeClickPoint = stage.getRelativePointerPosition();
18008
- if (containerRect && pointerPos && relativeClickPoint) {
18018
+ if (containerRect && pointerPos && relativeClickPoint && allNodesUnlocked) {
18009
18019
  const contextMenuPoint = {
18010
18020
  x: containerRect.left + pointerPos.x + (this.config.xOffset ?? 4),
18011
18021
  y: containerRect.top + pointerPos.y + (this.config.yOffset ?? 4)
@@ -18562,6 +18572,7 @@ const WEAVE_GRID_LAYER_ID = "gridLayer";
18562
18572
  //#endregion
18563
18573
  //#region src/plugins/stage-panning/constants.ts
18564
18574
  const WEAVE_STAGE_PANNING_KEY = "stagePanning";
18575
+ const WEAVE_STAGE_PANNING_THROTTLE_MS = 20;
18565
18576
  const WEAVE_STAGE_PANNING_DEFAULT_CONFIG = {
18566
18577
  edgePanOffset: 50,
18567
18578
  edgePanSpeed: 10
@@ -18577,6 +18588,16 @@ const WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_DEFAULT_CONFIG = { style: {
18577
18588
  fill: "transparent"
18578
18589
  } };
18579
18590
 
18591
+ //#endregion
18592
+ //#region src/constants.ts
18593
+ const DEFAULT_THROTTLE_MS = 50;
18594
+
18595
+ //#endregion
18596
+ //#region src/plugins/users-presence/constants.ts
18597
+ const WEAVE_USER_PRESENCE_KEY = "userPresence";
18598
+ const WEAVE_USERS_PRESENCE_PLUGIN_KEY = "usersPresence";
18599
+ const WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS = { awarenessThrottleMs: DEFAULT_THROTTLE_MS };
18600
+
18580
18601
  //#endregion
18581
18602
  //#region src/plugins/nodes-selection/nodes-selection.ts
18582
18603
  var WeaveNodesSelectionPlugin = class extends WeavePlugin {
@@ -18703,6 +18724,15 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18703
18724
  });
18704
18725
  tr.on("transformstart", () => {
18705
18726
  this.triggerSelectedNodesEvent();
18727
+ const selectedNodes = tr.nodes();
18728
+ for (const node of selectedNodes) if (node.getAttrs().strokeScaleEnabled !== false) {
18729
+ node.setAttr("strokeScaleEnabled", false);
18730
+ node.setAttr("_revertStrokeScaleEnabled", true);
18731
+ }
18732
+ if (this.getSelectedNodes().length > 1) this.instance.setMutexLock({
18733
+ nodeIds: selectedNodes.map((node) => node.id()),
18734
+ operation: "nodes-transform"
18735
+ });
18706
18736
  });
18707
18737
  let nodeHovered = void 0;
18708
18738
  tr.on("mousemove", () => {
@@ -18740,9 +18770,26 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18740
18770
  const moved = this.checkMoved(e);
18741
18771
  if (moved) this.getContextMenuPlugin()?.cancelLongPressTimer();
18742
18772
  this.triggerSelectedNodesEvent();
18773
+ if (this.getUsersPresencePlugin()) for (const node of tr.nodes()) this.getUsersPresencePlugin()?.setPresence(node.id(), {
18774
+ x: node.x(),
18775
+ y: node.y(),
18776
+ width: node.width(),
18777
+ height: node.height(),
18778
+ scaleX: node.scaleX(),
18779
+ scaleY: node.scaleY(),
18780
+ rotation: node.rotation(),
18781
+ strokeScaleEnabled: false
18782
+ });
18743
18783
  };
18744
- tr.on("transform", (0, import_throttle.default)(handleTransform, 50));
18784
+ tr.on("transform", (0, import_throttle.default)(handleTransform, DEFAULT_THROTTLE_MS));
18745
18785
  tr.on("transformend", () => {
18786
+ if (this.getSelectedNodes().length > 1) this.instance.releaseMutexLock();
18787
+ const selectedNodes = tr.nodes();
18788
+ for (const node of selectedNodes) {
18789
+ if (node.getAttrs()._revertStrokeScaleEnabled === true) node.setAttr("strokeScaleEnabled", true);
18790
+ node.setAttr("_revertStrokeScaleEnabled", void 0);
18791
+ if (this.getUsersPresencePlugin()) this.getUsersPresencePlugin()?.removePresence(node.id());
18792
+ }
18746
18793
  this.triggerSelectedNodesEvent();
18747
18794
  });
18748
18795
  let initialPos = null;
@@ -18776,6 +18823,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18776
18823
  }
18777
18824
  e.cancelBubble = true;
18778
18825
  tr.forceUpdate();
18826
+ if (this.getSelectedNodes().length > 1) this.instance.setMutexLock({
18827
+ nodeIds: selectedNodes.map((node) => node.id()),
18828
+ operation: "nodes-drag"
18829
+ });
18779
18830
  });
18780
18831
  const handleDragMove = (e) => {
18781
18832
  const actualPos = {
@@ -18808,6 +18859,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18808
18859
  if (this.isSelecting() && selectedNodes.length > 1) {
18809
18860
  clearContainerTargets(this.instance);
18810
18861
  const layerToMove = containerOverCursor(this.instance, selectedNodes);
18862
+ if (this.getUsersPresencePlugin()) for (const node of selectedNodes) this.getUsersPresencePlugin()?.setPresence(node.id(), {
18863
+ x: node.x(),
18864
+ y: node.y()
18865
+ });
18811
18866
  if (layerToMove && !selectionContainsFrames) layerToMove.fire(WEAVE_NODE_CUSTOM_EVENTS.onTargetEnter, { bubbles: true });
18812
18867
  }
18813
18868
  tr.forceUpdate();
@@ -18815,12 +18870,14 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
18815
18870
  tr.on("dragmove", handleDragMove);
18816
18871
  tr.on("dragend", (e) => {
18817
18872
  if (!this.didMove) return;
18873
+ if (this.getSelectedNodes().length > 1) this.instance.releaseMutexLock();
18818
18874
  e.cancelBubble = true;
18819
18875
  if (tr.nodes().length > 1) {
18820
18876
  const nodes$1 = tr.nodes();
18821
18877
  for (const node of nodes$1) {
18822
18878
  this.getNodesSelectionFeedbackPlugin()?.showSelectionHalo(node);
18823
18879
  this.getNodesSelectionFeedbackPlugin()?.updateSelectionHalo(node);
18880
+ this.getUsersPresencePlugin()?.removePresence(node.id());
18824
18881
  }
18825
18882
  }
18826
18883
  this.instance.getCloningManager().cleanupClones();
@@ -19194,6 +19251,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19194
19251
  stage.on("pointermove", handleMouseMove);
19195
19252
  this.panLoop();
19196
19253
  stage.on("pointerup", (e) => {
19254
+ const store = this.instance.getStore();
19255
+ const actUser = store.getUser();
19197
19256
  this.tr.setAttrs({ listening: true });
19198
19257
  this.selecting = false;
19199
19258
  this.stopPanLoop();
@@ -19258,6 +19317,8 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19258
19317
  const box = this.selectionRectangle.getClientRect();
19259
19318
  this.selectionRectangle.visible(false);
19260
19319
  const selected = shapes.filter((shape) => {
19320
+ const shapeMutex = this.instance.getNodeMutexLock(shape.id());
19321
+ if (shapeMutex && shapeMutex.user.id !== actUser.id) return false;
19261
19322
  let parent = this.instance.getInstanceRecursive(shape.getParent());
19262
19323
  if (parent.getAttrs().nodeId) parent = this.instance.getStage().findOne(`#${parent.getAttrs().nodeId}`);
19263
19324
  if (shape.getAttrs().nodeType && shape.getAttrs().nodeType === "frame") {
@@ -19360,7 +19421,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19360
19421
  return node.getAttrs().id === nodeTargeted.getAttrs().id;
19361
19422
  });
19362
19423
  const isSelected = nodeSelectedIndex !== -1;
19363
- if (nodeTargeted.getAttrs().locked) return;
19424
+ const user = this.instance.getStore().getUser();
19425
+ const isLocked = nodeTargeted.getAttrs().locked ?? false;
19426
+ const isMutexLocked = nodeTargeted.getAttrs().mutexLocked && nodeTargeted.getAttrs().mutexUserId !== user.id;
19427
+ if (isLocked || isMutexLocked) return;
19364
19428
  if (nodeTargeted.getAttrs().nodeId) {
19365
19429
  const realNode = stage.findOne(`#${nodeTargeted.getAttrs().nodeId}`);
19366
19430
  if (realNode) nodeTargeted = realNode;
@@ -19491,6 +19555,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
19491
19555
  const stagePanning = this.instance.getPlugin(WEAVE_STAGE_PANNING_KEY);
19492
19556
  return stagePanning;
19493
19557
  }
19558
+ getUsersPresencePlugin() {
19559
+ const usersPresencePlugin = this.instance.getPlugin(WEAVE_USERS_PRESENCE_PLUGIN_KEY);
19560
+ return usersPresencePlugin;
19561
+ }
19494
19562
  getSelectorConfig() {
19495
19563
  return this.config.selection;
19496
19564
  }
@@ -20112,6 +20180,25 @@ var WeaveNode = class {
20112
20180
  });
20113
20181
  return anchors;
20114
20182
  };
20183
+ node.lockMutex = function(user) {
20184
+ const actUser = actInstance.getStore().getUser();
20185
+ this.setAttrs({
20186
+ mutexLocked: true,
20187
+ mutexUserId: user.id
20188
+ });
20189
+ const selectionPlugin = actInstance.getPlugin("nodesSelection");
20190
+ if (selectionPlugin && actUser.id !== user.id) {
20191
+ const selectedNodes = selectionPlugin.getSelectedNodes();
20192
+ const filteredNodes = selectedNodes.filter((n) => n.getAttrs().id !== this.getAttrs().id);
20193
+ selectionPlugin.setSelectedNodes(filteredNodes);
20194
+ }
20195
+ };
20196
+ node.releaseMutex = function() {
20197
+ this.setAttrs({
20198
+ mutexLocked: false,
20199
+ mutexUserId: void 0
20200
+ });
20201
+ };
20115
20202
  }
20116
20203
  isNodeSelected(ele) {
20117
20204
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -20165,8 +20252,16 @@ var WeaveNode = class {
20165
20252
  let transforming = false;
20166
20253
  node.on("transformstart", (e) => {
20167
20254
  transforming = true;
20255
+ if (e.target.getAttrs().strokeScaleEnabled !== false) {
20256
+ e.target.setAttr("strokeScaleEnabled", false);
20257
+ e.target.setAttr("_revertStrokeScaleEnabled", true);
20258
+ }
20168
20259
  this.getNodesSelectionFeedbackPlugin()?.hideSelectionHalo(node);
20169
20260
  this.instance.emitEvent("onTransform", e.target);
20261
+ if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.setMutexLock({
20262
+ nodeIds: [e.target.id()],
20263
+ operation: "node-transform"
20264
+ });
20170
20265
  });
20171
20266
  const handleTransform = (e) => {
20172
20267
  const node$1 = e.target;
@@ -20174,11 +20269,24 @@ var WeaveNode = class {
20174
20269
  const nodesEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
20175
20270
  if (nodesSelectionPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSelectionPlugin.getTransformer().forceUpdate();
20176
20271
  if (nodesEdgeSnappingPlugin && transforming && this.isSelecting() && this.isNodeSelected(node$1)) nodesEdgeSnappingPlugin.evaluateGuidelines(e);
20272
+ this.getUsersPresencePlugin()?.setPresence(node$1.id(), {
20273
+ x: node$1.x(),
20274
+ y: node$1.y(),
20275
+ width: node$1.width(),
20276
+ height: node$1.height(),
20277
+ scaleX: node$1.scaleX(),
20278
+ scaleY: node$1.scaleY(),
20279
+ rotation: node$1.rotation(),
20280
+ strokeScaleEnabled: false
20281
+ });
20177
20282
  };
20178
- node.on("transform", (0, import_lodash.throttle)(handleTransform, 100));
20283
+ node.on("transform", (0, import_lodash.throttle)(handleTransform, DEFAULT_THROTTLE_MS));
20179
20284
  node.on("transformend", (e) => {
20180
20285
  const node$1 = e.target;
20181
- e.target.setAttr("strokeScaleEnabled", true);
20286
+ if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.releaseMutexLock();
20287
+ this.getUsersPresencePlugin()?.removePresence(node$1.id());
20288
+ if (e.target.getAttrs()._revertStrokeScaleEnabled === true) e.target.setAttr("strokeScaleEnabled", true);
20289
+ e.target.setAttr("_revertStrokeScaleEnabled", void 0);
20182
20290
  this.instance.emitEvent("onTransform", null);
20183
20291
  transforming = false;
20184
20292
  const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -20258,6 +20366,10 @@ var WeaveNode = class {
20258
20366
  clone?.startDrag(e.evt);
20259
20367
  });
20260
20368
  }
20369
+ if (this.getNodesSelectionPlugin()?.getSelectedNodes().length === 1) this.instance.setMutexLock({
20370
+ nodeIds: [e.target.id()],
20371
+ operation: "node-drag"
20372
+ });
20261
20373
  });
20262
20374
  const handleDragMove = (e) => {
20263
20375
  const nodeTarget = e.target;
@@ -20281,14 +20393,19 @@ var WeaveNode = class {
20281
20393
  const realNodeTarget = this.getRealSelectedNode(nodeTarget);
20282
20394
  if (this.isSelecting() && this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
20283
20395
  clearContainerTargets(this.instance);
20396
+ this.getUsersPresencePlugin()?.setPresence(realNodeTarget.id(), {
20397
+ x: realNodeTarget.x(),
20398
+ y: realNodeTarget.y()
20399
+ });
20284
20400
  const layerToMove = containerOverCursor(this.instance, [realNodeTarget]);
20285
20401
  if (layerToMove && !hasFrames(realNodeTarget) && realNodeTarget.isDragging() && !realNodeTarget.getAttrs().lockToContainer) layerToMove.fire(WEAVE_NODE_CUSTOM_EVENTS.onTargetEnter, { node: realNodeTarget });
20286
20402
  }
20287
20403
  };
20288
- node.on("dragmove", (0, import_lodash.throttle)(handleDragMove, 100));
20404
+ node.on("dragmove", (0, import_lodash.throttle)(handleDragMove, DEFAULT_THROTTLE_MS));
20289
20405
  node.on("dragend", (e) => {
20290
20406
  const nodeTarget = e.target;
20291
20407
  if (this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
20408
+ this.instance.releaseMutexLock();
20292
20409
  this.getNodesSelectionFeedbackPlugin()?.showSelectionHalo(nodeTarget);
20293
20410
  this.getNodesSelectionFeedbackPlugin()?.updateSelectionHalo(nodeTarget);
20294
20411
  }
@@ -20308,6 +20425,7 @@ var WeaveNode = class {
20308
20425
  }
20309
20426
  this.instance.emitEvent("onDrag", null);
20310
20427
  const realNodeTarget = this.getRealSelectedNode(nodeTarget);
20428
+ this.getUsersPresencePlugin()?.removePresence(realNodeTarget.id());
20311
20429
  if (this.getNodesSelectionPlugin()?.getSelectedNodes().length === 1 && realNodeTarget.getAttr("dragStartOpacity") !== void 0) {
20312
20430
  const originalNodeOpacity = realNodeTarget.getAttr("dragStartOpacity") ?? 1;
20313
20431
  realNodeTarget.setAttrs({ opacity: originalNodeOpacity });
@@ -20376,35 +20494,33 @@ var WeaveNode = class {
20376
20494
  }
20377
20495
  handleMouseOver(node) {
20378
20496
  const stage = this.instance.getStage();
20497
+ const user = this.instance.getStore().getUser();
20379
20498
  const activeAction = this.instance.getActiveAction();
20380
20499
  const isNodeSelectionEnabled = this.getSelectionPlugin()?.isEnabled();
20381
20500
  const realNode = this.instance.getInstanceRecursive(node);
20382
20501
  const isTargetable = node.getAttrs().isTargetable !== false;
20383
20502
  const isLocked = node.getAttrs().locked ?? false;
20503
+ const isMutexLocked = realNode.getAttrs().mutexLocked && realNode.getAttrs().mutexUserId !== user.id;
20384
20504
  if ([MOVE_TOOL_ACTION_NAME].includes(activeAction ?? "")) return false;
20385
20505
  let showHover = false;
20386
20506
  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";
20507
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && (isLocked || isMutexLocked)) {
20508
+ stage.container().style.cursor = "default";
20390
20509
  cancelBubble = true;
20391
20510
  }
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();
20511
+ if (isNodeSelectionEnabled && this.isSelecting() && !this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20394
20512
  showHover = true;
20395
- stage$1.container().style.cursor = "pointer";
20513
+ stage.container().style.cursor = "pointer";
20396
20514
  cancelBubble = true;
20397
20515
  }
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();
20516
+ if (isNodeSelectionEnabled && this.isSelecting() && this.isNodeSelected(realNode) && !this.isPasting() && isTargetable && !(isLocked || isMutexLocked) && stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
20400
20517
  showHover = true;
20401
- stage$1.container().style.cursor = "grab";
20518
+ stage.container().style.cursor = "grab";
20402
20519
  cancelBubble = true;
20403
20520
  }
20404
20521
  if (!isTargetable) cancelBubble = true;
20405
20522
  if (this.isPasting()) {
20406
- const stage$1 = this.instance.getStage();
20407
- stage$1.container().style.cursor = "crosshair";
20523
+ stage.container().style.cursor = "crosshair";
20408
20524
  cancelBubble = true;
20409
20525
  }
20410
20526
  if (showHover) this.setHoverState(realNode);
@@ -20435,6 +20551,8 @@ var WeaveNode = class {
20435
20551
  serialize(instance) {
20436
20552
  const attrs = instance.getAttrs();
20437
20553
  const cleanedAttrs = { ...attrs };
20554
+ delete cleanedAttrs.mutexLocked;
20555
+ delete cleanedAttrs.mutexUserId;
20438
20556
  delete cleanedAttrs.draggable;
20439
20557
  return {
20440
20558
  key: attrs.id ?? "",
@@ -20555,6 +20673,10 @@ var WeaveNode = class {
20555
20673
  const selectionFeedbackPlugin = this.instance.getPlugin(WEAVE_NODES_MULTI_SELECTION_FEEDBACK_PLUGIN_KEY);
20556
20674
  return selectionFeedbackPlugin;
20557
20675
  }
20676
+ getUsersPresencePlugin() {
20677
+ const usersPresencePlugin = this.instance.getPlugin(WEAVE_USERS_PRESENCE_PLUGIN_KEY);
20678
+ return usersPresencePlugin;
20679
+ }
20558
20680
  };
20559
20681
 
20560
20682
  //#endregion
@@ -21991,7 +22113,7 @@ var WeaveRegisterManager = class {
21991
22113
 
21992
22114
  //#endregion
21993
22115
  //#region package.json
21994
- var version = "2.12.1";
22116
+ var version = "2.13.1";
21995
22117
 
21996
22118
  //#endregion
21997
22119
  //#region src/managers/setup.ts
@@ -22470,7 +22592,163 @@ var WeavePluginsManager = class {
22470
22592
  };
22471
22593
 
22472
22594
  //#endregion
22473
- //#region src/watch-map.ts
22595
+ //#region src/plugins/connected-users/constants.ts
22596
+ const WEAVE_CONNECTED_USERS_KEY = "connectedUsers";
22597
+ const WEAVE_CONNECTED_USER_INFO_KEY = "userInfo";
22598
+
22599
+ //#endregion
22600
+ //#region src/managers/mutex/mutex.ts
22601
+ var WeaveMutexManager = class {
22602
+ userMutexLocked = new Map();
22603
+ nodeMutexLocked = new Map();
22604
+ WEAVE_USER_MUTEX_LOCK_KEY = "userMutexLock";
22605
+ constructor(instance) {
22606
+ this.instance = instance;
22607
+ this.logger = this.instance.getChildLogger("mutex-manager");
22608
+ this.logger.debug("Mutex manager created");
22609
+ this.init();
22610
+ }
22611
+ init() {
22612
+ this.setupMutexManager();
22613
+ }
22614
+ setupMutexManager() {
22615
+ this.instance.addEventListener("onConnectedUsersChange", (users) => {
22616
+ const actUser = this.instance.getStore().getUser();
22617
+ const userMutexKeys = Array.from(this.userMutexLocked.keys());
22618
+ for (const userMutexKey of userMutexKeys) if (actUser.id !== userMutexKey && !users[userMutexKey]) {
22619
+ const info = this.userMutexLocked.get(userMutexKey);
22620
+ if (info) {
22621
+ const user = info.user;
22622
+ this.releaseMutexLockRemote(user);
22623
+ }
22624
+ }
22625
+ });
22626
+ this.instance.addEventListener(
22627
+ "onAwarenessChange",
22628
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22629
+ (changes) => {
22630
+ const actUser = this.instance.getStore().getUser();
22631
+ for (const change of changes) {
22632
+ if (!change[this.WEAVE_USER_MUTEX_LOCK_KEY] && change[WEAVE_CONNECTED_USER_INFO_KEY] && actUser.id !== change[WEAVE_CONNECTED_USER_INFO_KEY].id) {
22633
+ const user = change[WEAVE_CONNECTED_USER_INFO_KEY];
22634
+ this.releaseMutexLockRemote(user);
22635
+ continue;
22636
+ }
22637
+ if (change[WEAVE_CONNECTED_USER_INFO_KEY] && actUser.id !== change[WEAVE_CONNECTED_USER_INFO_KEY].id) {
22638
+ const user = change[WEAVE_CONNECTED_USER_INFO_KEY];
22639
+ const mutexInfo = change[this.WEAVE_USER_MUTEX_LOCK_KEY];
22640
+ this.setMutexLockRemote({
22641
+ nodeIds: mutexInfo.nodeIds,
22642
+ operation: mutexInfo.operation,
22643
+ metadata: mutexInfo.metadata
22644
+ }, user);
22645
+ }
22646
+ }
22647
+ }
22648
+ );
22649
+ }
22650
+ async acquireMutexLock({ nodeIds, operation }, action) {
22651
+ const lockAcquired = this.setMutexLock({
22652
+ nodeIds,
22653
+ operation
22654
+ });
22655
+ if (lockAcquired) {
22656
+ await Promise.resolve(action());
22657
+ this.releaseMutexLock();
22658
+ }
22659
+ }
22660
+ getUserMutexLock(userMutexKey) {
22661
+ if (this.userMutexLocked.get(userMutexKey)) return this.userMutexLocked.get(userMutexKey);
22662
+ return void 0;
22663
+ }
22664
+ getNodeMutexLock(nodeMutexKey) {
22665
+ if (this.nodeMutexLocked.get(nodeMutexKey)) return this.nodeMutexLocked.get(nodeMutexKey);
22666
+ return void 0;
22667
+ }
22668
+ getUserMutexKey(user) {
22669
+ const store = this.instance.getStore();
22670
+ let userInfo = store.getUser();
22671
+ if (user !== void 0) userInfo = user;
22672
+ return userInfo.id;
22673
+ }
22674
+ getNodeMutexKey(nodeId) {
22675
+ return nodeId;
22676
+ }
22677
+ setMutexLockRemote({ nodeIds, operation, metadata }, user) {
22678
+ return this.setMutexLock({
22679
+ nodeIds,
22680
+ operation,
22681
+ metadata
22682
+ }, user, false);
22683
+ }
22684
+ setMutexLock({ nodeIds, operation, metadata }, userInfo = void 0, sendAwareness = true) {
22685
+ const store = this.instance.getStore();
22686
+ let user = store.getUser();
22687
+ if (userInfo !== void 0) user = userInfo;
22688
+ const userMutexKey = this.getUserMutexKey(user);
22689
+ if (this.userMutexLocked.has(userMutexKey)) return false;
22690
+ const preLockedNodes = [];
22691
+ for (const nodeId of nodeIds) {
22692
+ const nodeMutexKey = this.getNodeMutexKey(nodeId);
22693
+ if (this.nodeMutexLocked.has(nodeMutexKey)) break;
22694
+ else {
22695
+ this.nodeMutexLocked.set(nodeMutexKey, {
22696
+ user,
22697
+ operation,
22698
+ metadata
22699
+ });
22700
+ const nodeInstance = this.instance.getStage().findOne(`#${nodeId}`);
22701
+ if (nodeInstance) nodeInstance.lockMutex(user);
22702
+ preLockedNodes.push(nodeMutexKey);
22703
+ }
22704
+ }
22705
+ if (preLockedNodes.length === nodeIds.length && !this.userMutexLocked.has(userMutexKey)) {
22706
+ this.userMutexLocked.set(userMutexKey, {
22707
+ user,
22708
+ nodeIds,
22709
+ operation,
22710
+ metadata
22711
+ });
22712
+ if (sendAwareness) store.setAwarenessInfo(this.WEAVE_USER_MUTEX_LOCK_KEY, {
22713
+ user,
22714
+ nodeIds,
22715
+ operation,
22716
+ metadata
22717
+ });
22718
+ this.instance.emitEvent("onMutexLockChange", { locks: [...this.userMutexLocked.keys()] });
22719
+ return true;
22720
+ }
22721
+ if (preLockedNodes.length !== nodeIds.length) {
22722
+ this.userMutexLocked.delete(userMutexKey);
22723
+ for (const nodeMutexKey of preLockedNodes) this.nodeMutexLocked.delete(nodeMutexKey);
22724
+ }
22725
+ return false;
22726
+ }
22727
+ releaseMutexLockRemote(user) {
22728
+ this.releaseMutexLock(user, false);
22729
+ }
22730
+ releaseMutexLock(userInfo = void 0, sendAwareness = true) {
22731
+ const store = this.instance.getStore();
22732
+ let user = store.getUser();
22733
+ if (userInfo !== void 0) user = userInfo;
22734
+ const userMutexKey = this.getUserMutexKey(user);
22735
+ if (this.userMutexLocked.has(userMutexKey)) {
22736
+ const nodeIds = this.userMutexLocked.get(userMutexKey).nodeIds;
22737
+ for (const nodeId of nodeIds) {
22738
+ const nodeMutexKey = this.getNodeMutexKey(nodeId);
22739
+ this.nodeMutexLocked.delete(nodeMutexKey);
22740
+ const nodeInstance = this.instance.getStage().findOne(`#${nodeId}`);
22741
+ if (nodeInstance) nodeInstance.releaseMutex();
22742
+ }
22743
+ this.userMutexLocked.delete(userMutexKey);
22744
+ if (sendAwareness) store.setAwarenessInfo(this.WEAVE_USER_MUTEX_LOCK_KEY, void 0);
22745
+ this.instance.emitEvent("onMutexLockChange", { locks: [...this.userMutexLocked.keys()] });
22746
+ }
22747
+ }
22748
+ };
22749
+
22750
+ //#endregion
22751
+ //#region src/managers/async/watch-map.ts
22474
22752
  function watchMap(onChange, map = new Map()) {
22475
22753
  const handler = { get(target, prop, receiver) {
22476
22754
  if (prop === "set") return (key, value$1) => {
@@ -22514,12 +22792,70 @@ function watchMap(onChange, map = new Map()) {
22514
22792
  return new Proxy(map, handler);
22515
22793
  }
22516
22794
 
22795
+ //#endregion
22796
+ //#region src/managers/async/async.ts
22797
+ var WeaveAsyncManager = class {
22798
+ constructor(instance) {
22799
+ this.instance = instance;
22800
+ this.logger = this.instance.getChildLogger("async-manager");
22801
+ this.logger.debug("Async manager created");
22802
+ this.asyncElements = watchMap(() => {
22803
+ this.instance.emitEvent("onAsyncElementChange");
22804
+ }, new Map());
22805
+ }
22806
+ asyncElementsLoaded() {
22807
+ return [...this.asyncElements.values()].every((el) => el.status === WEAVE_ASYNC_STATUS.LOADED);
22808
+ }
22809
+ loadAsyncElement(nodeId, type) {
22810
+ let element = this.asyncElements.get(nodeId);
22811
+ if (element) element.status = WEAVE_ASYNC_STATUS.LOADING;
22812
+ else element = {
22813
+ type,
22814
+ status: WEAVE_ASYNC_STATUS.LOADING
22815
+ };
22816
+ this.asyncElements.set(nodeId, element);
22817
+ }
22818
+ resolveAsyncElement(nodeId, type) {
22819
+ let element = this.asyncElements.get(nodeId);
22820
+ if (element) element.status = WEAVE_ASYNC_STATUS.LOADED;
22821
+ else element = {
22822
+ type,
22823
+ status: WEAVE_ASYNC_STATUS.LOADED
22824
+ };
22825
+ this.asyncElements.set(nodeId, element);
22826
+ }
22827
+ };
22828
+
22829
+ //#endregion
22830
+ //#region src/managers/hooks.ts
22831
+ var WeaveHooksManager = class {
22832
+ registeredHooks = new Map();
22833
+ constructor(instance) {
22834
+ this.instance = instance;
22835
+ this.logger = this.instance.getChildLogger("hooks-manager");
22836
+ this.logger.debug("Hooks manager created");
22837
+ }
22838
+ registerHook(hookName, hook) {
22839
+ const exists = this.registeredHooks.has(hookName);
22840
+ if (!exists) this.registeredHooks.set(hookName, hook);
22841
+ }
22842
+ runPhaseHooks(phaseName, execution) {
22843
+ const hooks = [...this.registeredHooks.keys()].filter((key) => key.startsWith(`${phaseName}:`)).map((key) => this.registeredHooks.get(key));
22844
+ for (const hook of hooks) execution(hook);
22845
+ }
22846
+ getHook(hookName) {
22847
+ return this.registeredHooks.get(hookName);
22848
+ }
22849
+ unregisterHook(hookName) {
22850
+ this.registeredHooks.delete(hookName);
22851
+ }
22852
+ };
22853
+
22517
22854
  //#endregion
22518
22855
  //#region src/weave.ts
22519
22856
  var Weave = class {
22520
22857
  initialized = false;
22521
22858
  status = WEAVE_INSTANCE_STATUS.IDLE;
22522
- registeredHooks = new Map();
22523
22859
  constructor(weaveConfig, stageConfig) {
22524
22860
  globalThis._weave_isServerSide = false;
22525
22861
  if (typeof window === "undefined") globalThis._weave_isServerSide = true;
@@ -22527,9 +22863,6 @@ var Weave = class {
22527
22863
  Konva.showWarnings = false;
22528
22864
  this.id = v4_default();
22529
22865
  this.initialized = false;
22530
- this.asyncElements = watchMap(() => {
22531
- this.emitEvent("onAsyncElementChange");
22532
- }, new Map());
22533
22866
  this.config = mergeExceptArrays({}, weaveConfig);
22534
22867
  this.logger = new WeaveLogger(this.config?.logger ?? {
22535
22868
  disabled: false,
@@ -22552,6 +22885,9 @@ var Weave = class {
22552
22885
  this.exportManager = new WeaveExportManager(this);
22553
22886
  this.actionsManager = new WeaveActionsManager(this);
22554
22887
  this.pluginsManager = new WeavePluginsManager(this);
22888
+ this.mutexManager = new WeaveMutexManager(this);
22889
+ this.asyncManager = new WeaveAsyncManager(this);
22890
+ this.hooksManager = new WeaveHooksManager(this);
22555
22891
  this.setupManager.welcomeLog();
22556
22892
  }
22557
22893
  getRenderer() {
@@ -23041,42 +23377,50 @@ var Weave = class {
23041
23377
  }
23042
23378
  }
23043
23379
  asyncElementsLoaded() {
23044
- return [...this.asyncElements.values()].every((el) => el.status === "loaded");
23380
+ return this.asyncManager.asyncElementsLoaded();
23045
23381
  }
23046
23382
  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);
23383
+ this.asyncManager.loadAsyncElement(nodeId, type);
23054
23384
  }
23055
23385
  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);
23386
+ this.asyncManager.resolveAsyncElement(nodeId, type);
23063
23387
  }
23064
23388
  isServerSide() {
23065
23389
  return globalThis._weave_isServerSide === true;
23066
23390
  }
23067
23391
  registerHook(hookName, hook) {
23068
- const exists = this.registeredHooks.has(hookName);
23069
- if (!exists) this.registeredHooks.set(hookName, hook);
23392
+ this.hooksManager.registerHook(hookName, hook);
23070
23393
  }
23071
23394
  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);
23395
+ this.hooksManager.runPhaseHooks(phaseName, execution);
23074
23396
  }
23075
23397
  getHook(hookName) {
23076
- return this.registeredHooks.get(hookName);
23398
+ return this.hooksManager.getHook(hookName);
23077
23399
  }
23078
23400
  unregisterHook(hookName) {
23079
- this.registeredHooks.delete(hookName);
23401
+ this.hooksManager.unregisterHook(hookName);
23402
+ }
23403
+ async acquireMutexLock({ nodeIds, operation }, action) {
23404
+ return await this.mutexManager.acquireMutexLock({
23405
+ nodeIds,
23406
+ operation
23407
+ }, action);
23408
+ }
23409
+ setMutexLock({ nodeIds, operation, metadata }) {
23410
+ return this.mutexManager.setMutexLock({
23411
+ nodeIds,
23412
+ operation,
23413
+ metadata
23414
+ });
23415
+ }
23416
+ releaseMutexLock() {
23417
+ this.mutexManager.releaseMutexLock();
23418
+ }
23419
+ getLockDetails(lockId) {
23420
+ return this.mutexManager.getUserMutexLock(lockId);
23421
+ }
23422
+ getNodeMutexLock(nodeId) {
23423
+ return this.mutexManager.getNodeMutexLock(nodeId);
23080
23424
  }
23081
23425
  };
23082
23426
 
@@ -23225,11 +23569,15 @@ var WeaveLayerNode = class extends WeaveNode {
23225
23569
  if (!handler) continue;
23226
23570
  childrenMapped.push(handler.serialize(node));
23227
23571
  }
23572
+ const cleanedAttrs = { ...attrs };
23573
+ delete cleanedAttrs.mutexLocked;
23574
+ delete cleanedAttrs.mutexUserId;
23575
+ delete cleanedAttrs.draggable;
23228
23576
  return {
23229
23577
  key: attrs.id ?? "",
23230
23578
  type: attrs.nodeType,
23231
23579
  props: {
23232
- ...attrs,
23580
+ ...cleanedAttrs,
23233
23581
  id: attrs.id ?? "",
23234
23582
  nodeType: attrs.nodeType,
23235
23583
  children: childrenMapped
@@ -23302,11 +23650,15 @@ var WeaveGroupNode = class extends WeaveNode {
23302
23650
  if (!handler) continue;
23303
23651
  childrenMapped.push(handler.serialize(node));
23304
23652
  }
23653
+ const cleanedAttrs = { ...attrs };
23654
+ delete cleanedAttrs.mutexLocked;
23655
+ delete cleanedAttrs.mutexUserId;
23656
+ delete cleanedAttrs.draggable;
23305
23657
  return {
23306
23658
  key: attrs.id ?? "",
23307
23659
  type: attrs.nodeType,
23308
23660
  props: {
23309
- ...attrs,
23661
+ ...cleanedAttrs,
23310
23662
  id: attrs.id ?? "",
23311
23663
  nodeType: attrs.nodeType,
23312
23664
  sceneFunc: void 0,
@@ -23918,7 +24270,7 @@ var WeaveTextNode = class extends WeaveNode {
23918
24270
  text.on("transformstart", (e) => {
23919
24271
  this.instance.emitEvent("onTransform", e.target);
23920
24272
  });
23921
- text.on("transform", (0, import_lodash.throttle)(handleTextTransform, 50));
24273
+ text.on("transform", (0, import_lodash.throttle)(handleTextTransform, DEFAULT_THROTTLE_MS));
23922
24274
  text.on("transformend", () => {
23923
24275
  this.instance.emitEvent("onTransform", null);
23924
24276
  });
@@ -23987,6 +24339,8 @@ var WeaveTextNode = class extends WeaveNode {
23987
24339
  serialize(instance) {
23988
24340
  const attrs = instance.getAttrs();
23989
24341
  const cleanedAttrs = { ...attrs };
24342
+ delete cleanedAttrs.mutexLocked;
24343
+ delete cleanedAttrs.mutexUserId;
23990
24344
  delete cleanedAttrs.draggable;
23991
24345
  delete cleanedAttrs.triggerEditMode;
23992
24346
  delete cleanedAttrs.cancelEditMode;
@@ -24145,6 +24499,13 @@ var WeaveTextNode = class extends WeaveNode {
24145
24499
  const correctionY = (actualFont === void 0 ? 0 : actualFont.offsetY ?? 0) * stage.scaleX();
24146
24500
  this.textArea.style.left = `${correctionX - 1}px`;
24147
24501
  this.textArea.style.top = `${correctionY}px`;
24502
+ const updateTextNode = () => {
24503
+ if (!this.textArea) return;
24504
+ updateTextNodeSize();
24505
+ textNode.text(this.textArea.value);
24506
+ textNode.visible(true);
24507
+ this.instance.updateNode(this.serialize(textNode));
24508
+ };
24148
24509
  this.textArea.onfocus = () => {
24149
24510
  this.textAreaDomResize(textNode);
24150
24511
  };
@@ -24156,9 +24517,11 @@ var WeaveTextNode = class extends WeaveNode {
24156
24517
  };
24157
24518
  this.textArea.onpaste = () => {
24158
24519
  this.textAreaDomResize(textNode);
24520
+ updateTextNode();
24159
24521
  };
24160
24522
  this.textArea.oninput = () => {
24161
24523
  this.textAreaDomResize(textNode);
24524
+ updateTextNode();
24162
24525
  };
24163
24526
  this.textAreaSuperContainer.addEventListener("scroll", () => {
24164
24527
  if (this.textAreaSuperContainer) {
@@ -24287,6 +24650,7 @@ var WeaveTextNode = class extends WeaveNode {
24287
24650
  else textNode.visible(true);
24288
24651
  }
24289
24652
  removeTextAreaDOM(textNode) {
24653
+ this.instance.releaseMutexLock();
24290
24654
  this.editing = false;
24291
24655
  const stage = this.instance.getStage();
24292
24656
  delete window.weaveTextEditing[textNode.id()];
@@ -24309,6 +24673,11 @@ var WeaveTextNode = class extends WeaveNode {
24309
24673
  this.instance.emitEvent("onExitTextNodeEditMode", { node: textNode });
24310
24674
  }
24311
24675
  triggerEditMode(textNode) {
24676
+ const lockAcquired = this.instance.setMutexLock({
24677
+ nodeIds: [textNode.id()],
24678
+ operation: "text-edit"
24679
+ });
24680
+ if (!lockAcquired) return;
24312
24681
  this.editing = true;
24313
24682
  textNode.visible(false);
24314
24683
  const selectionPlugin = this.instance.getPlugin("nodesSelection");
@@ -24533,6 +24902,7 @@ var WeaveImageCrop = class WeaveImageCrop {
24533
24902
  const nodesSelectionPlugin = this.getNodesSelectionPlugin();
24534
24903
  if (nodesSelectionPlugin) nodesSelectionPlugin.enable();
24535
24904
  stage.mode(WEAVE_STAGE_DEFAULT_MODE);
24905
+ this.instance.releaseMutexLock();
24536
24906
  this.instance.emitEvent("onImageCropEnd", { instance: this.image });
24537
24907
  }
24538
24908
  drawGridLines(x, y, width, height) {
@@ -24714,6 +25084,11 @@ var WeaveImageNode = class extends WeaveNode {
24714
25084
  const stage = this.instance.getStage();
24715
25085
  if (imageNode.getAttrs().cropping ?? false) return;
24716
25086
  if (!(this.isSelecting() && this.isNodeSelected(imageNode))) return;
25087
+ const lockAcquired = this.instance.setMutexLock({
25088
+ nodeIds: [imageNode.id()],
25089
+ operation: "image-crop"
25090
+ });
25091
+ if (!lockAcquired) return;
24717
25092
  stage.mode("cropping");
24718
25093
  const image = stage.findOne(`#${imageNode.getAttrs().id}`);
24719
25094
  const internalImage = image?.findOne(`#${image.getAttrs().id}-image`);
@@ -25688,6 +26063,8 @@ var WeaveFrameNode = class extends WeaveNode {
25688
26063
  }
25689
26064
  const realAttrs = mainNode?.getAttrs();
25690
26065
  const cleanedAttrs = { ...realAttrs };
26066
+ delete cleanedAttrs.mutexLocked;
26067
+ delete cleanedAttrs.mutexUserId;
25691
26068
  delete cleanedAttrs.draggable;
25692
26069
  delete cleanedAttrs.onTargetEnter;
25693
26070
  return {
@@ -25920,6 +26297,8 @@ var WeaveStrokeNode = class extends WeaveNode {
25920
26297
  serialize(instance) {
25921
26298
  const attrs = instance.getAttrs();
25922
26299
  const cleanedAttrs = { ...attrs };
26300
+ delete cleanedAttrs.mutexLocked;
26301
+ delete cleanedAttrs.mutexUserId;
25923
26302
  delete cleanedAttrs.draggable;
25924
26303
  delete cleanedAttrs.sceneFunc;
25925
26304
  delete cleanedAttrs.hitFunc;
@@ -29092,6 +29471,8 @@ var WeaveConnectorNode = class extends WeaveNode {
29092
29471
  serialize(instance) {
29093
29472
  const attrs = instance.getAttrs();
29094
29473
  const cleanedAttrs = { ...attrs };
29474
+ delete cleanedAttrs.mutexLocked;
29475
+ delete cleanedAttrs.mutexUserId;
29095
29476
  delete cleanedAttrs.draggable;
29096
29477
  delete cleanedAttrs.sceneFunc;
29097
29478
  delete cleanedAttrs.hitFunc;
@@ -29272,7 +29653,7 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29272
29653
  this.config.zoomSteps = [minimumZoom, ...this.config.zoomSteps];
29273
29654
  }
29274
29655
  };
29275
- mainLayer?.on("draw", (0, import_lodash.throttle)(handleDraw, 50));
29656
+ mainLayer?.on("draw", (0, import_lodash.throttle)(handleDraw, DEFAULT_THROTTLE_MS));
29276
29657
  this.setZoom(this.config.zoomSteps[this.actualStep]);
29277
29658
  }
29278
29659
  setZoom(scale, centered = true, pointer) {
@@ -29438,15 +29819,8 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29438
29819
  });
29439
29820
  this.setZoom(scale, false);
29440
29821
  }
29441
- fitToSelection(smartZoom = false) {
29442
- if (!this.enabled) return;
29822
+ fitToElements(box, smartZoom = false) {
29443
29823
  const stage = this.instance.getStage();
29444
- const selectionPlugin = this.getNodesSelectionPlugin();
29445
- if (!selectionPlugin) return;
29446
- const nodes = selectionPlugin.getTransformer().getNodes();
29447
- if (nodes.length === 0) return;
29448
- const box = getBoundingBox(selectionPlugin.getTransformer().getNodes(), { relativeTo: stage });
29449
- if (box.width === 0 || box.height === 0) return;
29450
29824
  const container = stage.container();
29451
29825
  const scale = stage.scale();
29452
29826
  const containerWidth = container.clientWidth;
@@ -29497,6 +29871,26 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29497
29871
  });
29498
29872
  this.setZoom(finalScale, false);
29499
29873
  }
29874
+ fitToNodes(nodes, smartZoom = false) {
29875
+ if (!this.enabled) return;
29876
+ const stage = this.instance.getStage();
29877
+ if (nodes.length === 0) return;
29878
+ const nodesInstances = nodes.map((nodeId) => this.instance.getStage().findOne(`#${nodeId}`)).filter((node) => node !== null);
29879
+ const box = getBoundingBox(nodesInstances, { relativeTo: stage });
29880
+ if (box.width === 0 || box.height === 0) return;
29881
+ this.fitToElements(box, smartZoom);
29882
+ }
29883
+ fitToSelection(smartZoom = false) {
29884
+ if (!this.enabled) return;
29885
+ const stage = this.instance.getStage();
29886
+ const selectionPlugin = this.getNodesSelectionPlugin();
29887
+ if (!selectionPlugin) return;
29888
+ const nodes = selectionPlugin.getTransformer().getNodes();
29889
+ if (nodes.length === 0) return;
29890
+ const box = getBoundingBox(selectionPlugin.getTransformer().getNodes(), { relativeTo: stage });
29891
+ if (box.width === 0 || box.height === 0) return;
29892
+ this.fitToElements(box, smartZoom);
29893
+ }
29500
29894
  enable() {
29501
29895
  this.enabled = true;
29502
29896
  }
@@ -29618,7 +30012,7 @@ var WeaveStageZoomPlugin = class extends WeavePlugin {
29618
30012
  requestAnimationFrame(this.zoomTick.bind(this));
29619
30013
  }
29620
30014
  };
29621
- const throttledHandleWheel = (0, import_lodash.throttle)(handleWheel, 30);
30015
+ const throttledHandleWheel = (0, import_lodash.throttle)(handleWheel, DEFAULT_THROTTLE_MS);
29622
30016
  window.addEventListener("wheel", throttledHandleWheel, { passive: true });
29623
30017
  }
29624
30018
  getInertiaScale() {
@@ -32075,12 +32469,12 @@ var WeaveArrowToolAction = class extends WeaveAction {
32075
32469
  this.instance.addNode(finalArrow, this.container?.getAttrs().id);
32076
32470
  this.instance.emitEvent("onAddedArrow");
32077
32471
  }
32078
- }
32079
- const selectionPlugin = this.instance.getPlugin("nodesSelection");
32080
- if (selectionPlugin) {
32081
- const node = stage.findOne(`#${this.arrowId}`);
32082
- if (node) selectionPlugin.setSelectedNodes([node]);
32083
- this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
32472
+ const selectionPlugin = this.instance.getPlugin("nodesSelection");
32473
+ if (selectionPlugin) {
32474
+ const node = stage.findOne(`#${this.arrowId}`);
32475
+ if (node) selectionPlugin.setSelectedNodes([node]);
32476
+ this.instance.triggerAction(SELECTION_TOOL_ACTION_NAME);
32477
+ }
32084
32478
  }
32085
32479
  stage.container().style.cursor = "default";
32086
32480
  this.initialCursor = null;
@@ -33953,7 +34347,7 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
33953
34347
  if (!this.enabled || !(this.isSpaceKeyPressed || this.isMouseMiddleButtonPressed || this.moveToolActive)) return;
33954
34348
  this.onRender();
33955
34349
  };
33956
- stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, 50));
34350
+ stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, DEFAULT_THROTTLE_MS));
33957
34351
  stage.on("pointermove", () => {
33958
34352
  if (this.enabled) this.onRender();
33959
34353
  });
@@ -34260,7 +34654,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
34260
34654
  lastPos = pos;
34261
34655
  this.instance.emitEvent("onStageMove");
34262
34656
  };
34263
- stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, 50));
34657
+ stage.on("pointermove", (0, import_lodash.throttle)(handleMouseMove, DEFAULT_THROTTLE_MS));
34264
34658
  stage.on("pointerup", (e) => {
34265
34659
  this.pointers.delete(e.evt.pointerId);
34266
34660
  this.isMouseLeftButtonPressed = false;
@@ -34286,7 +34680,7 @@ var WeaveStagePanningPlugin = class extends WeavePlugin {
34286
34680
  stage.y(stage.y() - e.deltaY);
34287
34681
  this.instance.emitEvent("onStageMove");
34288
34682
  };
34289
- const handleWheelThrottled = (0, import_lodash.throttle)(handleWheel, 20);
34683
+ const handleWheelThrottled = (0, import_lodash.throttle)(handleWheel, WEAVE_STAGE_PANNING_THROTTLE_MS);
34290
34684
  window.addEventListener("wheel", handleWheelThrottled, { passive: true });
34291
34685
  stage.on("dragstart", (e) => {
34292
34686
  const duration = 1e3 / 60;
@@ -34528,7 +34922,7 @@ var WeaveStageMinimapPlugin = class extends WeavePlugin {
34528
34922
  const throttledUpdateMinimap = (0, import_lodash.throttle)(async () => {
34529
34923
  await this.updateMinimapContent();
34530
34924
  this.updateMinimapViewportReference();
34531
- }, 100);
34925
+ }, DEFAULT_THROTTLE_MS);
34532
34926
  this.instance.addEventListener("onStateChange", throttledUpdateMinimap);
34533
34927
  if (this.instance.isServerSide()) return;
34534
34928
  const workerPath = new URL("./stage-minimap.worker.js", import.meta.url);
@@ -34622,7 +35016,7 @@ var WeaveStageResizePlugin = class extends WeavePlugin {
34622
35016
  onInit() {
34623
35017
  const throttledResize = (0, import_lodash.throttle)(() => {
34624
35018
  this.resizeStage();
34625
- }, 100);
35019
+ }, DEFAULT_THROTTLE_MS);
34626
35020
  window.addEventListener("resize", () => {
34627
35021
  throttledResize();
34628
35022
  });
@@ -34809,11 +35203,6 @@ var WeaveNodesMultiSelectionFeedbackPlugin = class extends WeavePlugin {
34809
35203
  }
34810
35204
  };
34811
35205
 
34812
- //#endregion
34813
- //#region src/plugins/connected-users/constants.ts
34814
- const WEAVE_CONNECTED_USERS_KEY = "connectedUsers";
34815
- const WEAVE_CONNECTED_USER_INFO_KEY = "userInfo";
34816
-
34817
35206
  //#endregion
34818
35207
  //#region src/plugins/connected-users/connected-users.ts
34819
35208
  var WeaveConnectedUsersPlugin = class extends WeavePlugin {
@@ -35029,7 +35418,7 @@ const WEAVE_DEFAULT_USER_INFO_FUNCTION = () => ({
35029
35418
  email: "unknown@domain.com"
35030
35419
  });
35031
35420
  const WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS = {
35032
- awarenessThrottleMs: 100,
35421
+ awarenessThrottleMs: DEFAULT_THROTTLE_MS,
35033
35422
  ui: {
35034
35423
  separation: 8,
35035
35424
  pointer: {
@@ -35042,8 +35431,10 @@ const WEAVE_USERS_POINTERS_CONFIG_DEFAULT_PROPS = {
35042
35431
  backgroundCornerRadius: 0,
35043
35432
  backgroundPaddingX: 8,
35044
35433
  backgroundPaddingY: 4
35045
- }
35046
- }
35434
+ },
35435
+ operationSeparation: 4
35436
+ },
35437
+ getOperationName: (operation) => operation
35047
35438
  };
35048
35439
 
35049
35440
  //#endregion
@@ -35057,6 +35448,7 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35057
35448
  this.config.getUserBackgroundColor = memoize(this.config.getUserBackgroundColor);
35058
35449
  this.config.getUserForegroundColor = memoize(this.config.getUserForegroundColor);
35059
35450
  this.usersPointers = {};
35451
+ this.usersOperations = {};
35060
35452
  }
35061
35453
  getName() {
35062
35454
  return WEAVE_USERS_POINTERS_KEY;
@@ -35113,6 +35505,16 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35113
35505
  };
35114
35506
  const throttledHandleOnPointerMove = (0, import_lodash.throttle)(handleOnPointerMove, this.config.awarenessThrottleMs);
35115
35507
  stage.on("pointermove", throttledHandleOnPointerMove);
35508
+ const handleUsersLocksChange = ({ locks }) => {
35509
+ const actUsersLocks = {};
35510
+ for (const lockKey of locks) {
35511
+ const mutexInfo = this.instance?.getLockDetails(lockKey);
35512
+ if (mutexInfo) actUsersLocks[lockKey] = mutexInfo;
35513
+ }
35514
+ this.usersOperations = actUsersLocks;
35515
+ this.renderPointers();
35516
+ };
35517
+ this.instance.addEventListener("onMutexLockChange", handleUsersLocksChange);
35116
35518
  this.renderPointers();
35117
35519
  }
35118
35520
  sendAwarenessUpdate(mousePos) {
@@ -35146,7 +35548,8 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35146
35548
  scaleY: 1 / stage.scaleY()
35147
35549
  });
35148
35550
  userPointerNode.moveToTop();
35149
- const { separation, pointer: { circleRadius, circleStrokeWidth }, name: { fontFamily, fontSize, backgroundCornerRadius, backgroundPaddingX, backgroundPaddingY } } = this.config.ui;
35551
+ const { separation, pointer: { circleRadius, circleStrokeWidth }, name: { fontFamily, fontSize, backgroundCornerRadius, backgroundPaddingX, backgroundPaddingY }, operationSeparation } = this.config.ui;
35552
+ const getOperationName = this.config.getOperationName;
35150
35553
  const userBackgroundColor = this.config.getUserBackgroundColor(userPointer.rawUser);
35151
35554
  const userForegroundColor = this.config.getUserForegroundColor(userPointer.rawUser);
35152
35555
  const userPointNode = new Konva.Circle({
@@ -35196,6 +35599,41 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35196
35599
  userPointerNode.add(userPointNode);
35197
35600
  userPointerNode.add(userNameBackground);
35198
35601
  userPointerNode.add(userNameNode);
35602
+ if (this.usersOperations[userPointer.user]) {
35603
+ const userOperationNode = new Konva.Text({
35604
+ id: `pointer_${userPointer.user}_userPointOperation`,
35605
+ x: separation,
35606
+ y: -circleRadius * 2 + backgroundPaddingY + operationSeparation + textHeight + backgroundPaddingY * 2,
35607
+ text: getOperationName(this.usersOperations[userPointer.user].operation),
35608
+ fontSize,
35609
+ fontFamily,
35610
+ lineHeight: .9,
35611
+ fill: userForegroundColor,
35612
+ align: "center",
35613
+ verticalAlign: "middle",
35614
+ draggable: false,
35615
+ listening: false,
35616
+ strokeScaleEnabled: false,
35617
+ ellipsis: true
35618
+ });
35619
+ const textOperationWidth = userOperationNode.getTextWidth();
35620
+ const textOperationHeight = userOperationNode.getTextHeight();
35621
+ userOperationNode.width(textOperationWidth + backgroundPaddingX * 2);
35622
+ userOperationNode.height(textOperationHeight + backgroundPaddingY * 2);
35623
+ const userOperationBackground = new Konva.Rect({
35624
+ id: `pointer_${userPointer.user}_userPointOperationRect`,
35625
+ x: separation,
35626
+ y: -backgroundPaddingY + 4 + userNameBackground.height(),
35627
+ width: textOperationWidth + backgroundPaddingX * 2,
35628
+ height: textOperationHeight + backgroundPaddingY * 2,
35629
+ cornerRadius: backgroundCornerRadius,
35630
+ fill: userBackgroundColor,
35631
+ draggable: false,
35632
+ listening: false
35633
+ });
35634
+ userPointerNode.add(userOperationBackground);
35635
+ userPointerNode.add(userOperationNode);
35636
+ }
35199
35637
  pointersLayer?.add(userPointerNode);
35200
35638
  }
35201
35639
  const selectors = pointersLayer?.find(".selector") ?? [];
@@ -35211,6 +35649,78 @@ var WeaveUsersPointersPlugin = class extends WeavePlugin {
35211
35649
  }
35212
35650
  };
35213
35651
 
35652
+ //#endregion
35653
+ //#region src/plugins/users-presence/users-presence.ts
35654
+ var WeaveUsersPresencePlugin = class extends WeavePlugin {
35655
+ userPresence = {};
35656
+ onRender = void 0;
35657
+ constructor(params) {
35658
+ super();
35659
+ const { config } = params;
35660
+ this.config = mergeExceptArrays(WEAVE_USERS_PRESENCE_CONFIG_DEFAULT_PROPS, config);
35661
+ this.userPresence = {};
35662
+ }
35663
+ getName() {
35664
+ return WEAVE_USERS_PRESENCE_PLUGIN_KEY;
35665
+ }
35666
+ registerHooks() {
35667
+ this.instance.registerHook("onPresenceUpdate:usersPresencePlugin", ({ node, presenceData }) => {
35668
+ const nodeHandler = this.instance.getNodeHandler(node.getAttrs().nodeType);
35669
+ const newProps = {
35670
+ ...node.getAttrs(),
35671
+ ...presenceData
35672
+ };
35673
+ nodeHandler?.onUpdate(node, newProps);
35674
+ });
35675
+ }
35676
+ onInit() {
35677
+ const stage = this.instance.getStage();
35678
+ this.registerHooks();
35679
+ this.instance.addEventListener("onAwarenessChange", (changes) => {
35680
+ for (const change of changes) {
35681
+ if (!change[WEAVE_USER_PRESENCE_KEY]) continue;
35682
+ const userPresence = change[WEAVE_USER_PRESENCE_KEY];
35683
+ const nodes = Object.keys(userPresence);
35684
+ if (nodes.length === 0) continue;
35685
+ for (const nodeId of nodes) {
35686
+ const presenceInfo = userPresence[nodeId];
35687
+ if (this.config.getUser().id === presenceInfo.userId) continue;
35688
+ const nodeInstance = stage.findOne(`#${presenceInfo.nodeId}`);
35689
+ if (nodeInstance) this.instance.runPhaseHooks("onPresenceUpdate", (hook) => {
35690
+ hook({
35691
+ node: nodeInstance,
35692
+ presenceData: presenceInfo.attrs
35693
+ });
35694
+ });
35695
+ }
35696
+ }
35697
+ });
35698
+ }
35699
+ sendPresence() {
35700
+ const store = this.instance.getStore();
35701
+ store.setAwarenessInfo(WEAVE_USER_PRESENCE_KEY, this.userPresence);
35702
+ }
35703
+ setPresence(nodeId, attrs) {
35704
+ const userInfo = this.config.getUser();
35705
+ this.userPresence[nodeId] = {
35706
+ userId: userInfo.id,
35707
+ nodeId,
35708
+ attrs
35709
+ };
35710
+ this.sendPresence();
35711
+ }
35712
+ removePresence(nodeId) {
35713
+ if (this.userPresence[nodeId]) delete this.userPresence[nodeId];
35714
+ this.sendPresence();
35715
+ }
35716
+ enable() {
35717
+ this.enabled = true;
35718
+ }
35719
+ disable() {
35720
+ this.enabled = false;
35721
+ }
35722
+ };
35723
+
35214
35724
  //#endregion
35215
35725
  //#region src/plugins/stage-drop-area/constants.ts
35216
35726
  const WEAVE_STAGE_DROP_AREA_KEY = "stageDropArea";
@@ -36358,5 +36868,5 @@ const setupCanvasBackend = async () => {
36358
36868
  };
36359
36869
 
36360
36870
  //#endregion
36361
- 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 };
36871
+ 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 };
36362
36872
  //# sourceMappingURL=sdk.node.js.map