@inditextech/weave-sdk 0.49.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk.cjs CHANGED
@@ -15645,7 +15645,7 @@ const WEAVE_NODES_SELECTION_LAYER_ID = "selectionLayer";
15645
15645
 
15646
15646
  //#endregion
15647
15647
  //#region src/plugins/context-menu/constants.ts
15648
- const WEAVE_CONTEXT_MENU_KEY = "contextMenu";
15648
+ const WEAVE_CONTEXT_MENU_PLUGIN_KEY = "contextMenu";
15649
15649
  const WEAVE_CONTEXT_MENU_X_OFFSET_DEFAULT = 4;
15650
15650
  const WEAVE_CONTEXT_MENU_Y_OFFSET_DEFAULT = 4;
15651
15651
  const WEAVE_CONTEXT_MENU_TAP_HOLD_TIMEOUT = 500;
@@ -15829,6 +15829,80 @@ function containsNodeDeep(nodes, target) {
15829
15829
  }
15830
15830
  return false;
15831
15831
  }
15832
+ function getSelectedNodesMetadata(transformer) {
15833
+ const firstNode = transformer.getNodes()[0];
15834
+ const firstNodeClientRect = firstNode.getClientRect();
15835
+ const rectCoordsMin = {
15836
+ x: firstNodeClientRect.x,
15837
+ y: firstNodeClientRect.y
15838
+ };
15839
+ const rectCoordsMax = {
15840
+ x: firstNodeClientRect.x + firstNodeClientRect.width,
15841
+ y: firstNodeClientRect.y + firstNodeClientRect.height
15842
+ };
15843
+ const nodes = [];
15844
+ for (const node of transformer.getNodes()) {
15845
+ const clientRect = node.getClientRect();
15846
+ if (clientRect.x < rectCoordsMin.x) rectCoordsMin.x = clientRect.x;
15847
+ if (clientRect.y < rectCoordsMin.y) rectCoordsMin.y = clientRect.y;
15848
+ if (clientRect.x + clientRect.width > rectCoordsMax.x) rectCoordsMax.x = clientRect.x + clientRect.width;
15849
+ if (clientRect.y + clientRect.height > rectCoordsMax.y) rectCoordsMax.y = clientRect.y + clientRect.height;
15850
+ nodes.push(node.getAttrs().id);
15851
+ }
15852
+ return {
15853
+ width: rectCoordsMax.x - rectCoordsMin.x,
15854
+ height: rectCoordsMax.y - rectCoordsMin.y,
15855
+ nodes
15856
+ };
15857
+ }
15858
+ function getTargetAndSkipNodes(instance, e) {
15859
+ const nodesSelectionPlugin = instance.getPlugin("nodesSelection");
15860
+ let skipNodes = [];
15861
+ let node = void 0;
15862
+ if (e.type === "dragmove" && nodesSelectionPlugin && nodesSelectionPlugin.getTransformer().nodes().length === 1) {
15863
+ node = nodesSelectionPlugin.getTransformer().nodes()[0];
15864
+ skipNodes.push(node.getAttrs().id ?? "");
15865
+ }
15866
+ if (e.type === "dragmove" && nodesSelectionPlugin && nodesSelectionPlugin.getTransformer().nodes().length > 1) {
15867
+ const { nodes } = getSelectedNodesMetadata(nodesSelectionPlugin.getTransformer());
15868
+ node = nodesSelectionPlugin.getTransformer();
15869
+ skipNodes = [...nodes];
15870
+ }
15871
+ if (e.type === "transform") {
15872
+ node = e.target;
15873
+ skipNodes.push(node.getAttrs().id ?? "");
15874
+ }
15875
+ return {
15876
+ targetNode: node,
15877
+ skipNodes
15878
+ };
15879
+ }
15880
+ function getVisibleNodesInViewport(stage, referenceLayer) {
15881
+ const scale = stage.scaleX();
15882
+ const stagePos = stage.position();
15883
+ const stageSize = {
15884
+ width: stage.width(),
15885
+ height: stage.height()
15886
+ };
15887
+ const viewRect = {
15888
+ x: -stagePos.x / scale,
15889
+ y: -stagePos.y / scale,
15890
+ width: stageSize.width / scale,
15891
+ height: stageSize.height / scale
15892
+ };
15893
+ const visibleNodes = [];
15894
+ referenceLayer?.find(".node").forEach((node) => {
15895
+ if (!node.isVisible()) return;
15896
+ const box = node.getClientRect({
15897
+ relativeTo: stage,
15898
+ skipStroke: true,
15899
+ skipShadow: true
15900
+ });
15901
+ const intersects = box.x + box.width > viewRect.x && box.x < viewRect.x + viewRect.width && box.y + box.height > viewRect.y && box.y < viewRect.y + viewRect.height;
15902
+ if (intersects) visibleNodes.push(node);
15903
+ });
15904
+ return visibleNodes;
15905
+ }
15832
15906
 
15833
15907
  //#endregion
15834
15908
  //#region src/actions/selection-tool/constants.ts
@@ -15863,7 +15937,7 @@ var WeaveContextMenuPlugin = class extends WeavePlugin {
15863
15937
  this.pointers = {};
15864
15938
  }
15865
15939
  getName() {
15866
- return WEAVE_CONTEXT_MENU_KEY;
15940
+ return WEAVE_CONTEXT_MENU_PLUGIN_KEY;
15867
15941
  }
15868
15942
  onInit() {
15869
15943
  this.initEvents();
@@ -15966,6 +16040,9 @@ var WeaveContextMenuPlugin = class extends WeavePlugin {
15966
16040
  this.tapHold = false;
15967
16041
  }
15968
16042
  });
