@pixerate/editor-svelte 0.4.0 → 0.5.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/canvas/index.d.ts +227 -0
- package/dist/canvas/index.js +526 -1
- package/dist/canvas/index.js.map +1 -1
- package/package.json +1 -1
- package/src/canvas/__tests__/canvas-explosion.test.ts +249 -0
- package/src/canvas/createCanvasDisplacement.ts +226 -0
- package/src/canvas/createCanvasExplosion.svelte.ts +368 -0
- package/src/canvas/createCanvasTrajectory.ts +188 -0
- package/src/canvas/index.d.ts +227 -0
- package/src/canvas/index.ts +22 -0
- package/src/canvas/types.ts +116 -0
package/dist/canvas/index.js
CHANGED
|
@@ -651,22 +651,547 @@ function restorePanelPointerEvents(panelSelector = ".svelte-flow__panel") {
|
|
|
651
651
|
panel.style.pointerEvents = "auto";
|
|
652
652
|
});
|
|
653
653
|
}
|
|
654
|
+
|
|
655
|
+
// src/canvas/createCanvasTrajectory.ts
|
|
656
|
+
import { cubicOut as cubicOut2 } from "svelte/easing";
|
|
657
|
+
var linearTrajectory = (origin, target, progress) => {
|
|
658
|
+
return {
|
|
659
|
+
position: {
|
|
660
|
+
x: origin.x + (target.x - origin.x) * progress,
|
|
661
|
+
y: origin.y + (target.y - origin.y) * progress
|
|
662
|
+
},
|
|
663
|
+
scale: progress,
|
|
664
|
+
opacity: Math.min(1, progress * 1.5)
|
|
665
|
+
};
|
|
666
|
+
};
|
|
667
|
+
function createFanOutTrajectory(options = {}) {
|
|
668
|
+
const {
|
|
669
|
+
curvature = 0.4,
|
|
670
|
+
startScale = 0,
|
|
671
|
+
endScale = 1,
|
|
672
|
+
startOpacity = 0,
|
|
673
|
+
endOpacity = 1
|
|
674
|
+
} = options;
|
|
675
|
+
return (origin, target, progress, index, total) => {
|
|
676
|
+
const dx = target.x - origin.x;
|
|
677
|
+
const dy = target.y - origin.y;
|
|
678
|
+
const normIndex = total > 1 ? (index - (total - 1) / 2) / ((total - 1) / 2) : 0;
|
|
679
|
+
const midX = origin.x + dx * 0.4;
|
|
680
|
+
const midY = origin.y + dy * 0.1 - normIndex * Math.abs(dx) * 0.15 * curvature;
|
|
681
|
+
const t = progress;
|
|
682
|
+
const oneMinusT = 1 - t;
|
|
683
|
+
const x = oneMinusT * oneMinusT * origin.x + 2 * oneMinusT * t * midX + t * t * target.x;
|
|
684
|
+
const y = oneMinusT * oneMinusT * origin.y + 2 * oneMinusT * t * midY + t * t * target.y;
|
|
685
|
+
const scale = startScale + (endScale - startScale) * progress;
|
|
686
|
+
const opacity = startOpacity + (endOpacity - startOpacity) * progress;
|
|
687
|
+
return {
|
|
688
|
+
position: { x, y },
|
|
689
|
+
scale,
|
|
690
|
+
opacity
|
|
691
|
+
};
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
function createBezierTrajectory(getControlPoint) {
|
|
695
|
+
return (origin, target, progress) => {
|
|
696
|
+
const cp = getControlPoint(origin, target);
|
|
697
|
+
const t = progress;
|
|
698
|
+
const oneMinusT = 1 - t;
|
|
699
|
+
const x = oneMinusT * oneMinusT * origin.x + 2 * oneMinusT * t * cp.x + t * t * target.x;
|
|
700
|
+
const y = oneMinusT * oneMinusT * origin.y + 2 * oneMinusT * t * cp.y + t * t * target.y;
|
|
701
|
+
return {
|
|
702
|
+
position: { x, y },
|
|
703
|
+
scale: progress,
|
|
704
|
+
opacity: progress
|
|
705
|
+
};
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function runMultiNodeTransition(transitions, options = {}) {
|
|
709
|
+
if (transitions.length === 0) {
|
|
710
|
+
options.onComplete?.();
|
|
711
|
+
return () => {
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
const { defaultDuration = 400, defaultEasing = cubicOut2, onUpdate, onComplete } = options;
|
|
715
|
+
let isCancelled = false;
|
|
716
|
+
const startTime = Date.now();
|
|
717
|
+
const items = transitions.map((tr, i) => ({
|
|
718
|
+
...tr,
|
|
719
|
+
index: tr.index ?? i,
|
|
720
|
+
total: tr.total ?? transitions.length,
|
|
721
|
+
duration: tr.duration ?? defaultDuration,
|
|
722
|
+
easing: tr.easing ?? defaultEasing,
|
|
723
|
+
delay: tr.delay ?? 0,
|
|
724
|
+
trajectory: tr.trajectory ?? linearTrajectory
|
|
725
|
+
}));
|
|
726
|
+
function frame() {
|
|
727
|
+
if (isCancelled) return;
|
|
728
|
+
const now = Date.now();
|
|
729
|
+
let allCompleted = true;
|
|
730
|
+
for (let i = 0; i < items.length; i++) {
|
|
731
|
+
const item = items[i];
|
|
732
|
+
const elapsed = now - (startTime + item.delay);
|
|
733
|
+
if (elapsed < 0) {
|
|
734
|
+
allCompleted = false;
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
const rawProgress = item.duration <= 0 ? 1 : Math.min(elapsed / item.duration, 1);
|
|
738
|
+
const progress = item.duration <= 0 ? 1 : item.easing(rawProgress);
|
|
739
|
+
const point = item.trajectory(item.from, item.to, progress, item.index, item.total);
|
|
740
|
+
item.node.position = { ...point.position };
|
|
741
|
+
if (point.scale !== void 0 || point.opacity !== void 0) {
|
|
742
|
+
if (!item.node.data) {
|
|
743
|
+
item.node.data = {};
|
|
744
|
+
}
|
|
745
|
+
if (point.scale !== void 0) {
|
|
746
|
+
item.node.data.scale = point.scale;
|
|
747
|
+
}
|
|
748
|
+
if (point.opacity !== void 0) {
|
|
749
|
+
item.node.data.opacity = point.opacity;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (rawProgress < 1) {
|
|
753
|
+
allCompleted = false;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
onUpdate?.();
|
|
757
|
+
if (!allCompleted) {
|
|
758
|
+
if (typeof requestAnimationFrame !== "undefined") {
|
|
759
|
+
requestAnimationFrame(frame);
|
|
760
|
+
}
|
|
761
|
+
} else {
|
|
762
|
+
onComplete?.();
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
frame();
|
|
766
|
+
return () => {
|
|
767
|
+
isCancelled = true;
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// src/canvas/createCanvasDisplacement.ts
|
|
772
|
+
import dagre2 from "@dagrejs/dagre";
|
|
773
|
+
function computeNodesBoundingBox(nodes, defaultWidth = 200, defaultHeight = 60) {
|
|
774
|
+
if (nodes.length === 0) {
|
|
775
|
+
return { x: 0, y: 0, width: 0, height: 0 };
|
|
776
|
+
}
|
|
777
|
+
let minX = Infinity;
|
|
778
|
+
let minY = Infinity;
|
|
779
|
+
let maxX = -Infinity;
|
|
780
|
+
let maxY = -Infinity;
|
|
781
|
+
for (const node of nodes) {
|
|
782
|
+
const width = node.measured?.width ?? node.width ?? defaultWidth;
|
|
783
|
+
const height = node.measured?.height ?? node.height ?? defaultHeight;
|
|
784
|
+
minX = Math.min(minX, node.position.x);
|
|
785
|
+
minY = Math.min(minY, node.position.y);
|
|
786
|
+
maxX = Math.max(maxX, node.position.x + width);
|
|
787
|
+
maxY = Math.max(maxY, node.position.y + height);
|
|
788
|
+
}
|
|
789
|
+
return {
|
|
790
|
+
x: minX,
|
|
791
|
+
y: minY,
|
|
792
|
+
width: maxX - minX,
|
|
793
|
+
height: maxY - minY
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
function calculateDirectionalDisplacement(params) {
|
|
797
|
+
const {
|
|
798
|
+
existingNodes,
|
|
799
|
+
originNode,
|
|
800
|
+
childNodes,
|
|
801
|
+
getNodesBounds,
|
|
802
|
+
options = {}
|
|
803
|
+
} = params;
|
|
804
|
+
const {
|
|
805
|
+
direction = "right",
|
|
806
|
+
gap = 40,
|
|
807
|
+
spreadSiblingLanes = false,
|
|
808
|
+
siblingTolerance = 50
|
|
809
|
+
} = options;
|
|
810
|
+
const displacedMap = /* @__PURE__ */ new Map();
|
|
811
|
+
if (childNodes.length === 0 || existingNodes.length === 0) {
|
|
812
|
+
return displacedMap;
|
|
813
|
+
}
|
|
814
|
+
const childBounds = getNodesBounds ? getNodesBounds(childNodes) : computeNodesBoundingBox(childNodes);
|
|
815
|
+
const originWidth = originNode.measured?.width ?? originNode.width ?? 200;
|
|
816
|
+
const originHeight = originNode.measured?.height ?? originNode.height ?? 60;
|
|
817
|
+
const deltaPrimary = direction === "right" || direction === "left" ? childBounds.width + gap : childBounds.height + gap;
|
|
818
|
+
for (const node of existingNodes) {
|
|
819
|
+
if (node.id === originNode.id) continue;
|
|
820
|
+
let newX = node.position.x;
|
|
821
|
+
let newY = node.position.y;
|
|
822
|
+
let moved = false;
|
|
823
|
+
if (direction === "right") {
|
|
824
|
+
if (node.position.x >= originNode.position.x + originWidth * 0.5) {
|
|
825
|
+
newX += deltaPrimary;
|
|
826
|
+
moved = true;
|
|
827
|
+
} else if (spreadSiblingLanes) {
|
|
828
|
+
const isVerticallyOverlapping = node.position.y + (node.height ?? 60) >= childBounds.y - gap && node.position.y <= childBounds.y + childBounds.height + gap;
|
|
829
|
+
if (isVerticallyOverlapping && Math.abs(node.position.x - originNode.position.x) <= siblingTolerance) {
|
|
830
|
+
const pushDirection = node.position.y >= originNode.position.y ? 1 : -1;
|
|
831
|
+
newY += pushDirection * (childBounds.height * 0.5 + gap);
|
|
832
|
+
moved = true;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
} else if (direction === "left") {
|
|
836
|
+
if (node.position.x <= originNode.position.x) {
|
|
837
|
+
newX -= deltaPrimary;
|
|
838
|
+
moved = true;
|
|
839
|
+
}
|
|
840
|
+
} else if (direction === "down") {
|
|
841
|
+
if (node.position.y >= originNode.position.y + originHeight * 0.5) {
|
|
842
|
+
newY += deltaPrimary;
|
|
843
|
+
moved = true;
|
|
844
|
+
}
|
|
845
|
+
} else if (direction === "up") {
|
|
846
|
+
if (node.position.y <= originNode.position.y) {
|
|
847
|
+
newY -= deltaPrimary;
|
|
848
|
+
moved = true;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
if (moved) {
|
|
852
|
+
displacedMap.set(node.id, { x: newX, y: newY });
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return displacedMap;
|
|
856
|
+
}
|
|
857
|
+
function calculateReflowDisplacement(params) {
|
|
858
|
+
const {
|
|
859
|
+
existingNodes,
|
|
860
|
+
existingEdges,
|
|
861
|
+
originNode,
|
|
862
|
+
childNodes,
|
|
863
|
+
childEdges = [],
|
|
864
|
+
options = {}
|
|
865
|
+
} = params;
|
|
866
|
+
const {
|
|
867
|
+
direction = "LR",
|
|
868
|
+
ranksep = 80,
|
|
869
|
+
nodesep = 30,
|
|
870
|
+
defaultNodeWidth = 200,
|
|
871
|
+
defaultNodeHeight = 60
|
|
872
|
+
} = options;
|
|
873
|
+
const displacedMap = /* @__PURE__ */ new Map();
|
|
874
|
+
if (existingNodes.length === 0) return displacedMap;
|
|
875
|
+
const allNodes = [...existingNodes, ...childNodes];
|
|
876
|
+
const allEdges = [...existingEdges, ...childEdges];
|
|
877
|
+
const dagreGraph = new dagre2.graphlib.Graph();
|
|
878
|
+
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
|
879
|
+
dagreGraph.setGraph({ rankdir: direction, ranksep, nodesep });
|
|
880
|
+
const allNodeIds = new Set(allNodes.map((n) => n.id));
|
|
881
|
+
allNodes.forEach((node) => {
|
|
882
|
+
const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
|
|
883
|
+
const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
|
|
884
|
+
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
|
885
|
+
});
|
|
886
|
+
allEdges.forEach((edge) => {
|
|
887
|
+
if (allNodeIds.has(edge.source) && allNodeIds.has(edge.target)) {
|
|
888
|
+
dagreGraph.setEdge(edge.source, edge.target);
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
dagre2.layout(dagreGraph);
|
|
892
|
+
const dagreOrigin = dagreGraph.node(originNode.id);
|
|
893
|
+
if (!dagreOrigin) return displacedMap;
|
|
894
|
+
const originWidth = originNode.measured?.width ?? originNode.width ?? defaultNodeWidth;
|
|
895
|
+
const originHeight = originNode.measured?.height ?? originNode.height ?? defaultNodeHeight;
|
|
896
|
+
const anchorOffsetX = originNode.position.x - (dagreOrigin.x - originWidth / 2);
|
|
897
|
+
const anchorOffsetY = originNode.position.y - (dagreOrigin.y - originHeight / 2);
|
|
898
|
+
existingNodes.forEach((node) => {
|
|
899
|
+
if (node.id === originNode.id) return;
|
|
900
|
+
const dagreNode = dagreGraph.node(node.id);
|
|
901
|
+
if (!dagreNode) return;
|
|
902
|
+
const nodeWidth = node.measured?.width ?? node.width ?? defaultNodeWidth;
|
|
903
|
+
const nodeHeight = node.measured?.height ?? node.height ?? defaultNodeHeight;
|
|
904
|
+
const targetX = dagreNode.x - nodeWidth / 2 + anchorOffsetX;
|
|
905
|
+
const targetY = dagreNode.y - nodeHeight / 2 + anchorOffsetY;
|
|
906
|
+
if (Math.abs(targetX - node.position.x) > 0.5 || Math.abs(targetY - node.position.y) > 0.5) {
|
|
907
|
+
displacedMap.set(node.id, { x: targetX, y: targetY });
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
return displacedMap;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// src/canvas/createCanvasExplosion.svelte.ts
|
|
914
|
+
import * as $5 from "svelte/internal/client";
|
|
915
|
+
import { cubicOut as cubicOut3 } from "svelte/easing";
|
|
916
|
+
function createCanvasExplosion(graph, options = {}) {
|
|
917
|
+
let explodedNodeIds = $5.state($5.proxy([]));
|
|
918
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
919
|
+
let activeAnimationCancel = null;
|
|
920
|
+
function isExploded(nodeId) {
|
|
921
|
+
return $5.get(explodedNodeIds).includes(nodeId);
|
|
922
|
+
}
|
|
923
|
+
function explodeNode(parentId, explodeOptions) {
|
|
924
|
+
if (isExploded(parentId)) {
|
|
925
|
+
return false;
|
|
926
|
+
}
|
|
927
|
+
const parentNode = graph.nodes.find((n) => n.id === parentId);
|
|
928
|
+
if (!parentNode) {
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
const {
|
|
932
|
+
childNodes,
|
|
933
|
+
childEdges = [],
|
|
934
|
+
connectParentToChildren = "all",
|
|
935
|
+
displacementStrategy = "directional",
|
|
936
|
+
directionalOptions = {},
|
|
937
|
+
reflowOptions = {},
|
|
938
|
+
trajectory,
|
|
939
|
+
duration = 500,
|
|
940
|
+
staggerDelay = 20,
|
|
941
|
+
easing = cubicOut3,
|
|
942
|
+
onComplete
|
|
943
|
+
} = explodeOptions;
|
|
944
|
+
if (childNodes.length === 0) {
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
let displacementMap;
|
|
948
|
+
if (displacementStrategy === "dagre") {
|
|
949
|
+
displacementMap = calculateReflowDisplacement({
|
|
950
|
+
existingNodes: graph.nodes,
|
|
951
|
+
existingEdges: graph.edges,
|
|
952
|
+
originNode: parentNode,
|
|
953
|
+
childNodes,
|
|
954
|
+
childEdges,
|
|
955
|
+
getNodesBounds: options.getNodesBounds,
|
|
956
|
+
options: { ...reflowOptions, direction: reflowOptions.direction ?? "LR" }
|
|
957
|
+
});
|
|
958
|
+
} else if (displacementStrategy === "none") {
|
|
959
|
+
displacementMap = /* @__PURE__ */ new Map();
|
|
960
|
+
} else {
|
|
961
|
+
displacementMap = calculateDirectionalDisplacement({
|
|
962
|
+
existingNodes: graph.nodes,
|
|
963
|
+
originNode: parentNode,
|
|
964
|
+
childNodes,
|
|
965
|
+
getNodesBounds: options.getNodesBounds,
|
|
966
|
+
options: directionalOptions
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
const displacedNodesSnapshot = Array.from(displacementMap.entries()).map(([id]) => {
|
|
970
|
+
const node = graph.nodes.find((n) => n.id === id);
|
|
971
|
+
return {
|
|
972
|
+
id,
|
|
973
|
+
originalPosition: { ...node?.position ?? { x: 0, y: 0 } }
|
|
974
|
+
};
|
|
975
|
+
});
|
|
976
|
+
const edgesToAdd = [...childEdges];
|
|
977
|
+
const defaultCreateEdge = (sourceId, targetId) => {
|
|
978
|
+
if (graph.createEdge) {
|
|
979
|
+
return graph.createEdge(sourceId, targetId);
|
|
980
|
+
}
|
|
981
|
+
return {
|
|
982
|
+
id: crypto.randomUUID(),
|
|
983
|
+
type: "default",
|
|
984
|
+
source: sourceId,
|
|
985
|
+
target: targetId
|
|
986
|
+
};
|
|
987
|
+
};
|
|
988
|
+
if (connectParentToChildren === "all" || connectParentToChildren === true) {
|
|
989
|
+
childNodes.forEach((child) => {
|
|
990
|
+
const exists = edgesToAdd.some((e) => e.source === parentId && e.target === child.id);
|
|
991
|
+
if (!exists) {
|
|
992
|
+
edgesToAdd.push(defaultCreateEdge(parentId, child.id));
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
} else if (connectParentToChildren === "first" && childNodes.length > 0) {
|
|
996
|
+
const firstChild = childNodes[0];
|
|
997
|
+
const exists = edgesToAdd.some((e) => e.source === parentId && e.target === firstChild.id);
|
|
998
|
+
if (!exists) {
|
|
999
|
+
edgesToAdd.push(defaultCreateEdge(parentId, firstChild.id));
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
const snapshot = {
|
|
1003
|
+
parentId,
|
|
1004
|
+
childNodeIds: childNodes.map((n) => n.id),
|
|
1005
|
+
childEdgeIds: edgesToAdd.map((e) => e.id),
|
|
1006
|
+
displacedNodes: displacedNodesSnapshot,
|
|
1007
|
+
timestamp: Date.now()
|
|
1008
|
+
};
|
|
1009
|
+
snapshots.set(parentId, snapshot);
|
|
1010
|
+
const originPos = { ...parentNode.position };
|
|
1011
|
+
const targetPositions = childNodes.map((child) => ({ ...child.position }));
|
|
1012
|
+
childNodes.forEach((child) => {
|
|
1013
|
+
child.position = { ...originPos };
|
|
1014
|
+
if (!child.data) child.data = {};
|
|
1015
|
+
child.data.scale = 0;
|
|
1016
|
+
child.data.opacity = 0;
|
|
1017
|
+
});
|
|
1018
|
+
graph.addNodeOrNodes(childNodes, void 0, false);
|
|
1019
|
+
if (edgesToAdd.length > 0) {
|
|
1020
|
+
graph.addEdges(edgesToAdd, false);
|
|
1021
|
+
}
|
|
1022
|
+
const chosenTrajectory = trajectory ?? createFanOutTrajectory({ curvature: 0.35 });
|
|
1023
|
+
const transitions = [];
|
|
1024
|
+
const effectiveStagger = duration === 0 ? 0 : staggerDelay;
|
|
1025
|
+
childNodes.forEach((child, i) => {
|
|
1026
|
+
transitions.push({
|
|
1027
|
+
node: child,
|
|
1028
|
+
from: originPos,
|
|
1029
|
+
to: targetPositions[i],
|
|
1030
|
+
trajectory: chosenTrajectory,
|
|
1031
|
+
delay: i * effectiveStagger,
|
|
1032
|
+
duration,
|
|
1033
|
+
easing,
|
|
1034
|
+
index: i,
|
|
1035
|
+
total: childNodes.length
|
|
1036
|
+
});
|
|
1037
|
+
});
|
|
1038
|
+
displacementMap.forEach((targetPos, nodeId) => {
|
|
1039
|
+
const node = graph.nodes.find((n) => n.id === nodeId);
|
|
1040
|
+
if (node) {
|
|
1041
|
+
transitions.push({
|
|
1042
|
+
node,
|
|
1043
|
+
from: { ...node.position },
|
|
1044
|
+
to: targetPos,
|
|
1045
|
+
trajectory: linearTrajectory,
|
|
1046
|
+
duration,
|
|
1047
|
+
easing
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
});
|
|
1051
|
+
if (activeAnimationCancel) {
|
|
1052
|
+
activeAnimationCancel();
|
|
1053
|
+
}
|
|
1054
|
+
activeAnimationCancel = runMultiNodeTransition(transitions, {
|
|
1055
|
+
defaultDuration: duration,
|
|
1056
|
+
defaultEasing: easing,
|
|
1057
|
+
onUpdate: () => {
|
|
1058
|
+
graph.setNodes([...graph.nodes]);
|
|
1059
|
+
},
|
|
1060
|
+
onComplete: () => {
|
|
1061
|
+
graph.setNodes([...graph.nodes]);
|
|
1062
|
+
$5.set(explodedNodeIds, [...$5.get(explodedNodeIds), parentId], true);
|
|
1063
|
+
activeAnimationCancel = null;
|
|
1064
|
+
options.onSave?.();
|
|
1065
|
+
graph.onSave?.();
|
|
1066
|
+
onComplete?.();
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
return true;
|
|
1070
|
+
}
|
|
1071
|
+
function collapseNode(parentId, collapseOptions = {}) {
|
|
1072
|
+
const snapshot = snapshots.get(parentId);
|
|
1073
|
+
if (!snapshot) {
|
|
1074
|
+
return false;
|
|
1075
|
+
}
|
|
1076
|
+
const parentNode = graph.nodes.find((n) => n.id === parentId);
|
|
1077
|
+
if (!parentNode) {
|
|
1078
|
+
return false;
|
|
1079
|
+
}
|
|
1080
|
+
const {
|
|
1081
|
+
duration = 400,
|
|
1082
|
+
staggerDelay = 15,
|
|
1083
|
+
easing = cubicOut3,
|
|
1084
|
+
trajectory,
|
|
1085
|
+
onComplete
|
|
1086
|
+
} = collapseOptions;
|
|
1087
|
+
const childIdSet = new Set(snapshot.childNodeIds);
|
|
1088
|
+
const activeChildNodes = graph.nodes.filter((n) => childIdSet.has(n.id));
|
|
1089
|
+
const originPos = { ...parentNode.position };
|
|
1090
|
+
const reverseTrajectory = trajectory ?? createFanOutTrajectory({
|
|
1091
|
+
curvature: 0.2,
|
|
1092
|
+
startScale: 1,
|
|
1093
|
+
endScale: 0,
|
|
1094
|
+
startOpacity: 1,
|
|
1095
|
+
endOpacity: 0
|
|
1096
|
+
});
|
|
1097
|
+
const transitions = [];
|
|
1098
|
+
const effectiveStagger = duration === 0 ? 0 : staggerDelay;
|
|
1099
|
+
activeChildNodes.forEach((child, i) => {
|
|
1100
|
+
transitions.push({
|
|
1101
|
+
node: child,
|
|
1102
|
+
from: { ...child.position },
|
|
1103
|
+
to: originPos,
|
|
1104
|
+
trajectory: reverseTrajectory,
|
|
1105
|
+
delay: (activeChildNodes.length - 1 - i) * effectiveStagger,
|
|
1106
|
+
duration,
|
|
1107
|
+
easing,
|
|
1108
|
+
index: i,
|
|
1109
|
+
total: activeChildNodes.length
|
|
1110
|
+
});
|
|
1111
|
+
});
|
|
1112
|
+
snapshot.displacedNodes.forEach(({ id, originalPosition }) => {
|
|
1113
|
+
const node = graph.nodes.find((n) => n.id === id);
|
|
1114
|
+
if (node) {
|
|
1115
|
+
transitions.push({
|
|
1116
|
+
node,
|
|
1117
|
+
from: { ...node.position },
|
|
1118
|
+
to: originalPosition,
|
|
1119
|
+
trajectory: linearTrajectory,
|
|
1120
|
+
duration,
|
|
1121
|
+
easing
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
if (activeAnimationCancel) {
|
|
1126
|
+
activeAnimationCancel();
|
|
1127
|
+
}
|
|
1128
|
+
activeAnimationCancel = runMultiNodeTransition(transitions, {
|
|
1129
|
+
defaultDuration: duration,
|
|
1130
|
+
defaultEasing: easing,
|
|
1131
|
+
onUpdate: () => {
|
|
1132
|
+
graph.setNodes([...graph.nodes]);
|
|
1133
|
+
},
|
|
1134
|
+
onComplete: () => {
|
|
1135
|
+
graph.removeNodes(activeChildNodes, false);
|
|
1136
|
+
const edgeIdSet = new Set(snapshot.childEdgeIds);
|
|
1137
|
+
const edgesToRemove = graph.edges.filter((e) => edgeIdSet.has(e.id));
|
|
1138
|
+
if (edgesToRemove.length > 0) {
|
|
1139
|
+
graph.removeEdges(edgesToRemove, false);
|
|
1140
|
+
}
|
|
1141
|
+
snapshots.delete(parentId);
|
|
1142
|
+
$5.set(explodedNodeIds, $5.get(explodedNodeIds).filter((id) => id !== parentId), true);
|
|
1143
|
+
activeAnimationCancel = null;
|
|
1144
|
+
options.onSave?.();
|
|
1145
|
+
graph.onSave?.();
|
|
1146
|
+
onComplete?.();
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
return true;
|
|
1150
|
+
}
|
|
1151
|
+
function toggleExplode(parentId, explodeOptions, collapseOptions) {
|
|
1152
|
+
if (isExploded(parentId)) {
|
|
1153
|
+
return collapseNode(parentId, collapseOptions);
|
|
1154
|
+
}
|
|
1155
|
+
return explodeNode(parentId, explodeOptions);
|
|
1156
|
+
}
|
|
1157
|
+
function getSnapshot(parentId) {
|
|
1158
|
+
return snapshots.get(parentId);
|
|
1159
|
+
}
|
|
1160
|
+
return {
|
|
1161
|
+
get explodedNodeIds() {
|
|
1162
|
+
return $5.get(explodedNodeIds);
|
|
1163
|
+
},
|
|
1164
|
+
isExploded,
|
|
1165
|
+
explodeNode,
|
|
1166
|
+
collapseNode,
|
|
1167
|
+
toggleExplode,
|
|
1168
|
+
getSnapshot
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
654
1171
|
export {
|
|
1172
|
+
calculateDirectionalDisplacement,
|
|
655
1173
|
calculateGraphDifferences,
|
|
1174
|
+
calculateReflowDisplacement,
|
|
656
1175
|
centerNodes,
|
|
1176
|
+
computeNodesBoundingBox,
|
|
1177
|
+
createBezierTrajectory,
|
|
657
1178
|
createCanvasClipboard,
|
|
658
1179
|
createCanvasDocking,
|
|
1180
|
+
createCanvasExplosion,
|
|
659
1181
|
createCanvasGraph,
|
|
660
1182
|
createCanvasInteractions,
|
|
661
1183
|
createCanvasShortcuts,
|
|
1184
|
+
createFanOutTrajectory,
|
|
662
1185
|
defaultSvelteFlowPreset,
|
|
663
1186
|
getCenteredNodePosition,
|
|
664
1187
|
getLayoutedNodes,
|
|
665
1188
|
isEventFromTextInput,
|
|
666
1189
|
isValidCanvasNode,
|
|
667
1190
|
isValidUrl,
|
|
1191
|
+
linearTrajectory,
|
|
668
1192
|
miroCompatiblePreset,
|
|
669
1193
|
replaceNodeInGraph,
|
|
670
|
-
restorePanelPointerEvents
|
|
1194
|
+
restorePanelPointerEvents,
|
|
1195
|
+
runMultiNodeTransition
|
|
671
1196
|
};
|
|
672
1197
|
//# sourceMappingURL=index.js.map
|