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