16043
+ window.addEventListener("contextmenu", (e) => {
16044
+ e.preventDefault();
16045
+ });
15969
16046
  stage.on("contextmenu", (e) => {
15970
16047
  e.evt.preventDefault();
15971
16048
  if (!this.enabled) return;
@@ -16013,6 +16090,45 @@ const WEAVE_USER_SELECTION_KEY = "userSelection";
16013
16090
  const WEAVE_STAGE_NODE_TYPE = "stage";
16014
16091
  const WEAVE_STAGE_DEFAULT_MODE = "default";
16015
16092
 
16093
+ //#endregion
16094
+ //#region src/plugins/nodes-edge-snapping/constants.ts
16095
+ const WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY = "nodesEdgeSnapping";
16096
+ const GUIDE_LINE_NAME = "guide-edge-snapping-line";
16097
+ const GUIDE_LINE_DEFAULT_CONFIG = {
16098
+ stroke: "#ff0000",
16099
+ strokeWidth: 1,
16100
+ dash: []
16101
+ };
16102
+ const GUIDE_LINE_DRAG_SNAPPING_THRESHOLD = 3;
16103
+ const GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD = 3;
16104
+ const GUIDE_ORIENTATION = {
16105
+ ["HORIZONTAL"]: "H",
16106
+ ["VERTICAL"]: "V"
16107
+ };
16108
+ const NODE_SNAP = {
16109
+ ["START"]: "start",
16110
+ ["CENTER"]: "center",
16111
+ ["END"]: "end"
16112
+ };
16113
+
16114
+ //#endregion
16115
+ //#region src/plugins/nodes-distance-snapping/constants.ts
16116
+ const WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY = "nodesDistanceSnapping";
16117
+ const GUIDE_HORIZONTAL_LINE_NAME = "guide-distance-snapping-horizontal-line";
16118
+ const GUIDE_VERTICAL_LINE_NAME = "guide-distance-snapping-vertical-line";
16119
+ const GUIDE_ENTER_SNAPPING_TOLERANCE = 3;
16120
+ const GUIDE_EXIT_SNAPPING_TOLERANCE = 5;
16121
+ const NODE_SNAP_HORIZONTAL = {
16122
+ ["LEFT"]: "left",
16123
+ ["CENTER"]: "center",
16124
+ ["RIGHT"]: "right"
16125
+ };
16126
+ const NODE_SNAP_VERTICAL = {
16127
+ ["TOP"]: "top",
16128
+ ["MIDDLE"]: "middle",
16129
+ ["BOTTOM"]: "bottom"
16130
+ };
16131
+
16016
16132
  //#endregion
16017
16133
  //#region src/plugins/nodes-selection/nodes-selection.ts
16018
16134
  var WeaveNodesSelectionPlugin = class extends WeavePlugin {
@@ -16479,7 +16595,10 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
16479
16595
  const moved = this.checkMoved(e);
16480
16596
  this.checkDoubleTap(e);
16481
16597
  delete this.pointers[e.evt.pointerId];
16482
- if (stage.mode() === WEAVE_STAGE_DEFAULT_MODE) this.getSnappingPlugin()?.cleanupEvaluateGuidelines();
16598
+ if (stage.mode() === WEAVE_STAGE_DEFAULT_MODE) {
16599
+ this.getNodesEdgeSnappingPlugin()?.cleanupGuidelines();
16600
+ this.getNodesDistanceSnappingPlugin()?.cleanupGuidelines();
16601
+ }
16483
16602
  const contextMenuPlugin = this.getContextMenuPlugin();
16484
16603
  if (!this.initialized) {
16485
16604
  this.hideSelectorArea();
@@ -16720,11 +16839,15 @@ var WeaveNodesSelectionPlugin = class extends WeavePlugin {
16720
16839
  this.enabled = false;
16721
16840
  }
16722
16841
  getContextMenuPlugin() {
16723
- const contextMenuPlugin = this.instance.getPlugin("contextMenu");
16842
+ const contextMenuPlugin = this.instance.getPlugin(WEAVE_CONTEXT_MENU_PLUGIN_KEY);
16724
16843
  return contextMenuPlugin;
16725
16844
  }
16726
- getSnappingPlugin() {
16727
- const snappingPlugin = this.instance.getPlugin("nodesSnapping");
16845
+ getNodesEdgeSnappingPlugin() {
16846
+ const snappingPlugin = this.instance.getPlugin(WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY);
16847
+ return snappingPlugin;
16848
+ }
16849
+ getNodesDistanceSnappingPlugin() {
16850
+ const snappingPlugin = this.instance.getPlugin(WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY);
16728
16851
  return snappingPlugin;
16729
16852
  }
16730
16853
  getSelectorConfig() {
@@ -16765,17 +16888,7 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
16765
16888
  setTimeout(async () => {
16766
16889
  if (typeof navigator.clipboard === "undefined") return reject(new Error("Clipboard API not supported"));
16767
16890
  navigator.clipboard.readText().then((text) => {
16768
- try {
16769
- const object = JSON.parse(text);
16770
- if (object.weave && object.weaveMinPoint) this.toPaste = {
16771
- weaveInstanceId: object.weaveInstanceId,
16772
- weave: object.weave,
16773
- weaveMinPoint: object.weaveMinPoint
16774
- };
16775
- resolve(true);
16776
- } catch (_) {
16777
- resolve(false);
16778
- }
16891
+ resolve(this.isWeaveData(text));
16779
16892
  }).catch((error) => {
16780
16893
  reject(error);
16781
16894
  });
@@ -16803,33 +16916,70 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
16803
16916
  return;
16804
16917
  }
16805
16918
  if (stage.isFocused() && e.key === "v" && (e.ctrlKey || e.metaKey)) {
16806
- e.preventDefault();
16919
+ const catcher = document.getElementById("paste-catcher");
16920
+ catcher?.focus();
16807
16921
  if (!this.enabled) return;
16808
16922
  try {
16809
- const continueToPaste = await this.readClipboardData();
16810
- if (continueToPaste) {
16811
- this.state = COPY_PASTE_NODES_PLUGIN_STATE.PASTING;
16812
- this.handlePaste();
16923
+ if (this.isClipboardAPIAvailable()) {
16924
+ const continueToPaste = await this.readClipboardData();
16925
+ if (continueToPaste) {
16926
+ this.state = COPY_PASTE_NODES_PLUGIN_STATE.PASTING;
16927
+ this.handlePaste();
16928
+ e.preventDefault();
16929
+ return;
16930
+ }
16813
16931
  }
16814
16932
  } catch (ex) {
16815
16933
  this.instance.emitEvent("onPaste", ex);
16816
16934
  }
16817
- try {
16818
- const items = await navigator.clipboard.read();
16819
- if (items && items.length === 1) {
16820
- const item = items[0];
16821
- const position = this.instance.getStage().getRelativePointerPosition();
16822
- if (position) this.instance.emitEvent("onPasteExternal", {
16823
- position,
16824
- item
16825
- });
16935
+ e.preventDefault();
16936
+ stage.container().focus();
16937
+ return;
16938
+ }
16939
+ });
16940
+ document.addEventListener("paste", async (e) => {
16941
+ e.preventDefault();
16942
+ const items = e.clipboardData?.items;
16943
+ if (!items) return;
16944
+ let hasWeaveData = false;
16945
+ if (this.isClipboardAPIAvailable()) {
16946
+ for (const item of items) if (item.type === "text/plain") {
16947
+ const text = await this.getTextFromClipboard(item);
16948
+ if (this.isWeaveData(text)) {
16949
+ hasWeaveData = true;
16950
+ this.toPaste = JSON.parse(text);
16826
16951
  }
16827
- } catch (ex) {
16828
- this.instance.emitEvent("onPaste", ex);
16829
16952
  }
16830
- stage.container().focus();
16953
+ }
16954
+ if (hasWeaveData) {
16955
+ this.handlePaste();
16831
16956
  return;
16832
16957
  }
16958
+ const position = this.instance.getStage().getRelativePointerPosition();
16959
+ if (position) this.instance.emitEvent("onPasteExternal", {
16960
+ position,
16961
+ dataList: items
16962
+ });
16963
+ });
16964
+ }
16965
+ isWeaveData(text) {
16966
+ try {
16967
+ const object = JSON.parse(text);
16968
+ if (object.weave && object.weaveMinPoint) this.toPaste = {
16969
+ weaveInstanceId: object.weaveInstanceId,
16970
+ weave: object.weave,
16971
+ weaveMinPoint: object.weaveMinPoint
16972
+ };
16973
+ return true;
16974
+ } catch (_) {
16975
+ return false;
16976
+ }
16977
+ }
16978
+ getTextFromClipboard(item) {
16979
+ return new Promise((resolve) => {
16980
+ item.getAsString((text) => {
16981
+ resolve(text);
16982
+ });
16833
16983
  });
16834
16984
  }
16835
16985
  mapToPasteNodes() {
@@ -16912,14 +17062,11 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
16912
17062
  }
16913
17063
  try {
16914
17064
  const items = await navigator.clipboard.read();
16915
- if (items && items.length === 1) {
16916
- const item = items[0];
16917
- const position = this.instance.getStage().getRelativePointerPosition();
16918
- if (position) this.instance.emitEvent("onPasteExternal", {
16919
- position,
16920
- item
16921
- });
16922
- }
17065
+ const position = this.instance.getStage().getRelativePointerPosition();
17066
+ if (position) this.instance.emitEvent("onPasteExternal", {
17067
+ position,
17068
+ items
17069
+ });
16923
17070
  } catch (ex) {
16924
17071
  this.instance.emitEvent("onPaste", ex);
16925
17072
  }
@@ -16964,6 +17111,19 @@ var WeaveCopyPasteNodesPlugin = class extends WeavePlugin {
16964
17111
  disable() {
16965
17112
  this.enabled = false;
16966
17113
  }
17114
+ isClipboardAPIAvailable() {
17115
+ return !!navigator.clipboard;
17116
+ }
17117
+ detectBrowser() {
17118
+ const ua = navigator.userAgent;
17119
+ return {
17120
+ isSafari: /^((?!chrome|android).)*safari/i.test(ua),
17121
+ isFirefox: ua.toLowerCase().includes("firefox"),
17122
+ isChrome: ua.toLowerCase().includes("chrome") && !ua.toLowerCase().includes("edge"),
17123
+ isEdge: ua.toLowerCase().includes("edg"),
17124
+ isIOS: /iP(ad|hone|od)/.test(navigator.userAgent)
17125
+ };
17126
+ }
16967
17127
  };
16968
17128
 
16969
17129
  //#endregion
@@ -17099,9 +17259,9 @@ var WeaveNode = class {
17099
17259
  const handleTransform = (e) => {
17100
17260
  const node$1 = e.target;
17101
17261
  const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
17102
- const nodesSnappingPlugin = this.instance.getPlugin("nodesSnapping");
17262
+ const nodesEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
17103
17263
  if (nodesSelectionPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSelectionPlugin.getTransformer().forceUpdate();
17104
- if (nodesSnappingPlugin && transforming && this.isSelecting() && this.isNodeSelected(node$1)) nodesSnappingPlugin.evaluateGuidelines(e);
17264
+ if (nodesEdgeSnappingPlugin && transforming && this.isSelecting() && this.isNodeSelected(node$1)) nodesEdgeSnappingPlugin.evaluateGuidelines(e);
17105
17265
  };
17106
17266
  node.on("transform", (0, import_lodash.throttle)(handleTransform, 100));
17107
17267
  node.on("transformend", (e) => {
@@ -17109,8 +17269,8 @@ var WeaveNode = class {
17109
17269
  this.instance.emitEvent("onTransform", null);
17110
17270
  transforming = false;
17111
17271
  const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
17112
- const nodesSnappingPlugin = this.instance.getPlugin("nodesSnapping");
17113
- if (nodesSnappingPlugin) nodesSnappingPlugin.cleanupEvaluateGuidelines();
17272
+ const nodesSnappingPlugin = this.getNodesEdgeSnappingPlugin();
17273
+ if (nodesSnappingPlugin) nodesSnappingPlugin.cleanupGuidelines();
17114
17274
  if (nodesSelectionPlugin) nodesSelectionPlugin.getTransformer().forceUpdate();
17115
17275
  this.scaleReset(node$1);
17116
17276
  const nodeHandler = this.instance.getNodeHandler(node$1.getAttrs().nodeType);
@@ -17168,8 +17328,10 @@ var WeaveNode = class {
17168
17328
  this.instance.emitEvent("onDrag", null);
17169
17329
  if (this.isSelecting() && this.isNodeSelected(node) && this.getSelectionPlugin()?.getSelectedNodes().length === 1) {
17170
17330
  clearContainerTargets(this.instance);
17171
- const nodesSnappingPlugin = this.instance.getPlugin("nodesSnapping");
17172
- if (nodesSnappingPlugin) nodesSnappingPlugin.cleanupEvaluateGuidelines();
17331
+ const nodesEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
17332
+ const nodesDistanceSnappingPlugin = this.getNodesDistanceSnappingPlugin();
17333
+ if (nodesEdgeSnappingPlugin) nodesEdgeSnappingPlugin.cleanupGuidelines();
17334
+ if (nodesDistanceSnappingPlugin) nodesDistanceSnappingPlugin.cleanupGuidelines();
17173
17335
  const layerToMove = containerOverCursor(this.instance, [node]);
17174
17336
  let containerToMove = this.instance.getMainLayer();
17175
17337
  if (layerToMove) {
@@ -17309,6 +17471,14 @@ var WeaveNode = class {
17309
17471
  ...nodeTransformConfig
17310
17472
  };
17311
17473
  }
17474
+ getNodesEdgeSnappingPlugin() {
17475
+ const snappingPlugin = this.instance.getPlugin(WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY);
17476
+ return snappingPlugin;
17477
+ }
17478
+ getNodesDistanceSnappingPlugin() {
17479
+ const snappingPlugin = this.instance.getPlugin(WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY);
17480
+ return snappingPlugin;
17481
+ }
17312
17482
  };
17313
17483
 
17314
17484
  //#endregion
@@ -18876,7 +19046,7 @@ var WeaveRegisterManager = class {
18876
19046
 
18877
19047
  //#endregion
18878
19048
  //#region package.json
18879
- var version = "0.49.0";
19049
+ var version = "0.51.0";
18880
19050
 
18881
19051
  //#endregion
18882
19052
  //#region src/managers/setup.ts
@@ -20553,8 +20723,10 @@ var WeaveImageToolAction = class extends WeaveAction {
20553
20723
  crossOrigin: "anonymous",
20554
20724
  ...options
20555
20725
  };
20556
- stage.container().style.cursor = "crosshair";
20557
- stage.container().focus();
20726
+ if (!position) {
20727
+ stage.container().style.cursor = "crosshair";
20728
+ stage.container().focus();
20729
+ }
20558
20730
  this.imageId = v4_default();
20559
20731
  this.imageURL = imageURL;
20560
20732
  this.preloadImgs[this.imageId] = new Image();
@@ -20581,8 +20753,10 @@ var WeaveImageToolAction = class extends WeaveAction {
20581
20753
  }
20582
20754
  addImageNode(position) {
20583
20755
  const stage = this.instance.getStage();
20584
- stage.container().style.cursor = "crosshair";
20585
- stage.container().focus();
20756
+ if (!position) {
20757
+ stage.container().style.cursor = "crosshair";
20758
+ stage.container().focus();
20759
+ }
20586
20760
  if (position) {
20587
20761
  this.setState(IMAGE_TOOL_STATE.SELECTED_POSITION);
20588
20762
  this.handleAdding(position);
@@ -25126,11 +25300,6 @@ var WeaveStageGridPlugin = class extends WeavePlugin {
25126
25300
  dotCountY = Math.ceil((endY - startY) / adjustedSpacing);
25127
25301
  }
25128
25302
  this.getAdjustedSpacing(startX, endX, startY, endY, spacing);
25129
- console.log({
25130
- dotCountX,
25131
- dotCountY,
25132
- adjustedSpacing
25133
- });
25134
25303
  startX = Math.floor((offsetX - margin * worldWidth) / adjustedSpacing) * adjustedSpacing;
25135
25304
  startY = Math.floor((offsetY - margin * worldHeight) / adjustedSpacing) * adjustedSpacing;
25136
25305
  const highlightEvery = this.config.gridMajorEvery ?? WEAVE_GRID_DEFAULT_MAJOR_EVERY;
@@ -25838,29 +26007,8 @@ var WeaveStageDropAreaPlugin = class extends WeavePlugin {
25838
26007
  };
25839
26008
 
25840
26009
  //#endregion
25841
- //#region src/plugins/nodes-snapping/constants.ts
25842
- const WEAVE_NODES_SNAPPING_KEY = "nodesSnapping";
25843
- const GUIDE_LINE_NAME = "guide-line";
25844
- const GUIDE_LINE_DEFAULT_CONFIG = {
25845
- stroke: "rgb(0, 161, 255)",
25846
- strokeWidth: 1,
25847
- dash: [4, 6]
25848
- };
25849
- const GUIDE_LINE_DRAG_SNAPPING_THRESHOLD = 10;
25850
- const GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD = 10;
25851
- const GUIDE_ORIENTATION = {
25852
- ["HORIZONTAL"]: "H",
25853
- ["VERTICAL"]: "V"
25854
- };
25855
- const NODE_SNAP = {
25856
- ["START"]: "start",
25857
- ["CENTER"]: "center",
25858
- ["END"]: "end"
25859
- };
25860
-
25861
- //#endregion
25862
- //#region src/plugins/nodes-snapping/nodes-snapping.ts
25863
- var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26010
+ //#region src/plugins/nodes-edge-snapping/nodes-edge-snapping.ts
26011
+ var WeaveNodesEdgeSnappingPlugin = class extends WeavePlugin {
25864
26012
  constructor(params) {
25865
26013
  super();
25866
26014
  const { config } = params ?? {};
@@ -25870,7 +26018,7 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
25870
26018
  this.enabled = true;
25871
26019
  }
25872
26020
  getName() {
25873
- return WEAVE_NODES_SNAPPING_KEY;
26021
+ return WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY;
25874
26022
  }
25875
26023
  onInit() {
25876
26024
  this.initEvents();
@@ -25878,32 +26026,6 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
25878
26026
  setEnabled(enabled) {
25879
26027
  this.enabled = enabled;
25880
26028
  }
25881
- getSelectedNodesMetadata(transformer) {
25882
- const firstNode = transformer.getNodes()[0];
25883
- const firstNodeClientRect = firstNode.getClientRect();
25884
- const rectCoordsMin = {
25885
- x: firstNodeClientRect.x,
25886
- y: firstNodeClientRect.y
25887
- };
25888
- const rectCoordsMax = {
25889
- x: firstNodeClientRect.x + firstNodeClientRect.width,
25890
- y: firstNodeClientRect.y + firstNodeClientRect.height
25891
- };
25892
- const nodes = [];
25893
- for (const node of transformer.getNodes()) {
25894
- const clientRect = node.getClientRect();
25895
- if (clientRect.x < rectCoordsMin.x) rectCoordsMin.x = clientRect.x;
25896
- if (clientRect.y < rectCoordsMin.y) rectCoordsMin.y = clientRect.y;
25897
- if (clientRect.x + clientRect.width > rectCoordsMax.x) rectCoordsMax.x = clientRect.x + clientRect.width;
25898
- if (clientRect.y + clientRect.height > rectCoordsMax.y) rectCoordsMax.y = clientRect.y + clientRect.height;
25899
- nodes.push(node.getAttrs().id);
25900
- }
25901
- return {
25902
- width: rectCoordsMax.x - rectCoordsMin.x,
25903
- height: rectCoordsMax.y - rectCoordsMin.y,
25904
- nodes
25905
- };
25906
- }
25907
26029
  deleteGuides() {
25908
26030
  const utilityLayer = this.instance.getUtilityLayer();
25909
26031
  if (utilityLayer) utilityLayer.find(`.${GUIDE_LINE_NAME}`).forEach((l) => l.destroy());
@@ -25912,87 +26034,73 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
25912
26034
  const utilityLayer = this.instance.getUtilityLayer();
25913
26035
  if (!this.enabled) return;
25914
26036
  if (!utilityLayer) return;
25915
- const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
25916
- let skipNodes = [];
25917
- let node = void 0;
25918
- if (e.type === "dragmove" && nodesSelectionPlugin && nodesSelectionPlugin.getTransformer().nodes().length === 1) {
25919
- node = nodesSelectionPlugin.getTransformer().nodes()[0];
25920
- skipNodes.push(node.getAttrs().id ?? "");
25921
- }
25922
- if (e.type === "dragmove" && nodesSelectionPlugin && nodesSelectionPlugin.getTransformer().nodes().length > 1) {
25923
- const { nodes } = this.getSelectedNodesMetadata(nodesSelectionPlugin.getTransformer());
25924
- node = nodesSelectionPlugin.getTransformer();
25925
- skipNodes = [...nodes];
25926
- }
25927
- if (e.type === "transform") {
25928
- node = e.target;
25929
- skipNodes.push(node.getAttrs().id ?? "");
25930
- }
26037
+ const { targetNode: node, skipNodes } = getTargetAndSkipNodes(this.instance, e);
25931
26038
  if (typeof node === "undefined") return;
25932
- const lineGuideStops = this.getLineGuideStops(skipNodes);
26039
+ const visibleNodes = this.getVisibleNodes(skipNodes);
26040
+ const lineGuideStops = this.getLineGuideStops(visibleNodes);
25933
26041
  const itemBounds = this.getObjectSnappingEdges(node);
25934
26042
  const guides = this.getGuides(lineGuideStops, itemBounds, e.type);
25935
- utilityLayer.destroyChildren();
25936
- if (!guides.length) return;
25937
- utilityLayer.find(`.${GUIDE_LINE_NAME}`).forEach((l) => l.destroy());
25938
- this.drawGuides(guides);
25939
- if (e.type === "dragmove") {
25940
- const orgAbsPos = node.absolutePosition();
25941
- const absPos = node.absolutePosition();
25942
- guides.forEach((lg) => {
25943
- switch (lg.orientation) {
25944
- case GUIDE_ORIENTATION.VERTICAL: {
25945
- absPos.x = lg.lineGuide + lg.offset;
25946
- break;
25947
- }
25948
- case GUIDE_ORIENTATION.HORIZONTAL: {
25949
- absPos.y = lg.lineGuide + lg.offset;
25950
- break;
25951
- }
25952
- }
25953
- });
25954
- const vecDiff = {
25955
- x: orgAbsPos.x - absPos.x,
25956
- y: orgAbsPos.y - absPos.y
25957
- };
25958
- if (node instanceof konva.default.Transformer) node.getNodes().forEach((n) => {
25959
- const nodeAbsPos = n.getAbsolutePosition();
25960
- const newPos = {
25961
- x: nodeAbsPos.x - vecDiff.x,
25962
- y: nodeAbsPos.y - vecDiff.y
25963
- };
25964
- n.setAbsolutePosition(newPos);
25965
- });
25966
- else node.absolutePosition(absPos);
25967
- }
25968
- if (e.type === "transform") {
25969
- const nodesSelectionPlugin$1 = this.instance.getPlugin("nodesSelection");
25970
- if (nodesSelectionPlugin$1) {
25971
- const transformer = nodesSelectionPlugin$1.getTransformer();
25972
- transformer.anchorDragBoundFunc((_, newAbsPos) => {
25973
- const finalPos = { ...newAbsPos };
25974
- for (const lg of guides) switch (lg.orientation) {
26043
+ this.cleanupGuidelines();
26044
+ if (guides.length > 0) {
26045
+ this.drawGuides(guides);
26046
+ if (e.type === "dragmove") {
26047
+ const orgAbsPos = node.absolutePosition();
26048
+ const absPos = node.absolutePosition();
26049
+ guides.forEach((lg) => {
26050
+ switch (lg.orientation) {
25975
26051
  case GUIDE_ORIENTATION.VERTICAL: {
25976
- const distX = Math.sqrt(Math.pow(newAbsPos.x - lg.lineGuide, 2));
25977
- if (distX < this.transformSnappingThreshold) finalPos.x = lg.lineGuide;
26052
+ absPos.x = lg.lineGuide + lg.offset;
25978
26053
  break;
25979
26054
  }
25980
26055
  case GUIDE_ORIENTATION.HORIZONTAL: {
25981
- const distY = Math.sqrt(Math.pow(newAbsPos.y - lg.lineGuide, 2));
25982
- if (distY < this.transformSnappingThreshold) finalPos.y = lg.lineGuide;
26056
+ absPos.y = lg.lineGuide + lg.offset;
25983
26057
  break;
25984
26058
  }
25985
26059
  }
25986
- return finalPos;
25987
26060
  });
26061
+ const vecDiff = {
26062
+ x: orgAbsPos.x - absPos.x,
26063
+ y: orgAbsPos.y - absPos.y
26064
+ };
26065
+ if (node instanceof konva.default.Transformer) node.getNodes().forEach((n) => {
26066
+ const nodeAbsPos = n.getAbsolutePosition();
26067
+ const newPos = {
26068
+ x: nodeAbsPos.x - vecDiff.x,
26069
+ y: nodeAbsPos.y - vecDiff.y
26070
+ };
26071
+ n.setAbsolutePosition(newPos);
26072
+ });
26073
+ else node.absolutePosition(absPos);
26074
+ }
26075
+ if (e.type === "transform") {
26076
+ const nodesSelectionPlugin = this.instance.getPlugin("nodesSelection");
26077
+ if (nodesSelectionPlugin) {
26078
+ const transformer = nodesSelectionPlugin.getTransformer();
26079
+ transformer.anchorDragBoundFunc((_, newAbsPos) => {
26080
+ const finalPos = { ...newAbsPos };
26081
+ for (const lg of guides) switch (lg.orientation) {
26082
+ case GUIDE_ORIENTATION.VERTICAL: {
26083
+ const distX = Math.sqrt(Math.pow(newAbsPos.x - lg.lineGuide, 2));
26084
+ if (distX < this.transformSnappingThreshold) finalPos.x = lg.lineGuide;
26085
+ break;
26086
+ }
26087
+ case GUIDE_ORIENTATION.HORIZONTAL: {
26088
+ const distY = Math.sqrt(Math.pow(newAbsPos.y - lg.lineGuide, 2));
26089
+ if (distY < this.transformSnappingThreshold) finalPos.y = lg.lineGuide;
26090
+ break;
26091
+ }
26092
+ }
26093
+ return finalPos;
26094
+ });
26095
+ }
25988
26096
  }
25989
26097
  }
25990
26098
  }
25991
- cleanupEvaluateGuidelines() {
26099
+ cleanupGuidelines() {
25992
26100
  const utilityLayer = this.instance.getUtilityLayer();
25993
26101
  if (!this.enabled) return;
25994
26102
  if (!utilityLayer) return;
25995
- utilityLayer.destroyChildren();
26103
+ this.deleteGuides();
25996
26104
  }
25997
26105
  initEvents() {
25998
26106
  const stage = this.instance.getStage();
@@ -26002,45 +26110,29 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26002
26110
  this.evaluateGuidelines(e);
26003
26111
  });
26004
26112
  stage.on("dragend", () => {
26005
- this.cleanupEvaluateGuidelines();
26113
+ this.cleanupGuidelines();
26006
26114
  });
26007
26115
  }
26008
26116
  }
26009
- nodeIntersectsViewport(node) {
26010
- const stage = this.instance.getStage();
26011
- const scale = stage.scaleX();
26012
- const stageWidth = stage.width() / scale;
26013
- const stageHeight = stage.height() / scale;
26014
- const viewportRect = {
26015
- x: -stage.x() / scale,
26016
- y: -stage.y() / scale,
26017
- width: stageWidth,
26018
- height: stageHeight
26019
- };
26020
- if (!node.isVisible()) return false;
26021
- const box = node.getClientRect({ relativeTo: stage });
26022
- const intersects = box.x + box.width > viewportRect.x && box.x < viewportRect.x + viewportRect.width && box.y + box.height > viewportRect.y && box.y < viewportRect.y + viewportRect.height;
26023
- return intersects;
26024
- }
26025
- getLineGuideStops(skipNodes) {
26117
+ getVisibleNodes(skipNodes) {
26026
26118
  const stage = this.instance.getStage();
26027
26119
  const nodesSelection = this.instance.getPlugin("nodesSelection");
26028
26120
  if (nodesSelection) nodesSelection.getTransformer().hide();
26029
- const vertical = [
26030
- 0,
26031
- stage.width() / 2,
26032
- stage.width()
26033
- ];
26034
- const horizontal = [
26035
- 0,
26036
- stage.height() / 2,
26037
- stage.height()
26038
- ];
26039
- stage.find(".node").forEach((guideItem) => {
26040
- if (guideItem.getParent()?.getAttrs().nodeType === "group") return;
26041
- if (skipNodes.includes(guideItem.getParent()?.getAttrs().nodeId)) return;
26042
- if (skipNodes.includes(guideItem.getAttrs().id ?? "")) return;
26043
- if (!this.nodeIntersectsViewport(guideItem)) return;
26121
+ const nodes = getVisibleNodesInViewport(stage, this.instance.getMainLayer());
26122
+ const finalVisibleNodes = [];
26123
+ nodes.forEach((node) => {
26124
+ if (node.getParent()?.getAttrs().nodeType === "group") return;
26125
+ if (skipNodes.includes(node.getParent()?.getAttrs().nodeId)) return;
26126
+ if (skipNodes.includes(node.getAttrs().id ?? "")) return;
26127
+ finalVisibleNodes.push(node);
26128
+ });
26129
+ if (nodesSelection) nodesSelection.getTransformer().show();
26130
+ return finalVisibleNodes;
26131
+ }
26132
+ getLineGuideStops(nodes) {
26133
+ const vertical = [];
26134
+ const horizontal = [];
26135
+ nodes.forEach((guideItem) => {
26044
26136
  const box = guideItem.getClientRect({ skipStroke: true });
26045
26137
  vertical.push([
26046
26138
  box.x,
@@ -26053,7 +26145,6 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26053
26145
  box.y + box.height / 2
26054
26146
  ]);
26055
26147
  });
26056
- if (nodesSelection) nodesSelection.getTransformer().show();
26057
26148
  return {
26058
26149
  vertical: vertical.flat(),
26059
26150
  horizontal: horizontal.flat()
@@ -26071,16 +26162,19 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26071
26162
  const snappingEdges = {
26072
26163
  vertical: [
26073
26164
  {
26165
+ nodeId: node.getAttrs().id ?? "",
26074
26166
  guide: box.x,
26075
26167
  offset: Math.round(absPos.x - box.x),
26076
26168
  snap: NODE_SNAP.START
26077
26169
  },
26078
26170
  {
26171
+ nodeId: node.getAttrs().id ?? "",
26079
26172
  guide: box.x + box.width / 2,
26080
26173
  offset: Math.round(absPos.x - box.x - box.width / 2),
26081
26174
  snap: NODE_SNAP.CENTER
26082
26175
  },
26083
26176
  {
26177
+ nodeId: node.getAttrs().id ?? "",
26084
26178
  guide: box.x + box.width,
26085
26179
  offset: Math.round(absPos.x - box.x - box.width),
26086
26180
  snap: NODE_SNAP.END
@@ -26088,16 +26182,19 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26088
26182
  ],
26089
26183
  horizontal: [
26090
26184
  {
26185
+ nodeId: node.getAttrs().id ?? "",
26091
26186
  guide: Math.round(box.y),
26092
26187
  offset: Math.round(absPos.y - box.y),
26093
26188
  snap: NODE_SNAP.START
26094
26189
  },
26095
26190
  {
26191
+ nodeId: node.getAttrs().id ?? "",
26096
26192
  guide: Math.round(box.y + box.height / 2),
26097
26193
  offset: Math.round(absPos.y - box.y - box.height / 2),
26098
26194
  snap: NODE_SNAP.CENTER
26099
26195
  },
26100
26196
  {
26197
+ nodeId: node.getAttrs().id ?? "",
26101
26198
  guide: Math.round(box.y + box.height),
26102
26199
  offset: Math.round(absPos.y - box.y - box.height),
26103
26200
  snap: NODE_SNAP.END
@@ -26107,34 +26204,45 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26107
26204
  return snappingEdges;
26108
26205
  }
26109
26206
  getGuides(lineGuideStops, itemBounds, type) {
26207
+ const resultMapV = new Map();
26208
+ const resultMapH = new Map();
26110
26209
  const resultV = [];
26111
26210
  const resultH = [];
26112
26211
  lineGuideStops.vertical.forEach((lineGuide) => {
26113
26212
  itemBounds.vertical.forEach((itemBound) => {
26114
26213
  const diff = Math.abs(lineGuide - itemBound.guide);
26115
- if (diff < this.dragSnappingThreshold) resultV.push({
26116
- lineGuide,
26117
- diff,
26118
- snap: itemBound.snap,
26119
- offset: itemBound.offset
26120
- });
26214
+ if (diff < this.dragSnappingThreshold && !resultMapV.has(itemBound.nodeId)) {
26215
+ const guide = {
26216
+ nodeId: itemBound.nodeId,
26217
+ lineGuide,
26218
+ diff,
26219
+ snap: itemBound.snap,
26220
+ offset: itemBound.offset
26221
+ };
26222
+ resultMapV.set(itemBound.nodeId, guide);
26223
+ resultV.push(guide);
26224
+ }
26121
26225
  });
26122
26226
  });
26123
26227
  lineGuideStops.horizontal.forEach((lineGuide) => {
26124
26228
  itemBounds.horizontal.forEach((itemBound) => {
26125
26229
  const diff = Math.abs(lineGuide - itemBound.guide);
26126
- if (diff < this.dragSnappingThreshold) resultH.push({
26127
- lineGuide,
26128
- diff,
26129
- snap: itemBound.snap,
26130
- offset: itemBound.offset
26131
- });
26230
+ if (diff < this.dragSnappingThreshold && !resultMapH.has(itemBound.nodeId)) {
26231
+ const guide = {
26232
+ nodeId: itemBound.nodeId,
26233
+ lineGuide,
26234
+ diff,
26235
+ snap: itemBound.snap,
26236
+ offset: itemBound.offset
26237
+ };
26238
+ resultMapH.set(itemBound.nodeId, guide);
26239
+ resultH.push(guide);
26240
+ }
26132
26241
  });
26133
26242
  });
26134
26243
  const guides = [];
26135
26244
  if (type === "dragmove") {
26136
- const minV = resultV.sort((a, b) => a.diff - b.diff)[0];
26137
- const minH = resultH.sort((a, b) => a.diff - b.diff)[0];
26245
+ const { minH, minV } = this.sortedGuides(resultH, resultV);
26138
26246
  if (minV) guides.push({
26139
26247
  lineGuide: minV.lineGuide,
26140
26248
  offset: minV.offset,
@@ -26168,6 +26276,14 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26168
26276
  }
26169
26277
  return guides;
26170
26278
  }
26279
+ sortedGuides(resultH, resultV) {
26280
+ const minV = resultV.toSorted((a, b) => a.diff - b.diff)[0];
26281
+ const minH = resultH.toSorted((a, b) => a.diff - b.diff)[0];
26282
+ return {
26283
+ minH,
26284
+ minV
26285
+ };
26286
+ }
26171
26287
  drawGuides(guides) {
26172
26288
  const stage = this.instance.getStage();
26173
26289
  const utilityLayer = this.instance.getUtilityLayer();
@@ -26220,6 +26336,518 @@ var WeaveNodesSnappingPlugin = class extends WeavePlugin {
26220
26336
  }
26221
26337
  };
26222
26338
 
26339
+ //#endregion
26340
+ //#region src/plugins/nodes-distance-snapping/nodes-distance-snapping.ts
26341
+ var WeaveNodesDistanceSnappingPlugin = class extends WeavePlugin {
26342
+ peerDistanceX = null;
26343
+ peerDistanceY = null;
26344
+ snapPositionX = null;
26345
+ snapPositionY = null;
26346
+ currentSizeSnapHorizontal = null;
26347
+ currentSizeSnapVertical = null;
26348
+ constructor(params) {
26349
+ super();
26350
+ const { config } = params ?? {};
26351
+ this.enterSnappingTolerance = config?.enterSnappingTolerance ?? GUIDE_ENTER_SNAPPING_TOLERANCE;
26352
+ this.exitSnappingTolerance = config?.exitSnappingTolerance ?? GUIDE_EXIT_SNAPPING_TOLERANCE;
26353
+ this.enabled = true;
26354
+ }
26355
+ getName() {
26356
+ return WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY;
26357
+ }
26358
+ onInit() {
26359
+ this.initEvents();
26360
+ }
26361
+ setEnabled(enabled) {
26362
+ this.enabled = enabled;
26363
+ }
26364
+ deleteGuides() {
26365
+ const utilityLayer = this.instance.getUtilityLayer();
26366
+ if (utilityLayer) {
26367
+ utilityLayer.find(`.${GUIDE_HORIZONTAL_LINE_NAME}`).forEach((l) => l.destroy());
26368
+ utilityLayer.find(`.${GUIDE_VERTICAL_LINE_NAME}`).forEach((l) => l.destroy());
26369
+ }
26370
+ }
26371
+ evaluateGuidelines(e) {
26372
+ const stage = this.instance.getStage();
26373
+ const mainLayer = this.instance.getMainLayer();
26374
+ const utilityLayer = this.instance.getUtilityLayer();
26375
+ if (!this.enabled) return;
26376
+ if (!utilityLayer) return;
26377
+ const { targetNode: node, skipNodes } = getTargetAndSkipNodes(this.instance, e);
26378
+ if (typeof node === "undefined") return;
26379
+ if (node.getParent() === mainLayer) this.referenceLayer = mainLayer;
26380
+ if (node.getParent()?.getAttrs().nodeId) {
26381
+ const realNode = stage.findOne(`#${node.getParent()?.getAttrs().nodeId}`);
26382
+ if (realNode) this.referenceLayer = realNode;
26383
+ }
26384
+ const visibleNodes = this.getVisibleNodes(skipNodes);
26385
+ const { intersectedNodes: sortedHorizontalIntersectedNodes, intersectedNodesWithDistances: horizontalIntersectedNodes } = this.getHorizontallyIntersectingNodes(node, visibleNodes);
26386
+ const { intersectedNodes: sortedVerticalIntersectedNodes, intersectedNodesWithDistances: verticalIntersectedNodes } = this.getVerticallyIntersectingNodes(node, visibleNodes);
26387
+ this.cleanupGuidelines();
26388
+ if (horizontalIntersectedNodes.length > 0 || verticalIntersectedNodes.length > 0) {
26389
+ if (e.type === "dragmove") {
26390
+ this.validateHorizontalSnapping(node, visibleNodes, sortedHorizontalIntersectedNodes, horizontalIntersectedNodes);
26391
+ this.validateVerticalSnapping(node, visibleNodes, sortedVerticalIntersectedNodes, verticalIntersectedNodes);
26392
+ }
26393
+ }
26394
+ }
26395
+ getBoxClientRect(node) {
26396
+ const stage = this.instance.getStage();
26397
+ return node.getClientRect({
26398
+ relativeTo: stage,
26399
+ skipStroke: true,
26400
+ skipShadow: true
26401
+ });
26402
+ }
26403
+ getPeers(intersectedNodes, targetNode, prev, next) {
26404
+ const peers = intersectedNodes.filter((int) => {
26405
+ if (prev && next) return int.to.getAttrs().id !== targetNode.getAttrs().id && int.from.getAttrs().id !== targetNode.getAttrs().id;
26406
+ if (!prev && next) return int.from.getAttrs().id !== targetNode.getAttrs().id;
26407
+ return int.to.getAttrs().id !== targetNode.getAttrs().id;
26408
+ });
26409
+ let prevBox = null;
26410
+ if (prev) prevBox = this.getBoxClientRect(prev);
26411
+ let nextBox = null;
26412
+ if (next) nextBox = this.getBoxClientRect(next);
26413
+ return {
26414
+ prevBox,
26415
+ nextBox,
26416
+ peers
26417
+ };
26418
+ }
26419
+ validateHorizontalSnapping(node, visibleNodes, sortedHorizontalIntersectedNodes, horizontalIntersectedNodes) {
26420
+ const box = this.getBoxClientRect(node);
26421
+ const targetIndex = sortedHorizontalIntersectedNodes.findIndex((actNode) => actNode.getAttrs().id === node.getAttrs().id);
26422
+ const prev = sortedHorizontalIntersectedNodes[targetIndex - 1];
26423
+ const next = sortedHorizontalIntersectedNodes[targetIndex + 1];
26424
+ const { prevBox, nextBox, peers } = this.getPeers(horizontalIntersectedNodes, node, prev, next);
26425
+ if (this.currentSizeSnapHorizontal === NODE_SNAP_HORIZONTAL.LEFT && prev && prevBox) {
26426
+ const dist = Math.round(box.x - (prevBox.x + prevBox.width));
26427
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.exitSnappingTolerance);
26428
+ if (!match) this.currentSizeSnapHorizontal = null;
26429
+ }
26430
+ if (this.currentSizeSnapHorizontal === NODE_SNAP_HORIZONTAL.RIGHT && next && nextBox) {
26431
+ const dist = Math.round(nextBox.x - (box.x + box.width));
26432
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.exitSnappingTolerance);
26433
+ if (!match) this.currentSizeSnapHorizontal = null;
26434
+ }
26435
+ if (prev && prevBox && next && nextBox && prevBox.x + prevBox.width <= box.x && box.x + box.width <= nextBox.x) {
26436
+ const distanceToPrev = box.x - (prevBox.x + prevBox.width);
26437
+ const distanceToNext = nextBox.x - (box.x + box.width);
26438
+ const delta = Math.abs(distanceToPrev - distanceToNext);
26439
+ if (delta <= this.enterSnappingTolerance) {
26440
+ const center = (prevBox.x + prevBox.width + nextBox.x) / 2;
26441
+ const newX = center - box.width / 2;
26442
+ this.setNodeClientRectX(node, newX);
26443
+ this.snapPositionX = node.x();
26444
+ this.currentSizeSnapHorizontal = NODE_SNAP_HORIZONTAL.CENTER;
26445
+ const newBox = this.getBoxClientRect(node);
26446
+ this.peerDistanceX = Math.round(newBox.x - (prevBox.x + prevBox.width));
26447
+ }
26448
+ if (this.currentSizeSnapHorizontal === NODE_SNAP_HORIZONTAL.CENTER && delta > this.exitSnappingTolerance) this.currentSizeSnapHorizontal = null;
26449
+ }
26450
+ if (this.currentSizeSnapHorizontal && this.peerDistanceX && this.snapPositionX) {
26451
+ node.x(this.snapPositionX);
26452
+ const { intersectedNodesWithDistances: newHorizontalIntersectedNodes } = this.getHorizontallyIntersectingNodes(node, visibleNodes);
26453
+ this.drawSizeGuidesHorizontally(newHorizontalIntersectedNodes, this.peerDistanceX);
26454
+ return;
26455
+ }
26456
+ const canSnapLeft = prev && prevBox && (() => {
26457
+ const dist = Math.round(box.x - (prevBox.x + prevBox.width));
26458
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.enterSnappingTolerance);
26459
+ if (match) {
26460
+ const newX = prevBox.x + prevBox.width + match.distance;
26461
+ this.setNodeClientRectX(node, newX);
26462
+ this.snapPositionX = node.x();
26463
+ this.currentSizeSnapHorizontal = NODE_SNAP_HORIZONTAL.LEFT;
26464
+ const newBox = this.getBoxClientRect(node);
26465
+ this.peerDistanceX = Math.round(newBox.x - (prevBox.x + prevBox.width));
26466
+ return true;
26467
+ }
26468
+ return false;
26469
+ })();
26470
+ if (!canSnapLeft && next && nextBox) {
26471
+ const dist = Math.round(nextBox.x - (box.x + box.width));
26472
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.enterSnappingTolerance);
26473
+ if (match) {
26474
+ const newX = nextBox.x - match.distance - box.width;
26475
+ this.setNodeClientRectX(node, newX);
26476
+ this.snapPositionX = node.x();
26477
+ const newBox = this.getBoxClientRect(node);
26478
+ this.peerDistanceX = Math.round(nextBox.x - (newBox.x + newBox.width));
26479
+ this.currentSizeSnapHorizontal = NODE_SNAP_HORIZONTAL.RIGHT;
26480
+ }
26481
+ }
26482
+ }
26483
+ validateVerticalSnapping(node, visibleNodes, sortedVerticalIntersectedNodes, verticalIntersectedNodes) {
26484
+ const box = this.getBoxClientRect(node);
26485
+ const targetIndex = sortedVerticalIntersectedNodes.findIndex((actNode) => actNode.getAttrs().id === node.getAttrs().id);
26486
+ const prev = sortedVerticalIntersectedNodes[targetIndex - 1];
26487
+ const next = sortedVerticalIntersectedNodes[targetIndex + 1];
26488
+ const { prevBox, nextBox, peers } = this.getPeers(verticalIntersectedNodes, node, prev, next);
26489
+ if (this.currentSizeSnapVertical === NODE_SNAP_VERTICAL.TOP && prev && prevBox) {
26490
+ const dist = Math.round(box.y - (prevBox.y + prevBox.height));
26491
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.exitSnappingTolerance);
26492
+ if (!match) this.currentSizeSnapVertical = null;
26493
+ }
26494
+ if (this.currentSizeSnapVertical === NODE_SNAP_VERTICAL.BOTTOM && next && nextBox) {
26495
+ const dist = Math.round(nextBox.y - (box.y + box.height));
26496
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.exitSnappingTolerance);
26497
+ if (!match) this.currentSizeSnapVertical = null;
26498
+ }
26499
+ if (prev && prevBox && next && nextBox && prevBox.y + prevBox.height <= box.y && box.y + box.height <= nextBox.y) {
26500
+ const distanceToPrev = box.y - (prevBox.y + prevBox.height);
26501
+ const distanceToNext = nextBox.y - (box.y + box.height);
26502
+ const delta = Math.abs(distanceToPrev - distanceToNext);
26503
+ if (delta <= this.enterSnappingTolerance) {
26504
+ const center = (prevBox.y + prevBox.height + nextBox.y) / 2;
26505
+ const newY = center - box.height / 2;
26506
+ this.setNodeClientRectY(node, newY);
26507
+ this.snapPositionY = node.y();
26508
+ this.currentSizeSnapVertical = NODE_SNAP_VERTICAL.MIDDLE;
26509
+ const newBox = this.getBoxClientRect(node);
26510
+ this.peerDistanceY = Math.round(newBox.y - (prevBox.y + prevBox.height));
26511
+ }
26512
+ if (this.currentSizeSnapVertical === NODE_SNAP_VERTICAL.MIDDLE && delta > this.exitSnappingTolerance) this.currentSizeSnapVertical = null;
26513
+ }
26514
+ if (this.currentSizeSnapVertical && this.peerDistanceY && this.snapPositionY) {
26515
+ node.y(this.snapPositionY);
26516
+ const { intersectedNodesWithDistances: newVerticalIntersectedNodes } = this.getVerticallyIntersectingNodes(node, visibleNodes);
26517
+ this.drawSizeGuidesVertically(newVerticalIntersectedNodes, this.peerDistanceY);
26518
+ return;
26519
+ }
26520
+ const canSnapTop = prev && prevBox && (() => {
26521
+ const dist = Math.round(box.y - (prevBox.y + prevBox.height));
26522
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.enterSnappingTolerance);
26523
+ if (match) {
26524
+ const newY = prevBox.y + prevBox.height + match.distance;
26525
+ this.setNodeClientRectY(node, newY);
26526
+ this.snapPositionY = node.y();
26527
+ this.currentSizeSnapVertical = NODE_SNAP_VERTICAL.TOP;
26528
+ const newBox = this.getBoxClientRect(node);
26529
+ this.peerDistanceY = Math.round(newBox.y - (prevBox.y + prevBox.height));
26530
+ return true;
26531
+ }
26532
+ return false;
26533
+ })();
26534
+ if (!canSnapTop && next && nextBox) {
26535
+ const dist = Math.round(nextBox.y - (box.y + box.height));
26536
+ const match = peers.find((d) => Math.abs(d.distance - dist) <= this.enterSnappingTolerance);
26537
+ if (match) {
26538
+ const newY = nextBox.y - match.distance - box.height;
26539
+ this.setNodeClientRectY(node, newY);
26540
+ this.snapPositionY = node.y();
26541
+ const newBox = this.getBoxClientRect(node);
26542
+ this.peerDistanceY = Math.round(nextBox.y - (newBox.y + newBox.height));
26543
+ this.currentSizeSnapVertical = NODE_SNAP_VERTICAL.BOTTOM;
26544
+ }
26545
+ }
26546
+ }
26547
+ setNodeClientRectX(node, snappedClientX) {
26548
+ if (node.getParent()?.getType() === "Layer") {
26549
+ node.x(snappedClientX);
26550
+ return;
26551
+ }
26552
+ const box = this.getBoxClientRect(node);
26553
+ const absolutePos = node.getAbsolutePosition();
26554
+ const offsetX = absolutePos.x - box.x;
26555
+ const newAbsX = snappedClientX + offsetX;
26556
+ const parent = node.getParent();
26557
+ if (!parent) {
26558
+ console.warn("Node has no parent to set position");
26559
+ return;
26560
+ }
26561
+ const local = parent.getAbsoluteTransform().copy().invert().point({
26562
+ x: newAbsX,
26563
+ y: absolutePos.y
26564
+ });
26565
+ node.position({
26566
+ x: local.x,
26567
+ y: node.y()
26568
+ });
26569
+ }
26570
+ setNodeClientRectY(node, snappedClientY) {
26571
+ if (node.getParent()?.getType() === "Layer") {
26572
+ node.y(snappedClientY);
26573
+ return;
26574
+ }
26575
+ const box = this.getBoxClientRect(node);
26576
+ const absolutePos = node.getAbsolutePosition();
26577
+ const offsetY = absolutePos.y - box.y;
26578
+ const newAbsY = snappedClientY + offsetY;
26579
+ const parent = node.getParent();
26580
+ if (!parent) {
26581
+ console.warn("Node has no parent to set position");
26582
+ return;
26583
+ }
26584
+ const local = parent.getAbsoluteTransform().copy().invert().point({
26585
+ x: absolutePos.x,
26586
+ y: newAbsY
26587
+ });
26588
+ node.position({
26589
+ x: node.x(),
26590
+ y: local.y
26591
+ });
26592
+ }
26593
+ cleanupGuidelines() {
26594
+ const utilityLayer = this.instance.getUtilityLayer();
26595
+ if (!this.enabled) return;
26596
+ if (!utilityLayer) return;
26597
+ this.deleteGuides();
26598
+ }
26599
+ initEvents() {
26600
+ const stage = this.instance.getStage();
26601
+ const utilityLayer = this.instance.getUtilityLayer();
26602
+ if (utilityLayer) {
26603
+ stage.on("dragmove", (e) => {
26604
+ this.evaluateGuidelines(e);
26605
+ });
26606
+ stage.on("dragend", () => {
26607
+ this.peerDistanceX = null;
26608
+ this.peerDistanceY = null;
26609
+ this.currentSizeSnapVertical = null;
26610
+ this.currentSizeSnapHorizontal = null;
26611
+ this.cleanupGuidelines();
26612
+ });
26613
+ }
26614
+ }
26615
+ getVerticallyIntersectingNodes(targetNode, nodes) {
26616
+ const targetBox = this.getBoxClientRect(targetNode);
26617
+ const intersectedNodes = [];
26618
+ nodes.forEach((node) => {
26619
+ if (node === targetNode || !node.isVisible()) return false;
26620
+ const box = this.getBoxClientRect(node);
26621
+ const horizontalOverlap = box.x + box.width > targetBox.x && box.x < targetBox.x + targetBox.width;
26622
+ if (horizontalOverlap) intersectedNodes.push(node);
26623
+ });
26624
+ intersectedNodes.push(targetNode);
26625
+ intersectedNodes.sort((a, b) => {
26626
+ const ay = this.getBoxClientRect(a).y;
26627
+ const by = this.getBoxClientRect(b).y;
26628
+ return ay - by;
26629
+ });
26630
+ const intersectedNodesWithDistances = [];
26631
+ for (let i = 0; i < intersectedNodes.length - 1; i++) {
26632
+ const a = intersectedNodes[i];
26633
+ const b = intersectedNodes[i + 1];
26634
+ const boxA = this.getBoxClientRect(a);
26635
+ const boxB = this.getBoxClientRect(b);
26636
+ const aBottom = boxA.y + boxA.height;
26637
+ const bTop = boxB.y;
26638
+ const distance = Math.abs(aBottom - bTop);
26639
+ const left = Math.max(boxA.x, boxB.x);
26640
+ const right = Math.min(boxA.x + boxA.width, boxB.x + boxB.width);
26641
+ let midX;
26642
+ if (right > left) midX = left + (right - left) / 2;
26643
+ else {
26644
+ const aCenterX = boxA.x + boxA.width / 2;
26645
+ const bCenterX = boxB.x + boxB.width / 2;
26646
+ midX = (aCenterX + bCenterX) / 2;
26647
+ }
26648
+ intersectedNodesWithDistances.push({
26649
+ index: i,
26650
+ from: a,
26651
+ to: b,
26652
+ midX,
26653
+ distance: Math.round(distance)
26654
+ });
26655
+ }
26656
+ return {
26657
+ intersectedNodes,
26658
+ intersectedNodesWithDistances
26659
+ };
26660
+ }
26661
+ getHorizontallyIntersectingNodes(targetNode, nodes) {
26662
+ const targetBox = this.getBoxClientRect(targetNode);
26663
+ const intersectedNodes = [];
26664
+ nodes.forEach((node) => {
26665
+ if (node === targetNode || !node.isVisible()) return false;
26666
+ const box = this.getBoxClientRect(node);
26667
+ const verticalOverlap = box.y + box.height > targetBox.y && box.y < targetBox.y + targetBox.height;
26668
+ if (verticalOverlap) intersectedNodes.push(node);
26669
+ });
26670
+ intersectedNodes.push(targetNode);
26671
+ intersectedNodes.sort((a, b) => {
26672
+ const ax = this.getBoxClientRect(a).x;
26673
+ const bx = this.getBoxClientRect(b).x;
26674
+ return ax - bx;
26675
+ });
26676
+ const intersectedNodesWithDistances = [];
26677
+ for (let i = 0; i < intersectedNodes.length - 1; i++) {
26678
+ const a = intersectedNodes[i];
26679
+ const b = intersectedNodes[i + 1];
26680
+ const boxA = this.getBoxClientRect(a);
26681
+ const boxB = this.getBoxClientRect(b);
26682
+ const aRight = boxA.x + boxA.width;
26683
+ const bLeft = boxB.x;
26684
+ const distance = Math.abs(Math.round(aRight - bLeft));
26685
+ const top = Math.max(boxA.y, boxB.y);
26686
+ const bottom = Math.min(boxA.y + boxA.height, boxB.y + boxB.height);
26687
+ let midY;
26688
+ if (bottom > top) midY = top + (bottom - top) / 2;
26689
+ else {
26690
+ const aCenterY = boxA.y + boxA.height / 2;
26691
+ const bCenterY = boxB.y + boxB.height / 2;
26692
+ midY = (aCenterY + bCenterY) / 2;
26693
+ }
26694
+ intersectedNodesWithDistances.push({
26695
+ index: i,
26696
+ from: a,
26697
+ to: b,
26698
+ midY,
26699
+ distance
26700
+ });
26701
+ }
26702
+ return {
26703
+ intersectedNodes,
26704
+ intersectedNodesWithDistances
26705
+ };
26706
+ }
26707
+ getVisibleNodes(skipNodes) {
26708
+ const stage = this.instance.getStage();
26709
+ const nodesSelection = this.instance.getPlugin("nodesSelection");
26710
+ if (nodesSelection) nodesSelection.getTransformer().hide();
26711
+ const nodes = getVisibleNodesInViewport(stage, this.referenceLayer);
26712
+ const finalVisibleNodes = [];
26713
+ nodes.forEach((node) => {
26714
+ if (node.getParent()?.getAttrs().nodeType === "group") return;
26715
+ if (skipNodes.includes(node.getParent()?.getAttrs().nodeId)) return;
26716
+ if (skipNodes.includes(node.getAttrs().id ?? "")) return;
26717
+ if (node.getParent() !== this.referenceLayer && !node.getParent()?.getAttrs().nodeId) return;
26718
+ if (node.getParent() !== this.referenceLayer && node.getParent()?.getAttrs().nodeId) {
26719
+ const realNode = stage.findOne(`#${node.getParent()?.getAttrs().nodeId}`);
26720
+ if (realNode && realNode !== this.referenceLayer) return;
26721
+ }
26722
+ finalVisibleNodes.push(node);
26723
+ });
26724
+ if (nodesSelection) nodesSelection.getTransformer().show();
26725
+ return finalVisibleNodes;
26726
+ }
26727
+ drawSizeGuidesHorizontally(intersectionsH, peerDistance) {
26728
+ const utilityLayer = this.instance.getUtilityLayer();
26729
+ if (utilityLayer) intersectionsH.forEach((pairInfo) => {
26730
+ const from = this.getBoxClientRect(pairInfo.from);
26731
+ const to = this.getBoxClientRect(pairInfo.to);
26732
+ if (pairInfo.distance === peerDistance) this.renderHorizontalLineWithDistanceBetweenNodes(from, to, pairInfo.midY, `${pairInfo.distance}`);
26733
+ });
26734
+ }
26735
+ drawSizeGuidesVertically(intersectionsV, peerDistance) {
26736
+ const utilityLayer = this.instance.getUtilityLayer();
26737
+ if (utilityLayer) intersectionsV.forEach((pairInfo) => {
26738
+ const from = this.getBoxClientRect(pairInfo.from);
26739
+ const to = this.getBoxClientRect(pairInfo.to);
26740
+ if (pairInfo.distance === peerDistance) this.renderVerticalLineWithDistanceBetweenNodes(from, to, pairInfo.midX, `${pairInfo.distance}`);
26741
+ });
26742
+ }
26743
+ renderDistanceLabel(ctx, stage, labelText, { canvasMidX, canvasMidY }) {
26744
+ const scaleX = stage?.scaleX() || 1;
26745
+ const scaleY = stage?.scaleY() || 1;
26746
+ const fontSize = 12;
26747
+ const fontFamily = "Arial";
26748
+ const padding = 6;
26749
+ const tempText = new konva.default.Text({
26750
+ text: labelText,
26751
+ fontSize,
26752
+ fontFamily,
26753
+ visible: false
26754
+ });
26755
+ const textWidth = tempText.width();
26756
+ const textHeight = tempText.height();
26757
+ const labelWidth = textWidth + padding * 2;
26758
+ const labelHeight = textHeight + padding * 2;
26759
+ ctx.save();
26760
+ ctx.scale(1 / scaleX, 1 / scaleY);
26761
+ const labelX = canvasMidX - labelWidth / 2;
26762
+ const labelY = canvasMidY - labelHeight / 2;
26763
+ ctx.beginPath();
26764
+ ctx.rect(labelX, labelY, labelWidth, labelHeight);
26765
+ ctx.fillStyle = "#ff0000";
26766
+ ctx.fill();
26767
+ ctx.font = `bold ${fontSize}px ${fontFamily}`;
26768
+ ctx.fillStyle = "white";
26769
+ ctx.textAlign = "center";
26770
+ ctx.textBaseline = "middle";
26771
+ ctx.fillText(labelText, canvasMidX, labelY + labelHeight / 2);
26772
+ ctx.restore();
26773
+ }
26774
+ renderHorizontalLineWithDistanceBetweenNodes(from, to, midY, labelText) {
26775
+ const utilityLayer = this.instance.getUtilityLayer();
26776
+ const renderLabel = this.renderDistanceLabel;
26777
+ const lineWithLabel = new konva.default.Shape({
26778
+ name: GUIDE_HORIZONTAL_LINE_NAME,
26779
+ sceneFunc: function(ctx, shape) {
26780
+ const stage = shape.getStage();
26781
+ const scaleX = stage?.scaleX() || 1;
26782
+ const scaleY = stage?.scaleY() || 1;
26783
+ const x1 = from.x + from.width;
26784
+ const x2 = to.x;
26785
+ const y = midY;
26786
+ ctx.beginPath();
26787
+ ctx.moveTo(x1, y);
26788
+ ctx.lineTo(x2, y);
26789
+ ctx.closePath();
26790
+ ctx.strokeStyle = "#ff0000";
26791
+ ctx.lineWidth = 1;
26792
+ ctx.setLineDash([]);
26793
+ ctx.stroke();
26794
+ ctx.closePath();
26795
+ const worldMidX = (x1 + x2) / 2;
26796
+ const worldMidY = y;
26797
+ const canvasMidX = worldMidX * scaleX;
26798
+ const canvasMidY = worldMidY * scaleY;
26799
+ renderLabel(ctx, stage, labelText, {
26800
+ canvasMidX,
26801
+ canvasMidY
26802
+ });
26803
+ ctx.fillStrokeShape(shape);
26804
+ }
26805
+ });
26806
+ lineWithLabel.moveToBottom();
26807
+ utilityLayer?.add(lineWithLabel);
26808
+ }
26809
+ renderVerticalLineWithDistanceBetweenNodes(from, to, midX, labelText) {
26810
+ const utilityLayer = this.instance.getUtilityLayer();
26811
+ const renderLabel = this.renderDistanceLabel;
26812
+ const lineWithLabel = new konva.default.Shape({
26813
+ name: GUIDE_VERTICAL_LINE_NAME,
26814
+ sceneFunc: function(ctx, shape) {
26815
+ const stage = shape.getStage();
26816
+ const scaleX = stage?.scaleX() || 1;
26817
+ const scaleY = stage?.scaleY() || 1;
26818
+ const x = midX;
26819
+ const y1 = from.y + from.height;
26820
+ const y2 = to.y;
26821
+ ctx.beginPath();
26822
+ ctx.setLineDash([]);
26823
+ ctx.moveTo(x, y1);
26824
+ ctx.lineTo(x, y2);
26825
+ ctx.strokeStyle = "#ff0000";
26826
+ ctx.lineWidth = 1;
26827
+ ctx.stroke();
26828
+ ctx.closePath();
26829
+ const worldMidX = x;
26830
+ const worldMidY = (y1 + y2) / 2;
26831
+ const canvasMidX = worldMidX * scaleX;
26832
+ const canvasMidY = worldMidY * scaleY;
26833
+ renderLabel(ctx, stage, labelText, {
26834
+ canvasMidX,
26835
+ canvasMidY
26836
+ });
26837
+ ctx.fillStrokeShape(shape);
26838
+ }
26839
+ });
26840
+ lineWithLabel.moveToBottom();
26841
+ utilityLayer?.add(lineWithLabel);
26842
+ }
26843
+ enable() {
26844
+ this.enabled = true;
26845
+ }
26846
+ disable() {
26847
+ this.enabled = false;
26848
+ }
26849
+ };
26850
+
26223
26851
  //#endregion
26224
26852
  exports.ALIGN_NODES_ALIGN_TO = ALIGN_NODES_ALIGN_TO
26225
26853
  exports.ALIGN_NODES_TOOL_ACTION_NAME = ALIGN_NODES_TOOL_ACTION_NAME
@@ -26235,16 +26863,22 @@ exports.ERASER_TOOL_ACTION_NAME = ERASER_TOOL_ACTION_NAME
26235
26863
  exports.ERASER_TOOL_STATE = ERASER_TOOL_STATE
26236
26864
  exports.FRAME_TOOL_ACTION_NAME = FRAME_TOOL_ACTION_NAME
26237
26865
  exports.FRAME_TOOL_STATE = FRAME_TOOL_STATE
26866
+ exports.GUIDE_ENTER_SNAPPING_TOLERANCE = GUIDE_ENTER_SNAPPING_TOLERANCE
26867
+ exports.GUIDE_EXIT_SNAPPING_TOLERANCE = GUIDE_EXIT_SNAPPING_TOLERANCE
26868
+ exports.GUIDE_HORIZONTAL_LINE_NAME = GUIDE_HORIZONTAL_LINE_NAME
26238
26869
  exports.GUIDE_LINE_DEFAULT_CONFIG = GUIDE_LINE_DEFAULT_CONFIG
26239
26870
  exports.GUIDE_LINE_DRAG_SNAPPING_THRESHOLD = GUIDE_LINE_DRAG_SNAPPING_THRESHOLD
26240
26871
  exports.GUIDE_LINE_NAME = GUIDE_LINE_NAME
26241
26872
  exports.GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD = GUIDE_LINE_TRANSFORM_SNAPPING_THRESHOLD
26242
26873
  exports.GUIDE_ORIENTATION = GUIDE_ORIENTATION
26874
+ exports.GUIDE_VERTICAL_LINE_NAME = GUIDE_VERTICAL_LINE_NAME
26243
26875
  exports.IMAGE_TOOL_ACTION_NAME = IMAGE_TOOL_ACTION_NAME
26244
26876
  exports.IMAGE_TOOL_STATE = IMAGE_TOOL_STATE
26245
26877
  exports.MOVE_TOOL_ACTION_NAME = MOVE_TOOL_ACTION_NAME
26246
26878
  exports.MOVE_TOOL_STATE = MOVE_TOOL_STATE
26247
26879
  exports.NODE_SNAP = NODE_SNAP
26880
+ exports.NODE_SNAP_HORIZONTAL = NODE_SNAP_HORIZONTAL
26881
+ exports.NODE_SNAP_VERTICAL = NODE_SNAP_VERTICAL
26248
26882
  exports.PEN_TOOL_ACTION_NAME = PEN_TOOL_ACTION_NAME
26249
26883
  exports.PEN_TOOL_STATE = PEN_TOOL_STATE
26250
26884
  exports.RECTANGLE_TOOL_ACTION_NAME = RECTANGLE_TOOL_ACTION_NAME
@@ -26283,9 +26917,10 @@ exports.WEAVE_IMAGE_CROP_END_TYPE = WEAVE_IMAGE_CROP_END_TYPE
26283
26917
  exports.WEAVE_IMAGE_NODE_TYPE = WEAVE_IMAGE_NODE_TYPE
26284
26918
  exports.WEAVE_LAYER_NODE_TYPE = WEAVE_LAYER_NODE_TYPE
26285
26919
  exports.WEAVE_LINE_NODE_TYPE = WEAVE_LINE_NODE_TYPE
26920
+ exports.WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY = WEAVE_NODES_DISTANCE_SNAPPING_PLUGIN_KEY
26921
+ exports.WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY = WEAVE_NODES_EDGE_SNAPPING_PLUGIN_KEY
26286
26922
  exports.WEAVE_NODES_SELECTION_KEY = WEAVE_NODES_SELECTION_KEY
26287
26923
  exports.WEAVE_NODES_SELECTION_LAYER_ID = WEAVE_NODES_SELECTION_LAYER_ID
26288
- exports.WEAVE_NODES_SNAPPING_KEY = WEAVE_NODES_SNAPPING_KEY
26289
26924
  exports.WEAVE_RECTANGLE_NODE_TYPE = WEAVE_RECTANGLE_NODE_TYPE
26290
26925
  exports.WEAVE_REGULAR_POLYGON_NODE_TYPE = WEAVE_REGULAR_POLYGON_NODE_TYPE
26291
26926
  exports.WEAVE_STAGE_DEFAULT_MODE = WEAVE_STAGE_DEFAULT_MODE
@@ -26324,8 +26959,9 @@ exports.WeaveLayerNode = WeaveLayerNode
26324
26959
  exports.WeaveLineNode = WeaveLineNode
26325
26960
  exports.WeaveMoveToolAction = WeaveMoveToolAction
26326
26961
  exports.WeaveNode = WeaveNode
26962
+ exports.WeaveNodesDistanceSnappingPlugin = WeaveNodesDistanceSnappingPlugin
26963
+ exports.WeaveNodesEdgeSnappingPlugin = WeaveNodesEdgeSnappingPlugin
26327
26964
  exports.WeaveNodesSelectionPlugin = WeaveNodesSelectionPlugin
26328
- exports.WeaveNodesSnappingPlugin = WeaveNodesSnappingPlugin
26329
26965
  exports.WeavePenToolAction = WeavePenToolAction
26330
26966
  exports.WeavePlugin = WeavePlugin
26331
26967
  exports.WeaveRectangleNode = WeaveRectangleNode
@@ -26355,7 +26991,10 @@ exports.containsNodeDeep = containsNodeDeep
26355
26991
  exports.getBoundingBox = getBoundingBox
26356
26992
  exports.getContrastTextColor = getContrastTextColor
26357
26993
  exports.getExportBoundingBox = getExportBoundingBox
26994
+ exports.getSelectedNodesMetadata = getSelectedNodesMetadata
26995
+ exports.getTargetAndSkipNodes = getTargetAndSkipNodes
26358
26996
  exports.getTargetedNode = getTargetedNode
26997
+ exports.getVisibleNodesInViewport = getVisibleNodesInViewport
26359
26998
  exports.hasFrames = hasFrames
26360
26999
  exports.hasImages = hasImages
26361
27000
  exports.intersectArrays = intersectArrays