@eventcatalog/visualiser 4.0.0-beta.0 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +230 -132
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +116 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
useNodesState as useNodesState2,
|
|
20
20
|
useEdgesState as useEdgesState2,
|
|
21
21
|
useReactFlow as useReactFlow5,
|
|
22
|
+
useStoreApi,
|
|
22
23
|
getNodesBounds,
|
|
23
|
-
getViewportForBounds,
|
|
24
24
|
MarkerType as MarkerType8
|
|
25
25
|
} from "@xyflow/react";
|
|
26
26
|
import {
|
|
@@ -9972,6 +9972,106 @@ var NodeContextMenu_default = memo39(function NodeContextMenu({
|
|
|
9972
9972
|
] });
|
|
9973
9973
|
});
|
|
9974
9974
|
|
|
9975
|
+
// src/utils/export-image.ts
|
|
9976
|
+
import { getViewportForBounds } from "@xyflow/react";
|
|
9977
|
+
var MIN_IMAGE_WIDTH = 1024;
|
|
9978
|
+
var MIN_IMAGE_HEIGHT = 768;
|
|
9979
|
+
var EXPORT_PADDING = 40;
|
|
9980
|
+
function getExportImageDimensions(nodesBounds) {
|
|
9981
|
+
const paddedBounds = {
|
|
9982
|
+
x: nodesBounds.x - EXPORT_PADDING,
|
|
9983
|
+
y: nodesBounds.y - EXPORT_PADDING,
|
|
9984
|
+
width: nodesBounds.width + EXPORT_PADDING * 2,
|
|
9985
|
+
height: nodesBounds.height + EXPORT_PADDING * 2
|
|
9986
|
+
};
|
|
9987
|
+
const width = Math.max(MIN_IMAGE_WIDTH, Math.ceil(paddedBounds.width));
|
|
9988
|
+
const height = Math.max(MIN_IMAGE_HEIGHT, Math.ceil(paddedBounds.height));
|
|
9989
|
+
const viewport = getViewportForBounds(paddedBounds, width, height, 0.5, 2, 0);
|
|
9990
|
+
return { width, height, viewport };
|
|
9991
|
+
}
|
|
9992
|
+
function extractEcVarNames(cssText) {
|
|
9993
|
+
return Array.from(new Set(cssText.match(/--ec-[a-z0-9-]+/g) ?? []));
|
|
9994
|
+
}
|
|
9995
|
+
function buildExportCss(themeVars) {
|
|
9996
|
+
const varDeclarations = Object.entries(themeVars).map(([name, value]) => `${name}: ${value};`).join(" ");
|
|
9997
|
+
return [
|
|
9998
|
+
// Applied to every element so the variables reach the cloned SVG subtree
|
|
9999
|
+
`* { ${varDeclarations} }`,
|
|
10000
|
+
// Mirrors .react-flow__edge-path in styles.css, which is lost in the clone
|
|
10001
|
+
`.react-flow__edge-path { stroke: var(--ec-edge-stroke, #6b7280); stroke-width: 1.5; fill: none; }`
|
|
10002
|
+
].join("\n");
|
|
10003
|
+
}
|
|
10004
|
+
function collectThemeCssVars(scope) {
|
|
10005
|
+
const names = /* @__PURE__ */ new Set();
|
|
10006
|
+
for (const sheet of Array.from(document.styleSheets)) {
|
|
10007
|
+
let rules;
|
|
10008
|
+
try {
|
|
10009
|
+
rules = sheet.cssRules;
|
|
10010
|
+
} catch {
|
|
10011
|
+
continue;
|
|
10012
|
+
}
|
|
10013
|
+
for (const rule of Array.from(rules)) {
|
|
10014
|
+
for (const name of extractEcVarNames(rule.cssText)) {
|
|
10015
|
+
names.add(name);
|
|
10016
|
+
}
|
|
10017
|
+
}
|
|
10018
|
+
}
|
|
10019
|
+
const computed = window.getComputedStyle(scope);
|
|
10020
|
+
const vars = {};
|
|
10021
|
+
for (const name of names) {
|
|
10022
|
+
const value = computed.getPropertyValue(name).trim();
|
|
10023
|
+
if (value) vars[name] = value;
|
|
10024
|
+
}
|
|
10025
|
+
return vars;
|
|
10026
|
+
}
|
|
10027
|
+
var SVG_EXPORT_STYLE_PROPERTIES = [
|
|
10028
|
+
"fill",
|
|
10029
|
+
"fill-opacity",
|
|
10030
|
+
"stroke",
|
|
10031
|
+
"stroke-width",
|
|
10032
|
+
"stroke-dasharray",
|
|
10033
|
+
"stroke-linecap",
|
|
10034
|
+
"stroke-linejoin",
|
|
10035
|
+
"opacity",
|
|
10036
|
+
"font-family",
|
|
10037
|
+
"font-size",
|
|
10038
|
+
"font-weight",
|
|
10039
|
+
"letter-spacing",
|
|
10040
|
+
"text-anchor",
|
|
10041
|
+
"dominant-baseline"
|
|
10042
|
+
];
|
|
10043
|
+
function inlineSvgComputedStyles(viewport) {
|
|
10044
|
+
const restores = [];
|
|
10045
|
+
const svgElements = viewport.querySelectorAll("svg, svg *");
|
|
10046
|
+
svgElements.forEach((element) => {
|
|
10047
|
+
if (!(element instanceof SVGElement)) return;
|
|
10048
|
+
const computed = window.getComputedStyle(element);
|
|
10049
|
+
const originalStyle = element.getAttribute("style");
|
|
10050
|
+
for (const property of SVG_EXPORT_STYLE_PROPERTIES) {
|
|
10051
|
+
const value = computed.getPropertyValue(property);
|
|
10052
|
+
if (value) element.style.setProperty(property, value);
|
|
10053
|
+
}
|
|
10054
|
+
restores.push(() => {
|
|
10055
|
+
if (originalStyle === null) {
|
|
10056
|
+
element.removeAttribute("style");
|
|
10057
|
+
} else {
|
|
10058
|
+
element.setAttribute("style", originalStyle);
|
|
10059
|
+
}
|
|
10060
|
+
});
|
|
10061
|
+
});
|
|
10062
|
+
return () => restores.forEach((restore) => restore());
|
|
10063
|
+
}
|
|
10064
|
+
function injectExportStyles(viewport) {
|
|
10065
|
+
const styleElement = document.createElement("style");
|
|
10066
|
+
styleElement.textContent = buildExportCss(collectThemeCssVars(viewport));
|
|
10067
|
+
viewport.appendChild(styleElement);
|
|
10068
|
+
const restoreSvgStyles = inlineSvgComputedStyles(viewport);
|
|
10069
|
+
return () => {
|
|
10070
|
+
restoreSvgStyles();
|
|
10071
|
+
styleElement.remove();
|
|
10072
|
+
};
|
|
10073
|
+
}
|
|
10074
|
+
|
|
9975
10075
|
// src/utils/layout.ts
|
|
9976
10076
|
import dagre2 from "dagre";
|
|
9977
10077
|
import { MarkerType as MarkerType7 } from "@xyflow/react";
|
|
@@ -11593,6 +11693,7 @@ var NodeGraphBuilder = ({
|
|
|
11593
11693
|
const [nodes, setNodes, onNodesChange] = useNodesState2(initialNodes);
|
|
11594
11694
|
const [edges, setEdges, onEdgesChange] = useEdgesState2(initialEdges);
|
|
11595
11695
|
const { fitView, getNodes, getIntersectingNodes, getZoom, setCenter } = useReactFlow5();
|
|
11696
|
+
const storeApi = useStoreApi();
|
|
11596
11697
|
useEffect9(() => {
|
|
11597
11698
|
setNodes(initialNodes);
|
|
11598
11699
|
setEdges(initialEdges);
|
|
@@ -12639,37 +12740,34 @@ var NodeGraphBuilder = ({
|
|
|
12639
12740
|
};
|
|
12640
12741
|
}, [fitView]);
|
|
12641
12742
|
const handleExportVisual = useCallback12(() => {
|
|
12642
|
-
const
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
const width
|
|
12646
|
-
const height = imageHeight > nodesBounds.height ? imageHeight : nodesBounds.height;
|
|
12647
|
-
const viewport = getViewportForBounds(
|
|
12648
|
-
nodesBounds,
|
|
12649
|
-
width,
|
|
12650
|
-
height,
|
|
12651
|
-
0.5,
|
|
12652
|
-
2,
|
|
12653
|
-
0
|
|
12654
|
-
);
|
|
12743
|
+
const nodesBounds = getNodesBounds(getNodes(), {
|
|
12744
|
+
nodeLookup: storeApi.getState().nodeLookup
|
|
12745
|
+
});
|
|
12746
|
+
const { width, height, viewport } = getExportImageDimensions(nodesBounds);
|
|
12655
12747
|
const controls = document.querySelector(
|
|
12656
12748
|
".react-flow__controls"
|
|
12657
12749
|
);
|
|
12658
12750
|
if (controls) controls.style.display = "none";
|
|
12659
|
-
|
|
12751
|
+
const viewportElement = document.querySelector(
|
|
12752
|
+
".react-flow__viewport"
|
|
12753
|
+
);
|
|
12754
|
+
const removeExportStyles = injectExportStyles(viewportElement);
|
|
12755
|
+
toPng(viewportElement, {
|
|
12660
12756
|
backgroundColor: "#f1f1f1",
|
|
12661
12757
|
width,
|
|
12662
12758
|
height,
|
|
12663
12759
|
style: {
|
|
12664
|
-
width: width
|
|
12665
|
-
height: height
|
|
12760
|
+
width: `${width}px`,
|
|
12761
|
+
height: `${height}px`,
|
|
12666
12762
|
transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom})`
|
|
12667
12763
|
}
|
|
12668
12764
|
}).then((dataUrl) => {
|
|
12669
12765
|
downloadImage(dataUrl, title);
|
|
12766
|
+
}).finally(() => {
|
|
12767
|
+
removeExportStyles();
|
|
12670
12768
|
if (controls) controls.style.display = "block";
|
|
12671
12769
|
});
|
|
12672
|
-
}, [getNodes, downloadImage, title]);
|
|
12770
|
+
}, [getNodes, storeApi, downloadImage, title]);
|
|
12673
12771
|
const handleLegendClick = useCallback12(
|
|
12674
12772
|
(collectionType, groupId) => {
|
|
12675
12773
|
const isLegendTarget = (node) => {
|