@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 +861 -222
- package/dist/sdk.d.cts +143 -31
- package/dist/sdk.d.cts.map +1 -1
- package/dist/sdk.d.ts +143 -31
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +861 -234
- package/dist/sdk.js.map +1 -1
- package/package.json +2 -2
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
|
|
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
|
|
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)
|
|
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(
|
|
16842
|
+
const contextMenuPlugin = this.instance.getPlugin(WEAVE_CONTEXT_MENU_PLUGIN_KEY);
|
|
16724
16843
|
return contextMenuPlugin;
|
|
16725
16844
|
}
|
|
16726
|
-
|
|
16727
|
-
const snappingPlugin = this.instance.getPlugin(
|
|
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
|
-
|
|
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
|
-
|
|
16919
|
+
const catcher = document.getElementById("paste-catcher");
|
|
16920
|
+
catcher?.focus();
|
|
16807
16921
|
if (!this.enabled) return;
|
|
16808
16922
|
try {
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
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
|
-
|
|
16818
|
-
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
|
|
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
|
-
|
|
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
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
|
|
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
|
|
17262
|
+
const nodesEdgeSnappingPlugin = this.getNodesEdgeSnappingPlugin();
|
|
17103
17263
|
if (nodesSelectionPlugin && this.isSelecting() && this.isNodeSelected(node$1)) nodesSelectionPlugin.getTransformer().forceUpdate();
|
|
17104
|
-
if (
|
|
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.
|
|
17113
|
-
if (nodesSnappingPlugin) nodesSnappingPlugin.
|
|
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
|
|
17172
|
-
|
|
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.
|
|
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
|
-
|
|
20557
|
-
|
|
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
|
-
|
|
20585
|
-
|
|
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/
|
|
25842
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
25936
|
-
if (
|
|
25937
|
-
|
|
25938
|
-
|
|
25939
|
-
|
|
25940
|
-
|
|
25941
|
-
|
|
25942
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26099
|
+
cleanupGuidelines() {
|
|
25992
26100
|
const utilityLayer = this.instance.getUtilityLayer();
|
|
25993
26101
|
if (!this.enabled) return;
|
|
25994
26102
|
if (!utilityLayer) return;
|
|
25995
|
-
|
|
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.
|
|
26113
|
+
this.cleanupGuidelines();
|
|
26006
26114
|
});
|
|
26007
26115
|
}
|
|
26008
26116
|
}
|
|
26009
|
-
|
|
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
|
|
26030
|
-
|
|
26031
|
-
|
|
26032
|
-
|
|
26033
|
-
|
|
26034
|
-
|
|
26035
|
-
|
|
26036
|
-
|
|
26037
|
-
|
|
26038
|
-
|
|
26039
|
-
|
|
26040
|
-
|
|
26041
|
-
|
|
26042
|
-
|
|
26043
|
-
|
|
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
|
|
26116
|
-
|
|
26117
|
-
|
|
26118
|
-
|
|
26119
|
-
|
|
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
|
|
26127
|
-
|
|
26128
|
-
|
|
26129
|
-
|
|
26130
|
-
|
|
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 =
|
|
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
|