package.dist.chunks.mermaid.core.chunk-HKLBG3BQ.mjs Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mermaid Show documentation
Show all versions of mermaid Show documentation
Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.
The newest version!
import {
getIconSVG
} from "./chunk-32DZJKXY.mjs";
import {
getSubGraphTitleMargins
} from "./chunk-V2CZVG6A.mjs";
import {
createText
} from "./chunk-U6O4IJP6.mjs";
import {
calculateTextWidth,
decodeEntities,
handleUndefinedAttr,
parseFontSize
} from "./chunk-MCANT3UC.mjs";
import {
__name,
common_default,
defaultConfig_default,
evaluate,
getConfig,
getConfig2,
hasKatex,
log,
renderKatex,
sanitizeText,
sanitizeText2
} from "./chunk-P27NXTFD.mjs";
// src/rendering-util/rendering-elements/shapes/util.ts
import { select } from "d3";
var labelHelper = /* @__PURE__ */ __name(async (parent, node, _classes) => {
let cssClasses;
const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig2()?.htmlLabels);
if (!_classes) {
cssClasses = "node default";
} else {
cssClasses = _classes;
}
const shapeSvg = parent.insert("g").attr("class", cssClasses).attr("id", node.domId || node.id);
const labelEl = shapeSvg.insert("g").attr("class", "label").attr("style", handleUndefinedAttr(node.labelStyle));
let label;
if (node.label === void 0) {
label = "";
} else {
label = typeof node.label === "string" ? node.label : node.label[0];
}
const text2 = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig2()), {
useHtmlLabels,
width: node.width || getConfig2().flowchart?.wrappingWidth,
// @ts-expect-error -- This is currently not used. Should this be `classes` instead?
cssClasses: "markdown-node-label",
style: node.labelStyle,
addSvgBackground: !!node.icon || !!node.img
});
let bbox = text2.getBBox();
const halfPadding = (node?.padding ?? 0) / 2;
if (useHtmlLabels) {
const div = text2.children[0];
const dv = select(text2);
const images = div.getElementsByTagName("img");
if (images) {
const noImgText = label.replace(/]*>/g, "").trim() === "";
await Promise.all(
[...images].map(
(img) => new Promise((res) => {
function setupImage() {
img.style.display = "flex";
img.style.flexDirection = "column";
if (noImgText) {
const bodyFontSize = getConfig2().fontSize ? getConfig2().fontSize : window.getComputedStyle(document.body).fontSize;
const enlargingFactor = 5;
const [parsedBodyFontSize = defaultConfig_default.fontSize] = parseFontSize(bodyFontSize);
const width = parsedBodyFontSize * enlargingFactor + "px";
img.style.minWidth = width;
img.style.maxWidth = width;
} else {
img.style.width = "100%";
}
res(img);
}
__name(setupImage, "setupImage");
setTimeout(() => {
if (img.complete) {
setupImage();
}
});
img.addEventListener("error", setupImage);
img.addEventListener("load", setupImage);
})
)
);
}
bbox = div.getBoundingClientRect();
dv.attr("width", bbox.width);
dv.attr("height", bbox.height);
}
if (useHtmlLabels) {
labelEl.attr("transform", "translate(" + -bbox.width / 2 + ", " + -bbox.height / 2 + ")");
} else {
labelEl.attr("transform", "translate(0, " + -bbox.height / 2 + ")");
}
if (node.centerLabel) {
labelEl.attr("transform", "translate(" + -bbox.width / 2 + ", " + -bbox.height / 2 + ")");
}
labelEl.insert("rect", ":first-child");
return { shapeSvg, bbox, halfPadding, label: labelEl };
}, "labelHelper");
var insertLabel = /* @__PURE__ */ __name(async (parent, label, options) => {
const useHtmlLabels = options.useHtmlLabels || evaluate(getConfig2()?.flowchart?.htmlLabels);
const labelEl = parent.insert("g").attr("class", "label").attr("style", options.labelStyle || "");
const text2 = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig2()), {
useHtmlLabels,
width: options.width || getConfig2()?.flowchart?.wrappingWidth,
style: options.labelStyle,
addSvgBackground: !!options.icon || !!options.img
});
let bbox = text2.getBBox();
const halfPadding = options.padding / 2;
if (evaluate(getConfig2()?.flowchart?.htmlLabels)) {
const div = text2.children[0];
const dv = select(text2);
bbox = div.getBoundingClientRect();
dv.attr("width", bbox.width);
dv.attr("height", bbox.height);
}
if (useHtmlLabels) {
labelEl.attr("transform", "translate(" + -bbox.width / 2 + ", " + -bbox.height / 2 + ")");
} else {
labelEl.attr("transform", "translate(0, " + -bbox.height / 2 + ")");
}
if (options.centerLabel) {
labelEl.attr("transform", "translate(" + -bbox.width / 2 + ", " + -bbox.height / 2 + ")");
}
labelEl.insert("rect", ":first-child");
return { shapeSvg: parent, bbox, halfPadding, label: labelEl };
}, "insertLabel");
var updateNodeBounds = /* @__PURE__ */ __name((node, element) => {
const bbox = element.node().getBBox();
node.width = bbox.width;
node.height = bbox.height;
}, "updateNodeBounds");
var getNodeClasses = /* @__PURE__ */ __name((node, extra) => (node.look === "handDrawn" ? "rough-node" : "node") + " " + node.cssClasses + " " + (extra || ""), "getNodeClasses");
function createPathFromPoints(points) {
const pointStrings = points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x},${p.y}`);
pointStrings.push("Z");
return pointStrings.join(" ");
}
__name(createPathFromPoints, "createPathFromPoints");
function generateFullSineWavePoints(x1, y1, x2, y2, amplitude, numCycles) {
const points = [];
const steps = 50;
const deltaX = x2 - x1;
const deltaY = y2 - y1;
const cycleLength = deltaX / numCycles;
const frequency = 2 * Math.PI / cycleLength;
const midY = y1 + deltaY / 2;
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const x = x1 + t * deltaX;
const y = midY + amplitude * Math.sin(frequency * (x - x1));
points.push({ x, y });
}
return points;
}
__name(generateFullSineWavePoints, "generateFullSineWavePoints");
function generateCirclePoints(centerX, centerY, radius, numPoints, startAngle, endAngle) {
const points = [];
const startAngleRad = startAngle * Math.PI / 180;
const endAngleRad = endAngle * Math.PI / 180;
const angleRange = endAngleRad - startAngleRad;
const angleStep = angleRange / (numPoints - 1);
for (let i = 0; i < numPoints; i++) {
const angle = startAngleRad + i * angleStep;
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
points.push({ x: -x, y: -y });
}
return points;
}
__name(generateCirclePoints, "generateCirclePoints");
// src/rendering-util/rendering-elements/clusters.js
import { select as select3 } from "d3";
import rough from "roughjs";
// src/rendering-util/rendering-elements/intersect/intersect-rect.js
var intersectRect = /* @__PURE__ */ __name((node, point) => {
var x = node.x;
var y = node.y;
var dx = point.x - x;
var dy = point.y - y;
var w = node.width / 2;
var h = node.height / 2;
var sx, sy;
if (Math.abs(dy) * w > Math.abs(dx) * h) {
if (dy < 0) {
h = -h;
}
sx = dy === 0 ? 0 : h * dx / dy;
sy = h;
} else {
if (dx < 0) {
w = -w;
}
sx = w;
sy = dx === 0 ? 0 : w * dy / dx;
}
return { x: x + sx, y: y + sy };
}, "intersectRect");
var intersect_rect_default = intersectRect;
// src/rendering-util/rendering-elements/createLabel.js
import { select as select2 } from "d3";
function applyStyle(dom, styleFn) {
if (styleFn) {
dom.attr("style", styleFn);
}
}
__name(applyStyle, "applyStyle");
async function addHtmlLabel(node) {
const fo = select2(document.createElementNS("http://www.w3.org/2000/svg", "foreignObject"));
const div = fo.append("xhtml:div");
let label = node.label;
if (node.label && hasKatex(node.label)) {
label = await renderKatex(node.label.replace(common_default.lineBreakRegex, "\n"), getConfig2());
}
const labelClass = node.isNode ? "nodeLabel" : "edgeLabel";
div.html(
'" + label + ""
);
applyStyle(div, node.labelStyle);
div.style("display", "inline-block");
div.style("padding-right", "1px");
div.style("white-space", "nowrap");
div.attr("xmlns", "http://www.w3.org/1999/xhtml");
return fo.node();
}
__name(addHtmlLabel, "addHtmlLabel");
var createLabel = /* @__PURE__ */ __name(async (_vertexText, style, isTitle, isNode) => {
let vertexText = _vertexText || "";
if (typeof vertexText === "object") {
vertexText = vertexText[0];
}
if (evaluate(getConfig2().flowchart.htmlLabels)) {
vertexText = vertexText.replace(/\\n|\n/g, "
");
log.info("vertexText" + vertexText);
const node = {
isNode,
label: decodeEntities(vertexText).replace(
/fa[blrs]?:fa-[\w-]+/g,
(s) => ``
),
labelStyle: style ? style.replace("fill:", "color:") : style
};
let vertexNode = await addHtmlLabel(node);
return vertexNode;
} else {
const svgLabel = document.createElementNS("http://www.w3.org/2000/svg", "text");
svgLabel.setAttribute("style", style.replace("color:", "fill:"));
let rows = [];
if (typeof vertexText === "string") {
rows = vertexText.split(/\\n|\n|
/gi);
} else if (Array.isArray(vertexText)) {
rows = vertexText;
} else {
rows = [];
}
for (const row of rows) {
const tspan = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
tspan.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space", "preserve");
tspan.setAttribute("dy", "1em");
tspan.setAttribute("x", "0");
if (isTitle) {
tspan.setAttribute("class", "title-row");
} else {
tspan.setAttribute("class", "row");
}
tspan.textContent = row.trim();
svgLabel.appendChild(tspan);
}
return svgLabel;
}
}, "createLabel");
var createLabel_default = createLabel;
// src/rendering-util/rendering-elements/shapes/roundedRectPath.ts
var createRoundedRectPathD = /* @__PURE__ */ __name((x, y, totalWidth, totalHeight, radius) => [
"M",
x + radius,
y,
// Move to the first point
"H",
x + totalWidth - radius,
// Draw horizontal line to the beginning of the right corner
"A",
radius,
radius,
0,
0,
1,
x + totalWidth,
y + radius,
// Draw arc to the right top corner
"V",
y + totalHeight - radius,
// Draw vertical line down to the beginning of the right bottom corner
"A",
radius,
radius,
0,
0,
1,
x + totalWidth - radius,
y + totalHeight,
// Draw arc to the right bottom corner
"H",
x + radius,
// Draw horizontal line to the beginning of the left bottom corner
"A",
radius,
radius,
0,
0,
1,
x,
y + totalHeight - radius,
// Draw arc to the left bottom corner
"V",
y + radius,
// Draw vertical line up to the beginning of the left top corner
"A",
radius,
radius,
0,
0,
1,
x + radius,
y,
// Draw arc to the left top corner
"Z"
// Close the path
].join(" "), "createRoundedRectPathD");
// src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts
var solidStateFill = /* @__PURE__ */ __name((color) => {
const { handDrawnSeed } = getConfig2();
return {
fill: color,
hachureAngle: 120,
// angle of hachure,
hachureGap: 4,
fillWeight: 2,
roughness: 0.7,
stroke: color,
seed: handDrawnSeed
};
}, "solidStateFill");
var compileStyles = /* @__PURE__ */ __name((node) => {
const stylesMap = styles2Map([...node.cssCompiledStyles || [], ...node.cssStyles || []]);
return { stylesMap, stylesArray: [...stylesMap] };
}, "compileStyles");
var styles2Map = /* @__PURE__ */ __name((styles) => {
const styleMap = /* @__PURE__ */ new Map();
styles.forEach((style) => {
const [key, value] = style.split(":");
styleMap.set(key.trim(), value?.trim());
});
return styleMap;
}, "styles2Map");
var styles2String = /* @__PURE__ */ __name((node) => {
const { stylesArray } = compileStyles(node);
const labelStyles = [];
const nodeStyles = [];
const borderStyles = [];
const backgroundStyles = [];
stylesArray.forEach((style) => {
const key = style[0];
if (key === "color" || key === "font-size" || key === "font-family" || key === "font-weight" || key === "font-style" || key === "text-decoration" || key === "text-align" || key === "text-transform" || key === "line-height" || key === "letter-spacing" || key === "word-spacing" || key === "text-shadow" || key === "text-overflow" || key === "white-space" || key === "word-wrap" || key === "word-break" || key === "overflow-wrap" || key === "hyphens") {
labelStyles.push(style.join(":") + " !important");
} else {
nodeStyles.push(style.join(":") + " !important");
if (key.includes("stroke")) {
borderStyles.push(style.join(":") + " !important");
}
if (key === "fill") {
backgroundStyles.push(style.join(":") + " !important");
}
}
});
return {
labelStyles: labelStyles.join(";"),
nodeStyles: nodeStyles.join(";"),
stylesArray,
borderStyles,
backgroundStyles
};
}, "styles2String");
var userNodeOverrides = /* @__PURE__ */ __name((node, options) => {
const { themeVariables, handDrawnSeed } = getConfig2();
const { nodeBorder, mainBkg } = themeVariables;
const { stylesMap } = compileStyles(node);
const result = Object.assign(
{
roughness: 0.7,
fill: stylesMap.get("fill") || mainBkg,
fillStyle: "hachure",
// solid fill
fillWeight: 4,
hachureGap: 5.2,
stroke: stylesMap.get("stroke") || nodeBorder,
seed: handDrawnSeed,
strokeWidth: stylesMap.get("stroke-width")?.replace("px", "") || 1.3,
fillLineDash: [0, 0]
},
options
);
return result;
}, "userNodeOverrides");
// src/rendering-util/rendering-elements/clusters.js
var rect = /* @__PURE__ */ __name(async (parent, node) => {
log.info("Creating subgraph rect for ", node.id, node);
const siteConfig = getConfig2();
const { themeVariables, handDrawnSeed } = siteConfig;
const { clusterBkg, clusterBorder } = themeVariables;
const { labelStyles, nodeStyles, borderStyles, backgroundStyles } = styles2String(node);
const shapeSvg = parent.insert("g").attr("class", "cluster " + node.cssClasses).attr("id", node.id).attr("data-look", node.look);
const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels);
const labelEl = shapeSvg.insert("g").attr("class", "cluster-label ");
const text2 = await createText(labelEl, node.label, {
style: node.labelStyle,
useHtmlLabels,
isNode: true
});
let bbox = text2.getBBox();
if (evaluate(siteConfig.flowchart.htmlLabels)) {
const div = text2.children[0];
const dv = select3(text2);
bbox = div.getBoundingClientRect();
dv.attr("width", bbox.width);
dv.attr("height", bbox.height);
}
const width = node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width;
if (node.width <= bbox.width + node.padding) {
node.diff = (width - node.width) / 2 - node.padding;
} else {
node.diff = -node.padding;
}
const height = node.height;
const x = node.x - width / 2;
const y = node.y - height / 2;
log.trace("Data ", node, JSON.stringify(node));
let rect2;
if (node.look === "handDrawn") {
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {
roughness: 0.7,
fill: clusterBkg,
// fill: 'red',
stroke: clusterBorder,
fillWeight: 3,
seed: handDrawnSeed
});
const roughNode = rc.path(createRoundedRectPathD(x, y, width, height, 0), options);
rect2 = shapeSvg.insert(() => {
log.debug("Rough node insert CXC", roughNode);
return roughNode;
}, ":first-child");
rect2.select("path:nth-child(2)").attr("style", borderStyles.join(";"));
rect2.select("path").attr("style", backgroundStyles.join(";").replace("fill", "stroke"));
} else {
rect2 = shapeSvg.insert("rect", ":first-child");
rect2.attr("style", nodeStyles).attr("rx", node.rx).attr("ry", node.ry).attr("x", x).attr("y", y).attr("width", width).attr("height", height);
}
const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
labelEl.attr(
"transform",
// This puts the label on top of the box instead of inside it
`translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
);
if (labelStyles) {
const span = labelEl.select("span");
if (span) {
span.attr("style", labelStyles);
}
}
const rectBox = rect2.node().getBBox();
node.offsetX = 0;
node.width = rectBox.width;
node.height = rectBox.height;
node.offsetY = bbox.height - node.padding / 2;
node.intersect = function(point) {
return intersect_rect_default(node, point);
};
return { cluster: shapeSvg, labelBBox: bbox };
}, "rect");
var noteGroup = /* @__PURE__ */ __name((parent, node) => {
const shapeSvg = parent.insert("g").attr("class", "note-cluster").attr("id", node.id);
const rect2 = shapeSvg.insert("rect", ":first-child");
const padding = 0 * node.padding;
const halfPadding = padding / 2;
rect2.attr("rx", node.rx).attr("ry", node.ry).attr("x", node.x - node.width / 2 - halfPadding).attr("y", node.y - node.height / 2 - halfPadding).attr("width", node.width + padding).attr("height", node.height + padding).attr("fill", "none");
const rectBox = rect2.node().getBBox();
node.width = rectBox.width;
node.height = rectBox.height;
node.intersect = function(point) {
return intersect_rect_default(node, point);
};
return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } };
}, "noteGroup");
var roundedWithTitle = /* @__PURE__ */ __name(async (parent, node) => {
const siteConfig = getConfig2();
const { themeVariables, handDrawnSeed } = siteConfig;
const { altBackground, compositeBackground, compositeTitleBackground, nodeBorder } = themeVariables;
const shapeSvg = parent.insert("g").attr("class", node.cssClasses).attr("id", node.id).attr("data-id", node.id).attr("data-look", node.look);
const outerRectG = shapeSvg.insert("g", ":first-child");
const label = shapeSvg.insert("g").attr("class", "cluster-label");
let innerRect = shapeSvg.append("rect");
const text2 = label.node().appendChild(await createLabel_default(node.label, node.labelStyle, void 0, true));
let bbox = text2.getBBox();
if (evaluate(siteConfig.flowchart.htmlLabels)) {
const div = text2.children[0];
const dv = select3(text2);
bbox = div.getBoundingClientRect();
dv.attr("width", bbox.width);
dv.attr("height", bbox.height);
}
const padding = 0 * node.padding;
const halfPadding = padding / 2;
const width = (node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width) + padding;
if (node.width <= bbox.width + node.padding) {
node.diff = (width - node.width) / 2 - node.padding;
} else {
node.diff = -node.padding;
}
const height = node.height + padding;
const innerHeight = node.height + padding - bbox.height - 6;
const x = node.x - width / 2;
const y = node.y - height / 2;
node.width = width;
const innerY = node.y - node.height / 2 - halfPadding + bbox.height + 2;
let rect2;
if (node.look === "handDrawn") {
const isAlt = node.cssClasses.includes("statediagram-cluster-alt");
const rc = rough.svg(shapeSvg);
const roughOuterNode = node.rx || node.ry ? rc.path(createRoundedRectPathD(x, y, width, height, 10), {
roughness: 0.7,
fill: compositeTitleBackground,
fillStyle: "solid",
stroke: nodeBorder,
seed: handDrawnSeed
}) : rc.rectangle(x, y, width, height, { seed: handDrawnSeed });
rect2 = shapeSvg.insert(() => roughOuterNode, ":first-child");
const roughInnerNode = rc.rectangle(x, innerY, width, innerHeight, {
fill: isAlt ? altBackground : compositeBackground,
fillStyle: isAlt ? "hachure" : "solid",
stroke: nodeBorder,
seed: handDrawnSeed
});
rect2 = shapeSvg.insert(() => roughOuterNode, ":first-child");
innerRect = shapeSvg.insert(() => roughInnerNode);
} else {
rect2 = outerRectG.insert("rect", ":first-child");
const outerRectClass = "outer";
rect2.attr("class", outerRectClass).attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("data-look", node.look);
innerRect.attr("class", "inner").attr("x", x).attr("y", innerY).attr("width", width).attr("height", innerHeight);
}
label.attr(
"transform",
`translate(${node.x - bbox.width / 2}, ${y + 1 - (evaluate(siteConfig.flowchart.htmlLabels) ? 0 : 3)})`
);
const rectBox = rect2.node().getBBox();
node.height = rectBox.height;
node.offsetX = 0;
node.offsetY = bbox.height - node.padding / 2;
node.labelBBox = bbox;
node.intersect = function(point) {
return intersect_rect_default(node, point);
};
return { cluster: shapeSvg, labelBBox: bbox };
}, "roundedWithTitle");
var kanbanSection = /* @__PURE__ */ __name(async (parent, node) => {
log.info("Creating subgraph rect for ", node.id, node);
const siteConfig = getConfig2();
const { themeVariables, handDrawnSeed } = siteConfig;
const { clusterBkg, clusterBorder } = themeVariables;
const { labelStyles, nodeStyles, borderStyles, backgroundStyles } = styles2String(node);
const shapeSvg = parent.insert("g").attr("class", "cluster " + node.cssClasses).attr("id", node.id).attr("data-look", node.look);
const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels);
const labelEl = shapeSvg.insert("g").attr("class", "cluster-label ");
const text2 = await createText(labelEl, node.label, {
style: node.labelStyle,
useHtmlLabels,
isNode: true,
width: node.width
});
let bbox = text2.getBBox();
if (evaluate(siteConfig.flowchart.htmlLabels)) {
const div = text2.children[0];
const dv = select3(text2);
bbox = div.getBoundingClientRect();
dv.attr("width", bbox.width);
dv.attr("height", bbox.height);
}
const width = node.width <= bbox.width + node.padding ? bbox.width + node.padding : node.width;
if (node.width <= bbox.width + node.padding) {
node.diff = (width - node.width) / 2 - node.padding;
} else {
node.diff = -node.padding;
}
const height = node.height;
const x = node.x - width / 2;
const y = node.y - height / 2;
log.trace("Data ", node, JSON.stringify(node));
let rect2;
if (node.look === "handDrawn") {
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {
roughness: 0.7,
fill: clusterBkg,
// fill: 'red',
stroke: clusterBorder,
fillWeight: 4,
seed: handDrawnSeed
});
const roughNode = rc.path(createRoundedRectPathD(x, y, width, height, node.rx), options);
rect2 = shapeSvg.insert(() => {
log.debug("Rough node insert CXC", roughNode);
return roughNode;
}, ":first-child");
rect2.select("path:nth-child(2)").attr("style", borderStyles.join(";"));
rect2.select("path").attr("style", backgroundStyles.join(";").replace("fill", "stroke"));
} else {
rect2 = shapeSvg.insert("rect", ":first-child");
rect2.attr("style", nodeStyles).attr("rx", node.rx).attr("ry", node.ry).attr("x", x).attr("y", y).attr("width", width).attr("height", height);
}
const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
labelEl.attr(
"transform",
// This puts the label on top of the box instead of inside it
`translate(${node.x - bbox.width / 2}, ${node.y - node.height / 2 + subGraphTitleTopMargin})`
);
if (labelStyles) {
const span = labelEl.select("span");
if (span) {
span.attr("style", labelStyles);
}
}
const rectBox = rect2.node().getBBox();
node.offsetX = 0;
node.width = rectBox.width;
node.height = rectBox.height;
node.offsetY = bbox.height - node.padding / 2;
node.intersect = function(point) {
return intersect_rect_default(node, point);
};
return { cluster: shapeSvg, labelBBox: bbox };
}, "kanbanSection");
var divider = /* @__PURE__ */ __name((parent, node) => {
const siteConfig = getConfig2();
const { themeVariables, handDrawnSeed } = siteConfig;
const { nodeBorder } = themeVariables;
const shapeSvg = parent.insert("g").attr("class", node.cssClasses).attr("id", node.id).attr("data-look", node.look);
const outerRectG = shapeSvg.insert("g", ":first-child");
const padding = 0 * node.padding;
const width = node.width + padding;
node.diff = -node.padding;
const height = node.height + padding;
const x = node.x - width / 2;
const y = node.y - height / 2;
node.width = width;
let rect2;
if (node.look === "handDrawn") {
const rc = rough.svg(shapeSvg);
const roughOuterNode = rc.rectangle(x, y, width, height, {
fill: "lightgrey",
roughness: 0.5,
strokeLineDash: [5],
stroke: nodeBorder,
seed: handDrawnSeed
});
rect2 = shapeSvg.insert(() => roughOuterNode, ":first-child");
} else {
rect2 = outerRectG.insert("rect", ":first-child");
const outerRectClass = "divider";
rect2.attr("class", outerRectClass).attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("data-look", node.look);
}
const rectBox = rect2.node().getBBox();
node.height = rectBox.height;
node.offsetX = 0;
node.offsetY = 0;
node.intersect = function(point) {
return intersect_rect_default(node, point);
};
return { cluster: shapeSvg, labelBBox: {} };
}, "divider");
var squareRect = rect;
var shapes = {
rect,
squareRect,
roundedWithTitle,
noteGroup,
divider,
kanbanSection
};
var clusterElems = /* @__PURE__ */ new Map();
var insertCluster = /* @__PURE__ */ __name(async (elem, node) => {
const shape = node.shape || "rect";
const cluster = await shapes[shape](elem, node);
clusterElems.set(node.id, cluster);
return cluster;
}, "insertCluster");
var clear = /* @__PURE__ */ __name(() => {
clusterElems = /* @__PURE__ */ new Map();
}, "clear");
// src/rendering-util/rendering-elements/intersect/intersect-node.js
function intersectNode(node, point) {
return node.intersect(point);
}
__name(intersectNode, "intersectNode");
var intersect_node_default = intersectNode;
// src/rendering-util/rendering-elements/intersect/intersect-ellipse.js
function intersectEllipse(node, rx, ry, point) {
var cx = node.x;
var cy = node.y;
var px = cx - point.x;
var py = cy - point.y;
var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px);
var dx = Math.abs(rx * ry * px / det);
if (point.x < cx) {
dx = -dx;
}
var dy = Math.abs(rx * ry * py / det);
if (point.y < cy) {
dy = -dy;
}
return { x: cx + dx, y: cy + dy };
}
__name(intersectEllipse, "intersectEllipse");
var intersect_ellipse_default = intersectEllipse;
// src/rendering-util/rendering-elements/intersect/intersect-circle.js
function intersectCircle(node, rx, point) {
return intersect_ellipse_default(node, rx, rx, point);
}
__name(intersectCircle, "intersectCircle");
var intersect_circle_default = intersectCircle;
// src/rendering-util/rendering-elements/intersect/intersect-line.js
function intersectLine(p1, p2, q1, q2) {
var a1, a2, b1, b2, c1, c2;
var r1, r2, r3, r4;
var denom, offset, num;
var x, y;
a1 = p2.y - p1.y;
b1 = p1.x - p2.x;
c1 = p2.x * p1.y - p1.x * p2.y;
r3 = a1 * q1.x + b1 * q1.y + c1;
r4 = a1 * q2.x + b1 * q2.y + c1;
if (r3 !== 0 && r4 !== 0 && sameSign(r3, r4)) {
return;
}
a2 = q2.y - q1.y;
b2 = q1.x - q2.x;
c2 = q2.x * q1.y - q1.x * q2.y;
r1 = a2 * p1.x + b2 * p1.y + c2;
r2 = a2 * p2.x + b2 * p2.y + c2;
if (r1 !== 0 && r2 !== 0 && sameSign(r1, r2)) {
return;
}
denom = a1 * b2 - a2 * b1;
if (denom === 0) {
return;
}
offset = Math.abs(denom / 2);
num = b1 * c2 - b2 * c1;
x = num < 0 ? (num - offset) / denom : (num + offset) / denom;
num = a2 * c1 - a1 * c2;
y = num < 0 ? (num - offset) / denom : (num + offset) / denom;
return { x, y };
}
__name(intersectLine, "intersectLine");
function sameSign(r1, r2) {
return r1 * r2 > 0;
}
__name(sameSign, "sameSign");
var intersect_line_default = intersectLine;
// src/rendering-util/rendering-elements/intersect/intersect-polygon.js
function intersectPolygon(node, polyPoints, point) {
let x1 = node.x;
let y1 = node.y;
let intersections = [];
let minX = Number.POSITIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
if (typeof polyPoints.forEach === "function") {
polyPoints.forEach(function(entry) {
minX = Math.min(minX, entry.x);
minY = Math.min(minY, entry.y);
});
} else {
minX = Math.min(minX, polyPoints.x);
minY = Math.min(minY, polyPoints.y);
}
let left = x1 - node.width / 2 - minX;
let top = y1 - node.height / 2 - minY;
for (let i = 0; i < polyPoints.length; i++) {
let p1 = polyPoints[i];
let p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
let intersect = intersect_line_default(
node,
point,
{ x: left + p1.x, y: top + p1.y },
{ x: left + p2.x, y: top + p2.y }
);
if (intersect) {
intersections.push(intersect);
}
}
if (!intersections.length) {
return node;
}
if (intersections.length > 1) {
intersections.sort(function(p, q) {
let pdx = p.x - point.x;
let pdy = p.y - point.y;
let distp = Math.sqrt(pdx * pdx + pdy * pdy);
let qdx = q.x - point.x;
let qdy = q.y - point.y;
let distq = Math.sqrt(qdx * qdx + qdy * qdy);
return distp < distq ? -1 : distp === distq ? 0 : 1;
});
}
return intersections[0];
}
__name(intersectPolygon, "intersectPolygon");
var intersect_polygon_default = intersectPolygon;
// src/rendering-util/rendering-elements/intersect/index.js
var intersect_default = {
node: intersect_node_default,
circle: intersect_circle_default,
ellipse: intersect_ellipse_default,
polygon: intersect_polygon_default,
rect: intersect_rect_default
};
// src/rendering-util/rendering-elements/shapes/anchor.ts
import rough2 from "roughjs";
function anchor(parent, node) {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
const classes = getNodeClasses(node);
let cssClasses = classes;
if (!classes) {
cssClasses = "anchor";
}
const shapeSvg = parent.insert("g").attr("class", cssClasses).attr("id", node.domId || node.id);
const radius = 1;
const { cssStyles } = node;
const rc = rough2.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: "black", stroke: "none", fillStyle: "solid" });
if (node.look !== "handDrawn") {
options.roughness = 0;
}
const roughNode = rc.circle(0, 0, radius * 2, options);
const circleElem = shapeSvg.insert(() => roughNode, ":first-child");
circleElem.attr("class", "anchor").attr("style", handleUndefinedAttr(cssStyles));
updateNodeBounds(node, circleElem);
node.intersect = function(point) {
log.info("Circle intersect", node, radius, point);
return intersect_default.circle(node, radius, point);
};
return shapeSvg;
}
__name(anchor, "anchor");
// src/rendering-util/rendering-elements/shapes/bowTieRect.ts
import rough3 from "roughjs";
function generateArcPoints(x1, y1, x2, y2, rx, ry, clockwise) {
const numPoints = 20;
const midX = (x1 + x2) / 2;
const midY = (y1 + y2) / 2;
const angle = Math.atan2(y2 - y1, x2 - x1);
const dx = (x2 - x1) / 2;
const dy = (y2 - y1) / 2;
const transformedX = dx / rx;
const transformedY = dy / ry;
const distance = Math.sqrt(transformedX ** 2 + transformedY ** 2);
if (distance > 1) {
throw new Error("The given radii are too small to create an arc between the points.");
}
const scaledCenterDistance = Math.sqrt(1 - distance ** 2);
const centerX = midX + scaledCenterDistance * ry * Math.sin(angle) * (clockwise ? -1 : 1);
const centerY = midY - scaledCenterDistance * rx * Math.cos(angle) * (clockwise ? -1 : 1);
const startAngle = Math.atan2((y1 - centerY) / ry, (x1 - centerX) / rx);
const endAngle = Math.atan2((y2 - centerY) / ry, (x2 - centerX) / rx);
let angleRange = endAngle - startAngle;
if (clockwise && angleRange < 0) {
angleRange += 2 * Math.PI;
}
if (!clockwise && angleRange > 0) {
angleRange -= 2 * Math.PI;
}
const points = [];
for (let i = 0; i < numPoints; i++) {
const t = i / (numPoints - 1);
const angle2 = startAngle + t * angleRange;
const x = centerX + rx * Math.cos(angle2);
const y = centerY + ry * Math.sin(angle2);
points.push({ x, y });
}
return points;
}
__name(generateArcPoints, "generateArcPoints");
async function bowTieRect(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + node.padding + 20;
const h = bbox.height + node.padding;
const ry = h / 2;
const rx = ry / (2.5 + h / 50);
const { cssStyles } = node;
const points = [
{ x: w / 2, y: -h / 2 },
{ x: -w / 2, y: -h / 2 },
...generateArcPoints(-w / 2, -h / 2, -w / 2, h / 2, rx, ry, false),
{ x: w / 2, y: h / 2 },
...generateArcPoints(w / 2, h / 2, w / 2, -h / 2, rx, ry, true)
];
const rc = rough3.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const bowTieRectPath = createPathFromPoints(points);
const bowTieRectShapePath = rc.path(bowTieRectPath, options);
const bowTieRectShape = shapeSvg.insert(() => bowTieRectShapePath, ":first-child");
bowTieRectShape.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
bowTieRectShape.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
bowTieRectShape.selectAll("path").attr("style", nodeStyles);
}
bowTieRectShape.attr("transform", `translate(${rx / 2}, 0)`);
updateNodeBounds(node, bowTieRectShape);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(bowTieRect, "bowTieRect");
// src/rendering-util/rendering-elements/shapes/card.ts
import rough4 from "roughjs";
// src/rendering-util/rendering-elements/shapes/insertPolygonShape.ts
function insertPolygonShape(parent, w, h, points) {
return parent.insert("polygon", ":first-child").attr(
"points",
points.map(function(d) {
return d.x + "," + d.y;
}).join(" ")
).attr("class", "label-container").attr("transform", "translate(" + -w / 2 + "," + h / 2 + ")");
}
__name(insertPolygonShape, "insertPolygonShape");
// src/rendering-util/rendering-elements/shapes/card.ts
async function card(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const h = bbox.height + node.padding;
const padding = 12;
const w = bbox.width + node.padding + padding;
const left = 0;
const right = w;
const top = -h;
const bottom = 0;
const points = [
{ x: left + padding, y: top },
{ x: right, y: top },
{ x: right, y: bottom },
{ x: left, y: bottom },
{ x: left, y: top + padding },
{ x: left + padding, y: top }
];
let polygon;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough4.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-w / 2}, ${h / 2})`);
if (cssStyles) {
polygon.attr("style", cssStyles);
}
} else {
polygon = insertPolygonShape(shapeSvg, w, h, points);
}
if (nodeStyles) {
polygon.attr("style", nodeStyles);
}
updateNodeBounds(node, polygon);
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(card, "card");
// src/rendering-util/rendering-elements/shapes/choice.ts
import rough5 from "roughjs";
function choice(parent, node) {
const { nodeStyles } = styles2String(node);
node.label = "";
const shapeSvg = parent.insert("g").attr("class", getNodeClasses(node)).attr("id", node.domId ?? node.id);
const { cssStyles } = node;
const s = Math.max(28, node.width ?? 0);
const points = [
{ x: 0, y: s / 2 },
{ x: s / 2, y: 0 },
{ x: 0, y: -s / 2 },
{ x: -s / 2, y: 0 }
];
const rc = rough5.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const choicePath = createPathFromPoints(points);
const roughNode = rc.path(choicePath, options);
const choiceShape = shapeSvg.insert(() => roughNode, ":first-child");
if (cssStyles && node.look !== "handDrawn") {
choiceShape.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
choiceShape.selectAll("path").attr("style", nodeStyles);
}
node.width = 28;
node.height = 28;
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(choice, "choice");
// src/rendering-util/rendering-elements/shapes/circle.ts
import rough6 from "roughjs";
async function circle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node));
const radius = bbox.width / 2 + halfPadding;
let circleElem;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough6.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const roughNode = rc.circle(0, 0, radius * 2, options);
circleElem = shapeSvg.insert(() => roughNode, ":first-child");
circleElem.attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles));
} else {
circleElem = shapeSvg.insert("circle", ":first-child").attr("class", "basic label-container").attr("style", nodeStyles).attr("r", radius).attr("cx", 0).attr("cy", 0);
}
updateNodeBounds(node, circleElem);
node.intersect = function(point) {
log.info("Circle intersect", node, radius, point);
return intersect_default.circle(node, radius, point);
};
return shapeSvg;
}
__name(circle, "circle");
// src/rendering-util/rendering-elements/shapes/crossedCircle.ts
import rough7 from "roughjs";
function createLine(r) {
const xAxis45 = Math.cos(Math.PI / 4);
const yAxis45 = Math.sin(Math.PI / 4);
const lineLength = r * 2;
const pointQ1 = { x: lineLength / 2 * xAxis45, y: lineLength / 2 * yAxis45 };
const pointQ2 = { x: -(lineLength / 2) * xAxis45, y: lineLength / 2 * yAxis45 };
const pointQ3 = { x: -(lineLength / 2) * xAxis45, y: -(lineLength / 2) * yAxis45 };
const pointQ4 = { x: lineLength / 2 * xAxis45, y: -(lineLength / 2) * yAxis45 };
return `M ${pointQ2.x},${pointQ2.y} L ${pointQ4.x},${pointQ4.y}
M ${pointQ1.x},${pointQ1.y} L ${pointQ3.x},${pointQ3.y}`;
}
__name(createLine, "createLine");
function crossedCircle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
node.label = "";
const shapeSvg = parent.insert("g").attr("class", getNodeClasses(node)).attr("id", node.domId ?? node.id);
const radius = Math.max(30, node?.width ?? 0);
const { cssStyles } = node;
const rc = rough7.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const circleNode = rc.circle(0, 0, radius * 2, options);
const linePath = createLine(radius);
const lineNode = rc.path(linePath, options);
const crossedCircle2 = shapeSvg.insert(() => circleNode, ":first-child");
crossedCircle2.insert(() => lineNode);
if (cssStyles && node.look !== "handDrawn") {
crossedCircle2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
crossedCircle2.selectAll("path").attr("style", nodeStyles);
}
updateNodeBounds(node, crossedCircle2);
node.intersect = function(point) {
log.info("crossedCircle intersect", node, { radius, point });
const pos = intersect_default.circle(node, radius, point);
return pos;
};
return shapeSvg;
}
__name(crossedCircle, "crossedCircle");
// src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts
import rough8 from "roughjs";
function generateCirclePoints2(centerX, centerY, radius, numPoints = 100, startAngle = 0, endAngle = 180) {
const points = [];
const startAngleRad = startAngle * Math.PI / 180;
const endAngleRad = endAngle * Math.PI / 180;
const angleRange = endAngleRad - startAngleRad;
const angleStep = angleRange / (numPoints - 1);
for (let i = 0; i < numPoints; i++) {
const angle = startAngleRad + i * angleStep;
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
points.push({ x: -x, y: -y });
}
return points;
}
__name(generateCirclePoints2, "generateCirclePoints");
async function curlyBraceLeft(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + (node.padding ?? 0);
const h = bbox.height + (node.padding ?? 0);
const radius = Math.max(5, h * 0.1);
const { cssStyles } = node;
const points = [
...generateCirclePoints2(w / 2, -h / 2, radius, 30, -90, 0),
{ x: -w / 2 - radius, y: radius },
...generateCirclePoints2(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
...generateCirclePoints2(w / 2 + radius * 2, radius, radius, 20, -90, -180),
{ x: -w / 2 - radius, y: -h / 2 },
...generateCirclePoints2(w / 2, h / 2, radius, 20, 0, 90)
];
const rectPoints = [
{ x: w / 2, y: -h / 2 - radius },
{ x: -w / 2, y: -h / 2 - radius },
...generateCirclePoints2(w / 2, -h / 2, radius, 20, -90, 0),
{ x: -w / 2 - radius, y: -radius },
...generateCirclePoints2(w / 2 + w * 0.1, -radius, radius, 20, -180, -270),
...generateCirclePoints2(w / 2 + w * 0.1, radius, radius, 20, -90, -180),
{ x: -w / 2 - radius, y: h / 2 },
...generateCirclePoints2(w / 2, h / 2, radius, 20, 0, 90),
{ x: -w / 2, y: h / 2 + radius },
{ x: w / 2, y: h / 2 + radius }
];
const rc = rough8.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: "none" });
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const curlyBraceLeftPath = createPathFromPoints(points);
const newCurlyBracePath = curlyBraceLeftPath.replace("Z", "");
const curlyBraceLeftNode = rc.path(newCurlyBracePath, options);
const rectPath = createPathFromPoints(rectPoints);
const rectShape = rc.path(rectPath, { ...options });
const curlyBraceLeftShape = shapeSvg.insert("g", ":first-child");
curlyBraceLeftShape.insert(() => rectShape, ":first-child").attr("stroke-opacity", 0);
curlyBraceLeftShape.insert(() => curlyBraceLeftNode, ":first-child");
curlyBraceLeftShape.attr("class", "text");
if (cssStyles && node.look !== "handDrawn") {
curlyBraceLeftShape.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
curlyBraceLeftShape.selectAll("path").attr("style", nodeStyles);
}
curlyBraceLeftShape.attr("transform", `translate(${radius}, 0)`);
label.attr(
"transform",
`translate(${-w / 2 + radius - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, curlyBraceLeftShape);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, rectPoints, point);
return pos;
};
return shapeSvg;
}
__name(curlyBraceLeft, "curlyBraceLeft");
// src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts
import rough9 from "roughjs";
function generateCirclePoints3(centerX, centerY, radius, numPoints = 100, startAngle = 0, endAngle = 180) {
const points = [];
const startAngleRad = startAngle * Math.PI / 180;
const endAngleRad = endAngle * Math.PI / 180;
const angleRange = endAngleRad - startAngleRad;
const angleStep = angleRange / (numPoints - 1);
for (let i = 0; i < numPoints; i++) {
const angle = startAngleRad + i * angleStep;
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
points.push({ x, y });
}
return points;
}
__name(generateCirclePoints3, "generateCirclePoints");
async function curlyBraceRight(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + (node.padding ?? 0);
const h = bbox.height + (node.padding ?? 0);
const radius = Math.max(5, h * 0.1);
const { cssStyles } = node;
const points = [
...generateCirclePoints3(w / 2, -h / 2, radius, 20, -90, 0),
{ x: w / 2 + radius, y: -radius },
...generateCirclePoints3(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
...generateCirclePoints3(w / 2 + radius * 2, radius, radius, 20, -90, -180),
{ x: w / 2 + radius, y: h / 2 },
...generateCirclePoints3(w / 2, h / 2, radius, 20, 0, 90)
];
const rectPoints = [
{ x: -w / 2, y: -h / 2 - radius },
{ x: w / 2, y: -h / 2 - radius },
...generateCirclePoints3(w / 2, -h / 2, radius, 20, -90, 0),
{ x: w / 2 + radius, y: -radius },
...generateCirclePoints3(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
...generateCirclePoints3(w / 2 + radius * 2, radius, radius, 20, -90, -180),
{ x: w / 2 + radius, y: h / 2 },
...generateCirclePoints3(w / 2, h / 2, radius, 20, 0, 90),
{ x: w / 2, y: h / 2 + radius },
{ x: -w / 2, y: h / 2 + radius }
];
const rc = rough9.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: "none" });
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const curlyBraceRightPath = createPathFromPoints(points);
const newCurlyBracePath = curlyBraceRightPath.replace("Z", "");
const curlyBraceRightNode = rc.path(newCurlyBracePath, options);
const rectPath = createPathFromPoints(rectPoints);
const rectShape = rc.path(rectPath, { ...options });
const curlyBraceRightShape = shapeSvg.insert("g", ":first-child");
curlyBraceRightShape.insert(() => rectShape, ":first-child").attr("stroke-opacity", 0);
curlyBraceRightShape.insert(() => curlyBraceRightNode, ":first-child");
curlyBraceRightShape.attr("class", "text");
if (cssStyles && node.look !== "handDrawn") {
curlyBraceRightShape.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
curlyBraceRightShape.selectAll("path").attr("style", nodeStyles);
}
curlyBraceRightShape.attr("transform", `translate(${-radius}, 0)`);
label.attr(
"transform",
`translate(${-w / 2 + (node.padding ?? 0) / 2 - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, curlyBraceRightShape);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, rectPoints, point);
return pos;
};
return shapeSvg;
}
__name(curlyBraceRight, "curlyBraceRight");
// src/rendering-util/rendering-elements/shapes/curlyBraces.ts
import rough10 from "roughjs";
function generateCirclePoints4(centerX, centerY, radius, numPoints = 100, startAngle = 0, endAngle = 180) {
const points = [];
const startAngleRad = startAngle * Math.PI / 180;
const endAngleRad = endAngle * Math.PI / 180;
const angleRange = endAngleRad - startAngleRad;
const angleStep = angleRange / (numPoints - 1);
for (let i = 0; i < numPoints; i++) {
const angle = startAngleRad + i * angleStep;
const x = centerX + radius * Math.cos(angle);
const y = centerY + radius * Math.sin(angle);
points.push({ x: -x, y: -y });
}
return points;
}
__name(generateCirclePoints4, "generateCirclePoints");
async function curlyBraces(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + (node.padding ?? 0);
const h = bbox.height + (node.padding ?? 0);
const radius = Math.max(5, h * 0.1);
const { cssStyles } = node;
const leftCurlyBracePoints = [
...generateCirclePoints4(w / 2, -h / 2, radius, 30, -90, 0),
{ x: -w / 2 - radius, y: radius },
...generateCirclePoints4(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
...generateCirclePoints4(w / 2 + radius * 2, radius, radius, 20, -90, -180),
{ x: -w / 2 - radius, y: -h / 2 },
...generateCirclePoints4(w / 2, h / 2, radius, 20, 0, 90)
];
const rightCurlyBracePoints = [
...generateCirclePoints4(-w / 2 + radius + radius / 2, -h / 2, radius, 20, -90, -180),
{ x: w / 2 - radius / 2, y: radius },
...generateCirclePoints4(-w / 2 - radius / 2, -radius, radius, 20, 0, 90),
...generateCirclePoints4(-w / 2 - radius / 2, radius, radius, 20, -90, 0),
{ x: w / 2 - radius / 2, y: -radius },
...generateCirclePoints4(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270)
];
const rectPoints = [
{ x: w / 2, y: -h / 2 - radius },
{ x: -w / 2, y: -h / 2 - radius },
...generateCirclePoints4(w / 2, -h / 2, radius, 20, -90, 0),
{ x: -w / 2 - radius, y: -radius },
...generateCirclePoints4(w / 2 + radius * 2, -radius, radius, 20, -180, -270),
...generateCirclePoints4(w / 2 + radius * 2, radius, radius, 20, -90, -180),
{ x: -w / 2 - radius, y: h / 2 },
...generateCirclePoints4(w / 2, h / 2, radius, 20, 0, 90),
{ x: -w / 2, y: h / 2 + radius },
{ x: w / 2 - radius - radius / 2, y: h / 2 + radius },
...generateCirclePoints4(-w / 2 + radius + radius / 2, -h / 2, radius, 20, -90, -180),
{ x: w / 2 - radius / 2, y: radius },
...generateCirclePoints4(-w / 2 - radius / 2, -radius, radius, 20, 0, 90),
...generateCirclePoints4(-w / 2 - radius / 2, radius, radius, 20, -90, 0),
{ x: w / 2 - radius / 2, y: -radius },
...generateCirclePoints4(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270)
];
const rc = rough10.svg(shapeSvg);
const options = userNodeOverrides(node, { fill: "none" });
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const leftCurlyBracePath = createPathFromPoints(leftCurlyBracePoints);
const newLeftCurlyBracePath = leftCurlyBracePath.replace("Z", "");
const leftCurlyBraceNode = rc.path(newLeftCurlyBracePath, options);
const rightCurlyBracePath = createPathFromPoints(rightCurlyBracePoints);
const newRightCurlyBracePath = rightCurlyBracePath.replace("Z", "");
const rightCurlyBraceNode = rc.path(newRightCurlyBracePath, options);
const rectPath = createPathFromPoints(rectPoints);
const rectShape = rc.path(rectPath, { ...options });
const curlyBracesShape = shapeSvg.insert("g", ":first-child");
curlyBracesShape.insert(() => rectShape, ":first-child").attr("stroke-opacity", 0);
curlyBracesShape.insert(() => leftCurlyBraceNode, ":first-child");
curlyBracesShape.insert(() => rightCurlyBraceNode, ":first-child");
curlyBracesShape.attr("class", "text");
if (cssStyles && node.look !== "handDrawn") {
curlyBracesShape.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
curlyBracesShape.selectAll("path").attr("style", nodeStyles);
}
curlyBracesShape.attr("transform", `translate(${radius - radius / 4}, 0)`);
label.attr(
"transform",
`translate(${-w / 2 + (node.padding ?? 0) / 2 - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, curlyBracesShape);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, rectPoints, point);
return pos;
};
return shapeSvg;
}
__name(curlyBraces, "curlyBraces");
// src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts
import rough11 from "roughjs";
async function curvedTrapezoid(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const minWidth = 80, minHeight = 20;
const w = Math.max(minWidth, (bbox.width + (node.padding ?? 0) * 2) * 1.25, node?.width ?? 0);
const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const radius = h / 2;
const { cssStyles } = node;
const rc = rough11.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const totalWidth = w, totalHeight = h;
const rw = totalWidth - radius;
const tw = totalHeight / 4;
const points = [
{ x: rw, y: 0 },
{ x: tw, y: 0 },
{ x: 0, y: totalHeight / 2 },
{ x: tw, y: totalHeight },
{ x: rw, y: totalHeight },
...generateCirclePoints(-rw, -totalHeight / 2, radius, 50, 270, 90)
];
const pathData = createPathFromPoints(points);
const shapeNode = rc.path(pathData, options);
const polygon = shapeSvg.insert(() => shapeNode, ":first-child");
polygon.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", nodeStyles);
}
polygon.attr("transform", `translate(${-w / 2}, ${-h / 2})`);
updateNodeBounds(node, polygon);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(curvedTrapezoid, "curvedTrapezoid");
// src/rendering-util/rendering-elements/shapes/cylinder.ts
import rough12 from "roughjs";
var createCylinderPathD = /* @__PURE__ */ __name((x, y, width, height, rx, ry) => {
return [
`M${x},${y + ry}`,
`a${rx},${ry} 0,0,0 ${width},0`,
`a${rx},${ry} 0,0,0 ${-width},0`,
`l0,${height}`,
`a${rx},${ry} 0,0,0 ${width},0`,
`l0,${-height}`
].join(" ");
}, "createCylinderPathD");
var createOuterCylinderPathD = /* @__PURE__ */ __name((x, y, width, height, rx, ry) => {
return [
`M${x},${y + ry}`,
`M${x + width},${y + ry}`,
`a${rx},${ry} 0,0,0 ${-width},0`,
`l0,${height}`,
`a${rx},${ry} 0,0,0 ${width},0`,
`l0,${-height}`
].join(" ");
}, "createOuterCylinderPathD");
var createInnerCylinderPathD = /* @__PURE__ */ __name((x, y, width, height, rx, ry) => {
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(" ");
}, "createInnerCylinderPathD");
async function cylinder(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + node.padding, node.width ?? 0);
const rx = w / 2;
const ry = rx / (2.5 + w / 50);
const h = Math.max(bbox.height + ry + node.padding, node.height ?? 0);
let cylinder2;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough12.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);
const outerNode = rc.path(outerPathData, userNodeOverrides(node, {}));
const innerLine = rc.path(innerPathData, userNodeOverrides(node, { fill: "none" }));
cylinder2 = shapeSvg.insert(() => innerLine, ":first-child");
cylinder2 = shapeSvg.insert(() => outerNode, ":first-child");
cylinder2.attr("class", "basic label-container");
if (cssStyles) {
cylinder2.attr("style", cssStyles);
}
} else {
const pathData = createCylinderPathD(0, 0, w, h, rx, ry);
cylinder2 = shapeSvg.insert("path", ":first-child").attr("d", pathData).attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles)).attr("style", nodeStyles);
}
cylinder2.attr("label-offset-y", ry);
cylinder2.attr("transform", `translate(${-w / 2}, ${-(h / 2 + ry)})`);
updateNodeBounds(node, cylinder2);
label.attr(
"transform",
`translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + (node.padding ?? 0) / 1.5 - (bbox.y - (bbox.top ?? 0))})`
);
node.intersect = function(point) {
const pos = intersect_default.rect(node, point);
const x = pos.x - (node.x ?? 0);
if (rx != 0 && (Math.abs(x) < (node.width ?? 0) / 2 || Math.abs(x) == (node.width ?? 0) / 2 && Math.abs(pos.y - (node.y ?? 0)) > (node.height ?? 0) / 2 - ry)) {
let y = ry * ry * (1 - x * x / (rx * rx));
if (y > 0) {
y = Math.sqrt(y);
}
y = ry - y;
if (point.y - (node.y ?? 0) > 0) {
y = -y;
}
pos.y += y;
}
return pos;
};
return shapeSvg;
}
__name(cylinder, "cylinder");
// src/rendering-util/rendering-elements/shapes/dividedRect.ts
import rough13 from "roughjs";
async function dividedRectangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + node.padding;
const h = bbox.height + node.padding;
const rectOffset = h * 0.2;
const x = -w / 2;
const y = -h / 2 - rectOffset / 2;
const { cssStyles } = node;
const rc = rough13.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const pts = [
{ x, y: y + rectOffset },
{ x: -x, y: y + rectOffset },
{ x: -x, y: -y },
{ x, y: -y },
{ x, y },
{ x: -x, y },
{ x: -x, y: y + rectOffset }
];
const poly = rc.polygon(
pts.map((p) => [p.x, p.y]),
options
);
const polygon = shapeSvg.insert(() => poly, ":first-child");
polygon.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
polygon.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectAll("path").attr("style", nodeStyles);
}
label.attr(
"transform",
`translate(${x + (node.padding ?? 0) / 2 - (bbox.x - (bbox.left ?? 0))}, ${y + rectOffset + (node.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, polygon);
node.intersect = function(point) {
const pos = intersect_default.rect(node, point);
return pos;
};
return shapeSvg;
}
__name(dividedRectangle, "dividedRectangle");
// src/rendering-util/rendering-elements/shapes/doubleCircle.ts
import rough14 from "roughjs";
async function doublecircle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node));
const gap = 5;
const outerRadius = bbox.width / 2 + halfPadding + gap;
const innerRadius = bbox.width / 2 + halfPadding;
let circleGroup;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough14.svg(shapeSvg);
const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 });
const innerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 1.5 });
const outerRoughNode = rc.circle(0, 0, outerRadius * 2, outerOptions);
const innerRoughNode = rc.circle(0, 0, innerRadius * 2, innerOptions);
circleGroup = shapeSvg.insert("g", ":first-child");
circleGroup.attr("class", handleUndefinedAttr(node.cssClasses)).attr("style", handleUndefinedAttr(cssStyles));
circleGroup.node()?.appendChild(outerRoughNode);
circleGroup.node()?.appendChild(innerRoughNode);
} else {
circleGroup = shapeSvg.insert("g", ":first-child");
const outerCircle = circleGroup.insert("circle", ":first-child");
const innerCircle = circleGroup.insert("circle");
circleGroup.attr("class", "basic label-container").attr("style", nodeStyles);
outerCircle.attr("class", "outer-circle").attr("style", nodeStyles).attr("r", outerRadius).attr("cx", 0).attr("cy", 0);
innerCircle.attr("class", "inner-circle").attr("style", nodeStyles).attr("r", innerRadius).attr("cx", 0).attr("cy", 0);
}
updateNodeBounds(node, circleGroup);
node.intersect = function(point) {
log.info("DoubleCircle intersect", node, outerRadius, point);
return intersect_default.circle(node, outerRadius, point);
};
return shapeSvg;
}
__name(doublecircle, "doublecircle");
// src/rendering-util/rendering-elements/shapes/filledCircle.ts
import rough15 from "roughjs";
function filledCircle(parent, node, { config: { themeVariables } }) {
const { labelStyles, nodeStyles } = styles2String(node);
node.label = "";
node.labelStyle = labelStyles;
const shapeSvg = parent.insert("g").attr("class", getNodeClasses(node)).attr("id", node.domId ?? node.id);
const radius = 7;
const { cssStyles } = node;
const rc = rough15.svg(shapeSvg);
const { nodeBorder } = themeVariables;
const options = userNodeOverrides(node, { fillStyle: "solid" });
if (node.look !== "handDrawn") {
options.roughness = 0;
}
const circleNode = rc.circle(0, 0, radius * 2, options);
const filledCircle2 = shapeSvg.insert(() => circleNode, ":first-child");
filledCircle2.selectAll("path").attr("style", `fill: ${nodeBorder} !important;`);
if (cssStyles && cssStyles.length > 0 && node.look !== "handDrawn") {
filledCircle2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
filledCircle2.selectAll("path").attr("style", nodeStyles);
}
updateNodeBounds(node, filledCircle2);
node.intersect = function(point) {
log.info("filledCircle intersect", node, { radius, point });
const pos = intersect_default.circle(node, radius, point);
return pos;
};
return shapeSvg;
}
__name(filledCircle, "filledCircle");
// src/rendering-util/rendering-elements/shapes/flippedTriangle.ts
import rough16 from "roughjs";
async function flippedTriangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + (node.padding ?? 0);
const h = w + bbox.height;
const tw = w + bbox.height;
const points = [
{ x: 0, y: -h },
{ x: tw, y: -h },
{ x: tw / 2, y: 0 }
];
const { cssStyles } = node;
const rc = rough16.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
const flippedTriangle2 = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-h / 2}, ${h / 2})`);
if (cssStyles && node.look !== "handDrawn") {
flippedTriangle2.selectChildren("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
flippedTriangle2.selectChildren("path").attr("style", nodeStyles);
}
node.width = w;
node.height = h;
updateNodeBounds(node, flippedTriangle2);
label.attr(
"transform",
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${-h / 2 + (node.padding ?? 0) / 2 + (bbox.y - (bbox.top ?? 0))})`
);
node.intersect = function(point) {
log.info("Triangle intersect", node, points, point);
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(flippedTriangle, "flippedTriangle");
// src/rendering-util/rendering-elements/shapes/forkJoin.ts
import rough17 from "roughjs";
function forkJoin(parent, node, { dir, config: { state: state2, themeVariables } }) {
const { nodeStyles } = styles2String(node);
node.label = "";
const shapeSvg = parent.insert("g").attr("class", getNodeClasses(node)).attr("id", node.domId ?? node.id);
const { cssStyles } = node;
let width = Math.max(70, node?.width ?? 0);
let height = Math.max(10, node?.height ?? 0);
if (dir === "LR") {
width = Math.max(10, node?.width ?? 0);
height = Math.max(70, node?.height ?? 0);
}
const x = -1 * width / 2;
const y = -1 * height / 2;
const rc = rough17.svg(shapeSvg);
const options = userNodeOverrides(node, {
stroke: themeVariables.lineColor,
fill: themeVariables.lineColor
});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const roughNode = rc.rectangle(x, y, width, height, options);
const shape = shapeSvg.insert(() => roughNode, ":first-child");
if (cssStyles && node.look !== "handDrawn") {
shape.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
shape.selectAll("path").attr("style", nodeStyles);
}
updateNodeBounds(node, shape);
const padding = state2?.padding ?? 0;
if (node.width && node.height) {
node.width += padding / 2 || 0;
node.height += padding / 2 || 0;
}
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(forkJoin, "forkJoin");
// src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts
import rough18 from "roughjs";
async function halfRoundedRectangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const minWidth = 80, minHeight = 50;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(minWidth, bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const radius = h / 2;
const { cssStyles } = node;
const rc = rough18.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x: -w / 2, y: -h / 2 },
{ x: w / 2 - radius, y: -h / 2 },
...generateCirclePoints(-w / 2 + radius, 0, radius, 50, 90, 270),
{ x: w / 2 - radius, y: h / 2 },
{ x: -w / 2, y: h / 2 }
];
const pathData = createPathFromPoints(points);
const shapeNode = rc.path(pathData, options);
const polygon = shapeSvg.insert(() => shapeNode, ":first-child");
polygon.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", nodeStyles);
}
updateNodeBounds(node, polygon);
node.intersect = function(point) {
log.info("Pill intersect", node, { radius, point });
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(halfRoundedRectangle, "halfRoundedRectangle");
// src/rendering-util/rendering-elements/shapes/hexagon.ts
import rough19 from "roughjs";
var createHexagonPathD = /* @__PURE__ */ __name((x, y, width, height, m) => {
return [
`M${x + m},${y}`,
`L${x + width - m},${y}`,
`L${x + width},${y - height / 2}`,
`L${x + width - m},${y - height}`,
`L${x + m},${y - height}`,
`L${x},${y - height / 2}`,
"Z"
].join(" ");
}, "createHexagonPathD");
async function hexagon(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const f = 4;
const h = bbox.height + node.padding;
const m = h / f;
const w = bbox.width + 2 * m + node.padding;
const points = [
{ x: m, y: 0 },
{ x: w - m, y: 0 },
{ x: w, y: -h / 2 },
{ x: w - m, y: -h },
{ x: m, y: -h },
{ x: 0, y: -h / 2 }
];
let polygon;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough19.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createHexagonPathD(0, 0, w, h, m);
const roughNode = rc.path(pathData, options);
polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-w / 2}, ${h / 2})`);
if (cssStyles) {
polygon.attr("style", cssStyles);
}
} else {
polygon = insertPolygonShape(shapeSvg, w, h, points);
}
if (nodeStyles) {
polygon.attr("style", nodeStyles);
}
node.width = w;
node.height = h;
updateNodeBounds(node, polygon);
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(hexagon, "hexagon");
// src/rendering-util/rendering-elements/shapes/hourglass.ts
import rough20 from "roughjs";
async function hourglass(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.label = "";
node.labelStyle = labelStyles;
const { shapeSvg } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(30, node?.width ?? 0);
const h = Math.max(30, node?.height ?? 0);
const { cssStyles } = node;
const rc = rough20.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x: 0, y: 0 },
{ x: w, y: 0 },
{ x: 0, y: h },
{ x: w, y: h }
];
const pathData = createPathFromPoints(points);
const shapeNode = rc.path(pathData, options);
const polygon = shapeSvg.insert(() => shapeNode, ":first-child");
polygon.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", nodeStyles);
}
polygon.attr("transform", `translate(${-w / 2}, ${-h / 2})`);
updateNodeBounds(node, polygon);
node.intersect = function(point) {
log.info("Pill intersect", node, { points });
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(hourglass, "hourglass");
// src/rendering-util/rendering-elements/shapes/icon.ts
import rough21 from "roughjs";
async function icon(parent, node, { config: { themeVariables, flowchart } }) {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
const assetHeight = node.assetHeight ?? 48;
const assetWidth = node.assetWidth ?? 48;
const iconSize = Math.max(assetHeight, assetWidth);
const defaultWidth = flowchart?.wrappingWidth;
node.width = Math.max(iconSize, defaultWidth ?? 0);
const { shapeSvg, bbox, label } = await labelHelper(parent, node, "icon-shape default");
const topLabel = node.pos === "t";
const height = iconSize;
const width = iconSize;
const { nodeBorder } = themeVariables;
const { stylesMap } = compileStyles(node);
const x = -width / 2;
const y = -height / 2;
const labelPadding = node.label ? 8 : 0;
const rc = rough21.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: "none", fill: "none" });
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const iconNode = rc.rectangle(x, y, width, height, options);
const outerWidth = Math.max(width, bbox.width);
const outerHeight = height + bbox.height + labelPadding;
const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
...options,
fill: "transparent",
stroke: "none"
});
const iconShape = shapeSvg.insert(() => iconNode, ":first-child");
const outerShape = shapeSvg.insert(() => outerNode);
if (node.icon) {
const iconElem = shapeSvg.append("g");
iconElem.html(
`${await getIconSVG(node.icon, {
height: iconSize,
width: iconSize,
fallbackPrefix: ""
})} `
);
const iconBBox = iconElem.node().getBBox();
const iconWidth = iconBBox.width;
const iconHeight = iconBBox.height;
const iconX = iconBBox.x;
const iconY = iconBBox.y;
iconElem.attr(
"transform",
`translate(${-iconWidth / 2 - iconX},${topLabel ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY})`
);
iconElem.attr("style", `color: ${stylesMap.get("stroke") ?? nodeBorder};`);
}
label.attr(
"transform",
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height})`
);
iconShape.attr(
"transform",
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
updateNodeBounds(node, outerShape);
node.intersect = function(point) {
log.info("iconSquare intersect", node, point);
if (!node.label) {
return intersect_default.rect(node, point);
}
const dx = node.x ?? 0;
const dy = node.y ?? 0;
const nodeHeight = node.height ?? 0;
let points = [];
if (topLabel) {
points = [
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + width / 2, y: dy + nodeHeight / 2 },
{ x: dx - width / 2, y: dy + nodeHeight / 2 },
{ x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }
];
} else {
points = [
{ x: dx - width / 2, y: dy - nodeHeight / 2 },
{ x: dx + width / 2, y: dy - nodeHeight / 2 },
{ x: dx + width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx - width / 2, y: dy - nodeHeight / 2 + height }
];
}
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(icon, "icon");
// src/rendering-util/rendering-elements/shapes/iconCircle.ts
import rough22 from "roughjs";
async function iconCircle(parent, node, { config: { themeVariables, flowchart } }) {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
const assetHeight = node.assetHeight ?? 48;
const assetWidth = node.assetWidth ?? 48;
const iconSize = Math.max(assetHeight, assetWidth);
const defaultWidth = flowchart?.wrappingWidth;
node.width = Math.max(iconSize, defaultWidth ?? 0);
const { shapeSvg, bbox, label } = await labelHelper(parent, node, "icon-shape default");
const padding = 20;
const labelPadding = node.label ? 8 : 0;
const topLabel = node.pos === "t";
const { nodeBorder, mainBkg } = themeVariables;
const { stylesMap } = compileStyles(node);
const rc = rough22.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const fill = stylesMap.get("fill");
options.stroke = fill ?? mainBkg;
const iconElem = shapeSvg.append("g");
if (node.icon) {
iconElem.html(
`${await getIconSVG(node.icon, {
height: iconSize,
width: iconSize,
fallbackPrefix: ""
})} `
);
}
const iconBBox = iconElem.node().getBBox();
const iconWidth = iconBBox.width;
const iconHeight = iconBBox.height;
const iconX = iconBBox.x;
const iconY = iconBBox.y;
const diameter = Math.max(iconWidth, iconHeight) * Math.SQRT2 + padding * 2;
const iconNode = rc.circle(0, 0, diameter, options);
const outerWidth = Math.max(diameter, bbox.width);
const outerHeight = diameter + bbox.height + labelPadding;
const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
...options,
fill: "transparent",
stroke: "none"
});
const iconShape = shapeSvg.insert(() => iconNode, ":first-child");
const outerShape = shapeSvg.insert(() => outerNode);
iconElem.attr(
"transform",
`translate(${-iconWidth / 2 - iconX},${topLabel ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY})`
);
iconElem.attr("style", `color: ${stylesMap.get("stroke") ?? nodeBorder};`);
label.attr(
"transform",
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height})`
);
iconShape.attr(
"transform",
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
updateNodeBounds(node, outerShape);
node.intersect = function(point) {
log.info("iconSquare intersect", node, point);
const pos = intersect_default.rect(node, point);
return pos;
};
return shapeSvg;
}
__name(iconCircle, "iconCircle");
// src/rendering-util/rendering-elements/shapes/iconRounded.ts
import rough23 from "roughjs";
async function iconRounded(parent, node, { config: { themeVariables, flowchart } }) {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
const assetHeight = node.assetHeight ?? 48;
const assetWidth = node.assetWidth ?? 48;
const iconSize = Math.max(assetHeight, assetWidth);
const defaultWidth = flowchart?.wrappingWidth;
node.width = Math.max(iconSize, defaultWidth ?? 0);
const { shapeSvg, bbox, halfPadding, label } = await labelHelper(
parent,
node,
"icon-shape default"
);
const topLabel = node.pos === "t";
const height = iconSize + halfPadding * 2;
const width = iconSize + halfPadding * 2;
const { nodeBorder, mainBkg } = themeVariables;
const { stylesMap } = compileStyles(node);
const x = -width / 2;
const y = -height / 2;
const labelPadding = node.label ? 8 : 0;
const rc = rough23.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const fill = stylesMap.get("fill");
options.stroke = fill ?? mainBkg;
const iconNode = rc.path(createRoundedRectPathD(x, y, width, height, 5), options);
const outerWidth = Math.max(width, bbox.width);
const outerHeight = height + bbox.height + labelPadding;
const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
...options,
fill: "transparent",
stroke: "none"
});
const iconShape = shapeSvg.insert(() => iconNode, ":first-child").attr("class", "icon-shape2");
const outerShape = shapeSvg.insert(() => outerNode);
if (node.icon) {
const iconElem = shapeSvg.append("g");
iconElem.html(
`${await getIconSVG(node.icon, {
height: iconSize,
width: iconSize,
fallbackPrefix: ""
})} `
);
const iconBBox = iconElem.node().getBBox();
const iconWidth = iconBBox.width;
const iconHeight = iconBBox.height;
const iconX = iconBBox.x;
const iconY = iconBBox.y;
iconElem.attr(
"transform",
`translate(${-iconWidth / 2 - iconX},${topLabel ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY})`
);
iconElem.attr("style", `color: ${stylesMap.get("stroke") ?? nodeBorder};`);
}
label.attr(
"transform",
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height})`
);
iconShape.attr(
"transform",
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
updateNodeBounds(node, outerShape);
node.intersect = function(point) {
log.info("iconSquare intersect", node, point);
if (!node.label) {
return intersect_default.rect(node, point);
}
const dx = node.x ?? 0;
const dy = node.y ?? 0;
const nodeHeight = node.height ?? 0;
let points = [];
if (topLabel) {
points = [
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + width / 2, y: dy + nodeHeight / 2 },
{ x: dx - width / 2, y: dy + nodeHeight / 2 },
{ x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }
];
} else {
points = [
{ x: dx - width / 2, y: dy - nodeHeight / 2 },
{ x: dx + width / 2, y: dy - nodeHeight / 2 },
{ x: dx + width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx - width / 2, y: dy - nodeHeight / 2 + height }
];
}
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(iconRounded, "iconRounded");
// src/rendering-util/rendering-elements/shapes/iconSquare.ts
import rough24 from "roughjs";
async function iconSquare(parent, node, { config: { themeVariables, flowchart } }) {
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
const assetHeight = node.assetHeight ?? 48;
const assetWidth = node.assetWidth ?? 48;
const iconSize = Math.max(assetHeight, assetWidth);
const defaultWidth = flowchart?.wrappingWidth;
node.width = Math.max(iconSize, defaultWidth ?? 0);
const { shapeSvg, bbox, halfPadding, label } = await labelHelper(
parent,
node,
"icon-shape default"
);
const topLabel = node.pos === "t";
const height = iconSize + halfPadding * 2;
const width = iconSize + halfPadding * 2;
const { nodeBorder, mainBkg } = themeVariables;
const { stylesMap } = compileStyles(node);
const x = -width / 2;
const y = -height / 2;
const labelPadding = node.label ? 8 : 0;
const rc = rough24.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const fill = stylesMap.get("fill");
options.stroke = fill ?? mainBkg;
const iconNode = rc.path(createRoundedRectPathD(x, y, width, height, 0.1), options);
const outerWidth = Math.max(width, bbox.width);
const outerHeight = height + bbox.height + labelPadding;
const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
...options,
fill: "transparent",
stroke: "none"
});
const iconShape = shapeSvg.insert(() => iconNode, ":first-child");
const outerShape = shapeSvg.insert(() => outerNode);
if (node.icon) {
const iconElem = shapeSvg.append("g");
iconElem.html(
`${await getIconSVG(node.icon, {
height: iconSize,
width: iconSize,
fallbackPrefix: ""
})} `
);
const iconBBox = iconElem.node().getBBox();
const iconWidth = iconBBox.width;
const iconHeight = iconBBox.height;
const iconX = iconBBox.x;
const iconY = iconBBox.y;
iconElem.attr(
"transform",
`translate(${-iconWidth / 2 - iconX},${topLabel ? bbox.height / 2 + labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY})`
);
iconElem.attr("style", `color: ${stylesMap.get("stroke") ?? nodeBorder};`);
}
label.attr(
"transform",
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${topLabel ? -outerHeight / 2 : outerHeight / 2 - bbox.height})`
);
iconShape.attr(
"transform",
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
updateNodeBounds(node, outerShape);
node.intersect = function(point) {
log.info("iconSquare intersect", node, point);
if (!node.label) {
return intersect_default.rect(node, point);
}
const dx = node.x ?? 0;
const dy = node.y ?? 0;
const nodeHeight = node.height ?? 0;
let points = [];
if (topLabel) {
points = [
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + width / 2, y: dy + nodeHeight / 2 },
{ x: dx - width / 2, y: dy + nodeHeight / 2 },
{ x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }
];
} else {
points = [
{ x: dx - width / 2, y: dy - nodeHeight / 2 },
{ x: dx + width / 2, y: dy - nodeHeight / 2 },
{ x: dx + width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height },
{ x: dx - width / 2, y: dy - nodeHeight / 2 + height }
];
}
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(iconSquare, "iconSquare");
// src/rendering-util/rendering-elements/shapes/imageSquare.ts
import rough25 from "roughjs";
async function imageSquare(parent, node, { config: { flowchart } }) {
const img = new Image();
img.src = node?.img ?? "";
await img.decode();
const imageNaturalWidth = Number(img.naturalWidth.toString().replace("px", ""));
const imageNaturalHeight = Number(img.naturalHeight.toString().replace("px", ""));
node.imageAspectRatio = imageNaturalWidth / imageNaturalHeight;
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
const defaultWidth = flowchart?.wrappingWidth;
node.defaultWidth = flowchart?.wrappingWidth;
const imageRawWidth = Math.max(
node.label ? defaultWidth ?? 0 : 0,
node?.assetWidth ?? imageNaturalWidth
);
const imageWidth = node.constraint === "on" ? node?.assetHeight ? node.assetHeight * node.imageAspectRatio : imageRawWidth : imageRawWidth;
const imageHeight = node.constraint === "on" ? imageWidth / node.imageAspectRatio : node?.assetHeight ?? imageNaturalHeight;
node.width = Math.max(imageWidth, defaultWidth ?? 0);
const { shapeSvg, bbox, label } = await labelHelper(parent, node, "image-shape default");
const topLabel = node.pos === "t";
const x = -imageWidth / 2;
const y = -imageHeight / 2;
const labelPadding = node.label ? 8 : 0;
const rc = rough25.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const imageNode = rc.rectangle(x, y, imageWidth, imageHeight, options);
const outerWidth = Math.max(imageWidth, bbox.width);
const outerHeight = imageHeight + bbox.height + labelPadding;
const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
...options,
fill: "none",
stroke: "none"
});
const iconShape = shapeSvg.insert(() => imageNode, ":first-child");
const outerShape = shapeSvg.insert(() => outerNode);
if (node.img) {
const image = shapeSvg.append("image");
image.attr("href", node.img);
image.attr("width", imageWidth);
image.attr("height", imageHeight);
image.attr("preserveAspectRatio", "none");
image.attr(
"transform",
`translate(${-imageWidth / 2},${topLabel ? outerHeight / 2 - imageHeight : -outerHeight / 2})`
);
}
label.attr(
"transform",
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${topLabel ? -imageHeight / 2 - bbox.height / 2 - labelPadding / 2 : imageHeight / 2 - bbox.height / 2 + labelPadding / 2})`
);
iconShape.attr(
"transform",
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
updateNodeBounds(node, outerShape);
node.intersect = function(point) {
log.info("iconSquare intersect", node, point);
if (!node.label) {
return intersect_default.rect(node, point);
}
const dx = node.x ?? 0;
const dy = node.y ?? 0;
const nodeHeight = node.height ?? 0;
let points = [];
if (topLabel) {
points = [
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + imageWidth / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx + imageWidth / 2, y: dy + nodeHeight / 2 },
{ x: dx - imageWidth / 2, y: dy + nodeHeight / 2 },
{ x: dx - imageWidth / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding }
];
} else {
points = [
{ x: dx - imageWidth / 2, y: dy - nodeHeight / 2 },
{ x: dx + imageWidth / 2, y: dy - nodeHeight / 2 },
{ x: dx + imageWidth / 2, y: dy - nodeHeight / 2 + imageHeight },
{ x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + imageHeight },
{ x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
{ x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + imageHeight },
{ x: dx - imageWidth / 2, y: dy - nodeHeight / 2 + imageHeight }
];
}
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(imageSquare, "imageSquare");
// src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts
import rough26 from "roughjs";
async function inv_trapezoid(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const points = [
{ x: 0, y: 0 },
{ x: w, y: 0 },
{ x: w + 3 * h / 6, y: -h },
{ x: -3 * h / 6, y: -h }
];
let polygon;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough26.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-w / 2}, ${h / 2})`);
if (cssStyles) {
polygon.attr("style", cssStyles);
}
} else {
polygon = insertPolygonShape(shapeSvg, w, h, points);
}
if (nodeStyles) {
polygon.attr("style", nodeStyles);
}
node.width = w;
node.height = h;
updateNodeBounds(node, polygon);
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(inv_trapezoid, "inv_trapezoid");
// src/rendering-util/rendering-elements/shapes/drawRect.ts
import rough27 from "roughjs";
async function drawRect(parent, node, options) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const totalWidth = Math.max(bbox.width + options.labelPaddingX * 2, node?.width || 0);
const totalHeight = Math.max(bbox.height + options.labelPaddingY * 2, node?.height || 0);
const x = -totalWidth / 2;
const y = -totalHeight / 2;
let rect2;
let { rx, ry } = node;
const { cssStyles } = node;
if (options?.rx && options.ry) {
rx = options.rx;
ry = options.ry;
}
if (node.look === "handDrawn") {
const rc = rough27.svg(shapeSvg);
const options2 = userNodeOverrides(node, {});
const roughNode = rx || ry ? rc.path(createRoundedRectPathD(x, y, totalWidth, totalHeight, rx || 0), options2) : rc.rectangle(x, y, totalWidth, totalHeight, options2);
rect2 = shapeSvg.insert(() => roughNode, ":first-child");
rect2.attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles));
} else {
rect2 = shapeSvg.insert("rect", ":first-child");
rect2.attr("class", "basic label-container").attr("style", nodeStyles).attr("rx", handleUndefinedAttr(rx)).attr("ry", handleUndefinedAttr(ry)).attr("x", x).attr("y", y).attr("width", totalWidth).attr("height", totalHeight);
}
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(drawRect, "drawRect");
// src/rendering-util/rendering-elements/shapes/labelRect.ts
async function labelRect(parent, node) {
const { shapeSvg, bbox, label } = await labelHelper(parent, node, "label");
const rect2 = shapeSvg.insert("rect", ":first-child");
const totalWidth = 0.1;
const totalHeight = 0.1;
rect2.attr("width", totalWidth).attr("height", totalHeight);
shapeSvg.attr("class", "label edgeLabel");
label.attr(
"transform",
`translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(labelRect, "labelRect");
// src/rendering-util/rendering-elements/shapes/leanLeft.ts
import rough28 from "roughjs";
async function lean_left(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0);
const points = [
{ x: 0, y: 0 },
{ x: w + 3 * h / 6, y: 0 },
{ x: w, y: -h },
{ x: -(3 * h) / 6, y: -h }
];
let polygon;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough28.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-w / 2}, ${h / 2})`);
if (cssStyles) {
polygon.attr("style", cssStyles);
}
} else {
polygon = insertPolygonShape(shapeSvg, w, h, points);
}
if (nodeStyles) {
polygon.attr("style", nodeStyles);
}
node.width = w;
node.height = h;
updateNodeBounds(node, polygon);
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(lean_left, "lean_left");
// src/rendering-util/rendering-elements/shapes/leanRight.ts
import rough29 from "roughjs";
async function lean_right(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0);
const points = [
{ x: -3 * h / 6, y: 0 },
{ x: w, y: 0 },
{ x: w + 3 * h / 6, y: -h },
{ x: 0, y: -h }
];
let polygon;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough29.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-w / 2}, ${h / 2})`);
if (cssStyles) {
polygon.attr("style", cssStyles);
}
} else {
polygon = insertPolygonShape(shapeSvg, w, h, points);
}
if (nodeStyles) {
polygon.attr("style", nodeStyles);
}
node.width = w;
node.height = h;
updateNodeBounds(node, polygon);
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(lean_right, "lean_right");
// src/rendering-util/rendering-elements/shapes/lightningBolt.ts
import rough30 from "roughjs";
function lightningBolt(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.label = "";
node.labelStyle = labelStyles;
const shapeSvg = parent.insert("g").attr("class", getNodeClasses(node)).attr("id", node.domId ?? node.id);
const { cssStyles } = node;
const width = Math.max(35, node?.width ?? 0);
const height = Math.max(35, node?.height ?? 0);
const gap = 7;
const points = [
{ x: width, y: 0 },
{ x: 0, y: height + gap / 2 },
{ x: width - 2 * gap, y: height + gap / 2 },
{ x: 0, y: 2 * height },
{ x: width, y: height - gap / 2 },
{ x: 2 * gap, y: height - gap / 2 }
];
const rc = rough30.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const linePath = createPathFromPoints(points);
const lineNode = rc.path(linePath, options);
const lightningBolt2 = shapeSvg.insert(() => lineNode, ":first-child");
if (cssStyles && node.look !== "handDrawn") {
lightningBolt2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
lightningBolt2.selectAll("path").attr("style", nodeStyles);
}
lightningBolt2.attr("transform", `translate(-${width / 2},${-height})`);
updateNodeBounds(node, lightningBolt2);
node.intersect = function(point) {
log.info("lightningBolt intersect", node, point);
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(lightningBolt, "lightningBolt");
// src/rendering-util/rendering-elements/shapes/linedCylinder.ts
import rough31 from "roughjs";
var createCylinderPathD2 = /* @__PURE__ */ __name((x, y, width, height, rx, ry, outerOffset) => {
return [
`M${x},${y + ry}`,
`a${rx},${ry} 0,0,0 ${width},0`,
`a${rx},${ry} 0,0,0 ${-width},0`,
`l0,${height}`,
`a${rx},${ry} 0,0,0 ${width},0`,
`l0,${-height}`,
`M${x},${y + ry + outerOffset}`,
`a${rx},${ry} 0,0,0 ${width},0`
].join(" ");
}, "createCylinderPathD");
var createOuterCylinderPathD2 = /* @__PURE__ */ __name((x, y, width, height, rx, ry, outerOffset) => {
return [
`M${x},${y + ry}`,
`M${x + width},${y + ry}`,
`a${rx},${ry} 0,0,0 ${-width},0`,
`l0,${height}`,
`a${rx},${ry} 0,0,0 ${width},0`,
`l0,${-height}`,
`M${x},${y + ry + outerOffset}`,
`a${rx},${ry} 0,0,0 ${width},0`
].join(" ");
}, "createOuterCylinderPathD");
var createInnerCylinderPathD2 = /* @__PURE__ */ __name((x, y, width, height, rx, ry) => {
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(" ");
}, "createInnerCylinderPathD");
async function linedCylinder(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0), node.width ?? 0);
const rx = w / 2;
const ry = rx / (2.5 + w / 50);
const h = Math.max(bbox.height + ry + (node.padding ?? 0), node.height ?? 0);
const outerOffset = h * 0.1;
let cylinder2;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough31.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD2(0, 0, w, h, rx, ry, outerOffset);
const innerPathData = createInnerCylinderPathD2(0, ry, w, h, rx, ry);
const options = userNodeOverrides(node, {});
const outerNode = rc.path(outerPathData, options);
const innerLine = rc.path(innerPathData, options);
const innerLineEl = shapeSvg.insert(() => innerLine, ":first-child");
innerLineEl.attr("class", "line");
cylinder2 = shapeSvg.insert(() => outerNode, ":first-child");
cylinder2.attr("class", "basic label-container");
if (cssStyles) {
cylinder2.attr("style", cssStyles);
}
} else {
const pathData = createCylinderPathD2(0, 0, w, h, rx, ry, outerOffset);
cylinder2 = shapeSvg.insert("path", ":first-child").attr("d", pathData).attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles)).attr("style", nodeStyles);
}
cylinder2.attr("label-offset-y", ry);
cylinder2.attr("transform", `translate(${-w / 2}, ${-(h / 2 + ry)})`);
updateNodeBounds(node, cylinder2);
label.attr(
"transform",
`translate(${-(bbox.width / 2) - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + ry - (bbox.y - (bbox.top ?? 0))})`
);
node.intersect = function(point) {
const pos = intersect_default.rect(node, point);
const x = pos.x - (node.x ?? 0);
if (rx != 0 && (Math.abs(x) < (node.width ?? 0) / 2 || Math.abs(x) == (node.width ?? 0) / 2 && Math.abs(pos.y - (node.y ?? 0)) > (node.height ?? 0) / 2 - ry)) {
let y = ry * ry * (1 - x * x / (rx * rx));
if (y > 0) {
y = Math.sqrt(y);
}
y = ry - y;
if (point.y - (node.y ?? 0) > 0) {
y = -y;
}
pos.y += y;
}
return pos;
};
return shapeSvg;
}
__name(linedCylinder, "linedCylinder");
// src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts
import rough32 from "roughjs";
async function linedWaveEdgedRect(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const waveAmplitude = h / 4;
const finalH = h + waveAmplitude;
const { cssStyles } = node;
const rc = rough32.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x: -w / 2 - w / 2 * 0.1, y: -finalH / 2 },
{ x: -w / 2 - w / 2 * 0.1, y: finalH / 2 },
...generateFullSineWavePoints(
-w / 2 - w / 2 * 0.1,
finalH / 2,
w / 2 + w / 2 * 0.1,
finalH / 2,
waveAmplitude,
0.8
),
{ x: w / 2 + w / 2 * 0.1, y: -finalH / 2 },
{ x: -w / 2 - w / 2 * 0.1, y: -finalH / 2 },
{ x: -w / 2, y: -finalH / 2 },
{ x: -w / 2, y: finalH / 2 * 1.1 },
{ x: -w / 2, y: -finalH / 2 }
];
const poly = rc.polygon(
points.map((p) => [p.x, p.y]),
options
);
const waveEdgeRect = shapeSvg.insert(() => poly, ":first-child");
waveEdgeRect.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
waveEdgeRect.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
waveEdgeRect.selectAll("path").attr("style", nodeStyles);
}
waveEdgeRect.attr("transform", `translate(0,${-waveAmplitude / 2})`);
label.attr(
"transform",
`translate(${-w / 2 + (node.padding ?? 0) + w / 2 * 0.1 / 2 - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - waveAmplitude / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, waveEdgeRect);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(linedWaveEdgedRect, "linedWaveEdgedRect");
// src/rendering-util/rendering-elements/shapes/multiRect.ts
import rough33 from "roughjs";
async function multiRect(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const rectOffset = 5;
const x = -w / 2;
const y = -h / 2;
const { cssStyles } = node;
const rc = rough33.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const outerPathPoints = [
{ x: x - rectOffset, y: y + rectOffset },
{ x: x - rectOffset, y: y + h + rectOffset },
{ x: x + w - rectOffset, y: y + h + rectOffset },
{ x: x + w - rectOffset, y: y + h },
{ x: x + w, y: y + h },
{ x: x + w, y: y + h - rectOffset },
{ x: x + w + rectOffset, y: y + h - rectOffset },
{ x: x + w + rectOffset, y: y - rectOffset },
{ x: x + rectOffset, y: y - rectOffset },
{ x: x + rectOffset, y },
{ x, y },
{ x, y: y + rectOffset }
];
const innerPathPoints = [
{ x, y: y + rectOffset },
{ x: x + w - rectOffset, y: y + rectOffset },
{ x: x + w - rectOffset, y: y + h },
{ x: x + w, y: y + h },
{ x: x + w, y },
{ x, y }
];
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const outerPath = createPathFromPoints(outerPathPoints);
const outerNode = rc.path(outerPath, options);
const innerPath = createPathFromPoints(innerPathPoints);
const innerNode = rc.path(innerPath, { ...options, fill: "none" });
const multiRect2 = shapeSvg.insert(() => innerNode, ":first-child");
multiRect2.insert(() => outerNode, ":first-child");
multiRect2.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
multiRect2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
multiRect2.selectAll("path").attr("style", nodeStyles);
}
label.attr(
"transform",
`translate(${-(bbox.width / 2) - rectOffset - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + rectOffset - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, multiRect2);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, outerPathPoints, point);
return pos;
};
return shapeSvg;
}
__name(multiRect, "multiRect");
// src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts
import rough34 from "roughjs";
async function multiWaveEdgedRectangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const waveAmplitude = h / 4;
const finalH = h + waveAmplitude;
const x = -w / 2;
const y = -finalH / 2;
const rectOffset = 5;
const { cssStyles } = node;
const wavePoints = generateFullSineWavePoints(
x - rectOffset,
y + finalH + rectOffset,
x + w - rectOffset,
y + finalH + rectOffset,
waveAmplitude,
0.8
);
const lastWavePoint = wavePoints?.[wavePoints.length - 1];
const outerPathPoints = [
{ x: x - rectOffset, y: y + rectOffset },
{ x: x - rectOffset, y: y + finalH + rectOffset },
...wavePoints,
{ x: x + w - rectOffset, y: lastWavePoint.y - rectOffset },
{ x: x + w, y: lastWavePoint.y - rectOffset },
{ x: x + w, y: lastWavePoint.y - 2 * rectOffset },
{ x: x + w + rectOffset, y: lastWavePoint.y - 2 * rectOffset },
{ x: x + w + rectOffset, y: y - rectOffset },
{ x: x + rectOffset, y: y - rectOffset },
{ x: x + rectOffset, y },
{ x, y },
{ x, y: y + rectOffset }
];
const innerPathPoints = [
{ x, y: y + rectOffset },
{ x: x + w - rectOffset, y: y + rectOffset },
{ x: x + w - rectOffset, y: lastWavePoint.y - rectOffset },
{ x: x + w, y: lastWavePoint.y - rectOffset },
{ x: x + w, y },
{ x, y }
];
const rc = rough34.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const outerPath = createPathFromPoints(outerPathPoints);
const outerNode = rc.path(outerPath, options);
const innerPath = createPathFromPoints(innerPathPoints);
const innerNode = rc.path(innerPath, options);
const shape = shapeSvg.insert(() => outerNode, ":first-child");
shape.insert(() => innerNode);
shape.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
shape.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
shape.selectAll("path").attr("style", nodeStyles);
}
shape.attr("transform", `translate(0,${-waveAmplitude / 2})`);
label.attr(
"transform",
`translate(${-(bbox.width / 2) - rectOffset - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + rectOffset - waveAmplitude / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, shape);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, outerPathPoints, point);
return pos;
};
return shapeSvg;
}
__name(multiWaveEdgedRectangle, "multiWaveEdgedRectangle");
// src/rendering-util/rendering-elements/shapes/note.ts
import rough35 from "roughjs";
async function note(parent, node, { config: { themeVariables } }) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const useHtmlLabels = node.useHtmlLabels || getConfig().flowchart?.htmlLabels !== false;
if (!useHtmlLabels) {
node.centerLabel = true;
}
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const totalWidth = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const totalHeight = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const x = -totalWidth / 2;
const y = -totalHeight / 2;
const { cssStyles } = node;
const rc = rough35.svg(shapeSvg);
const options = userNodeOverrides(node, {
fill: themeVariables.noteBkgColor,
stroke: themeVariables.noteBorderColor
});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const noteShapeNode = rc.rectangle(x, y, totalWidth, totalHeight, options);
const rect2 = shapeSvg.insert(() => noteShapeNode, ":first-child");
rect2.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
rect2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
rect2.selectAll("path").attr("style", nodeStyles);
}
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(note, "note");
// src/rendering-util/rendering-elements/shapes/question.ts
import rough36 from "roughjs";
var createDecisionBoxPathD = /* @__PURE__ */ __name((x, y, size) => {
return [
`M${x + size / 2},${y}`,
`L${x + size},${y - size / 2}`,
`L${x + size / 2},${y - size}`,
`L${x},${y - size / 2}`,
"Z"
].join(" ");
}, "createDecisionBoxPathD");
async function question(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + node.padding;
const h = bbox.height + node.padding;
const s = w + h;
const points = [
{ x: s / 2, y: 0 },
{ x: s, y: -s / 2 },
{ x: s / 2, y: -s },
{ x: 0, y: -s / 2 }
];
let polygon;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough36.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createDecisionBoxPathD(0, 0, s);
const roughNode = rc.path(pathData, options);
polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-s / 2}, ${s / 2})`);
if (cssStyles) {
polygon.attr("style", cssStyles);
}
} else {
polygon = insertPolygonShape(shapeSvg, s, s, points);
}
if (nodeStyles) {
polygon.attr("style", nodeStyles);
}
updateNodeBounds(node, polygon);
node.intersect = function(point) {
log.debug(
"APA12 Intersect called SPLIT\npoint:",
point,
"\nnode:\n",
node,
"\nres:",
intersect_default.polygon(node, points, point)
);
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(question, "question");
// src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts
import rough37 from "roughjs";
async function rect_left_inv_arrow(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0);
const x = -w / 2;
const y = -h / 2;
const notch = y / 2;
const points = [
{ x: x + notch, y },
{ x, y: 0 },
{ x: x + notch, y: -y },
{ x: -x, y: -y },
{ x: -x, y }
];
const { cssStyles } = node;
const rc = rough37.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
const polygon = shapeSvg.insert(() => roughNode, ":first-child");
polygon.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
polygon.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectAll("path").attr("style", nodeStyles);
}
polygon.attr("transform", `translate(${-notch / 2},0)`);
label.attr(
"transform",
`translate(${-notch / 2 - bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, polygon);
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(rect_left_inv_arrow, "rect_left_inv_arrow");
// src/rendering-util/rendering-elements/shapes/rectWithTitle.ts
import { select as select4 } from "d3";
import rough38 from "roughjs";
async function rectWithTitle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
let classes;
if (!node.cssClasses) {
classes = "node default";
} else {
classes = "node " + node.cssClasses;
}
const shapeSvg = parent.insert("g").attr("class", classes).attr("id", node.domId || node.id);
const g = shapeSvg.insert("g");
const label = shapeSvg.insert("g").attr("class", "label").attr("style", nodeStyles);
const description = node.description;
const title = node.label;
const text2 = label.node().appendChild(await createLabel_default(title, node.labelStyle, true, true));
let bbox = { width: 0, height: 0 };
if (evaluate(getConfig2()?.flowchart?.htmlLabels)) {
const div2 = text2.children[0];
const dv2 = select4(text2);
bbox = div2.getBoundingClientRect();
dv2.attr("width", bbox.width);
dv2.attr("height", bbox.height);
}
log.info("Text 2", description);
const textRows = description || [];
const titleBox = text2.getBBox();
const descr = label.node().appendChild(
await createLabel_default(
textRows.join ? textRows.join("
") : textRows,
node.labelStyle,
true,
true
)
);
const div = descr.children[0];
const dv = select4(descr);
bbox = div.getBoundingClientRect();
dv.attr("width", bbox.width);
dv.attr("height", bbox.height);
const halfPadding = (node.padding || 0) / 2;
select4(descr).attr(
"transform",
"translate( " + (bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) + ", " + (titleBox.height + halfPadding + 5) + ")"
);
select4(text2).attr(
"transform",
"translate( " + (bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) + ", 0)"
);
bbox = label.node().getBBox();
label.attr(
"transform",
"translate(" + -bbox.width / 2 + ", " + (-bbox.height / 2 - halfPadding + 3) + ")"
);
const totalWidth = bbox.width + (node.padding || 0);
const totalHeight = bbox.height + (node.padding || 0);
const x = -bbox.width / 2 - halfPadding;
const y = -bbox.height / 2 - halfPadding;
let rect2;
let innerLine;
if (node.look === "handDrawn") {
const rc = rough38.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const roughNode = rc.path(
createRoundedRectPathD(x, y, totalWidth, totalHeight, node.rx || 0),
options
);
const roughLine = rc.line(
-bbox.width / 2 - halfPadding,
-bbox.height / 2 - halfPadding + titleBox.height + halfPadding,
bbox.width / 2 + halfPadding,
-bbox.height / 2 - halfPadding + titleBox.height + halfPadding,
options
);
innerLine = shapeSvg.insert(() => {
log.debug("Rough node insert CXC", roughNode);
return roughLine;
}, ":first-child");
rect2 = shapeSvg.insert(() => {
log.debug("Rough node insert CXC", roughNode);
return roughNode;
}, ":first-child");
} else {
rect2 = g.insert("rect", ":first-child");
innerLine = g.insert("line");
rect2.attr("class", "outer title-state").attr("style", nodeStyles).attr("x", -bbox.width / 2 - halfPadding).attr("y", -bbox.height / 2 - halfPadding).attr("width", bbox.width + (node.padding || 0)).attr("height", bbox.height + (node.padding || 0));
innerLine.attr("class", "divider").attr("x1", -bbox.width / 2 - halfPadding).attr("x2", bbox.width / 2 + halfPadding).attr("y1", -bbox.height / 2 - halfPadding + titleBox.height + halfPadding).attr("y2", -bbox.height / 2 - halfPadding + titleBox.height + halfPadding);
}
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(rectWithTitle, "rectWithTitle");
// src/rendering-util/rendering-elements/shapes/roundedRect.ts
async function roundedRect(parent, node) {
const options = {
rx: 5,
ry: 5,
classes: "",
labelPaddingX: (node?.padding || 0) * 1,
labelPaddingY: (node?.padding || 0) * 1
};
return drawRect(parent, node, options);
}
__name(roundedRect, "roundedRect");
// src/rendering-util/rendering-elements/shapes/shadedProcess.ts
import rough39 from "roughjs";
async function shadedProcess(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const halfPadding = node?.padding ?? 0;
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const x = -bbox.width / 2 - halfPadding;
const y = -bbox.height / 2 - halfPadding;
const { cssStyles } = node;
const rc = rough39.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x, y },
{ x: x + w + 8, y },
{ x: x + w + 8, y: y + h },
{ x: x - 8, y: y + h },
{ x: x - 8, y },
{ x, y },
{ x, y: y + h }
];
const roughNode = rc.polygon(
points.map((p) => [p.x, p.y]),
options
);
const rect2 = shapeSvg.insert(() => roughNode, ":first-child");
rect2.attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles));
if (nodeStyles && node.look !== "handDrawn") {
rect2.selectAll("path").attr("style", nodeStyles);
}
if (cssStyles && node.look !== "handDrawn") {
rect2.selectAll("path").attr("style", nodeStyles);
}
label.attr(
"transform",
`translate(${-w / 2 + 4 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(shadedProcess, "shadedProcess");
// src/rendering-util/rendering-elements/shapes/slopedRect.ts
import rough40 from "roughjs";
async function slopedRect(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const x = -w / 2;
const y = -h / 2;
const { cssStyles } = node;
const rc = rough40.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x, y },
{ x, y: y + h },
{ x: x + w, y: y + h },
{ x: x + w, y: y - h / 2 }
];
const pathData = createPathFromPoints(points);
const shapeNode = rc.path(pathData, options);
const polygon = shapeSvg.insert(() => shapeNode, ":first-child");
polygon.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", nodeStyles);
}
polygon.attr("transform", `translate(0, ${h / 4})`);
label.attr(
"transform",
`translate(${-w / 2 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))}, ${-h / 4 + (node.padding ?? 0) - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, polygon);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(slopedRect, "slopedRect");
// src/rendering-util/rendering-elements/shapes/squareRect.ts
async function squareRect2(parent, node) {
const options = {
rx: 0,
ry: 0,
classes: "",
labelPaddingX: (node?.padding || 0) * 2,
labelPaddingY: (node?.padding || 0) * 1
};
return drawRect(parent, node, options);
}
__name(squareRect2, "squareRect");
// src/rendering-util/rendering-elements/shapes/stadium.ts
import rough41 from "roughjs";
async function stadium(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const h = bbox.height + node.padding;
const w = bbox.width + h / 4 + node.padding;
let rect2;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough41.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createRoundedRectPathD(-w / 2, -h / 2, w, h, h / 2);
const roughNode = rc.path(pathData, options);
rect2 = shapeSvg.insert(() => roughNode, ":first-child");
rect2.attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles));
} else {
rect2 = shapeSvg.insert("rect", ":first-child");
rect2.attr("class", "basic label-container").attr("style", nodeStyles).attr("rx", h / 2).attr("ry", h / 2).attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h);
}
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(stadium, "stadium");
// src/rendering-util/rendering-elements/shapes/state.ts
async function state(parent, node) {
const options = {
rx: 5,
ry: 5,
classes: "flowchart-node"
};
return drawRect(parent, node, options);
}
__name(state, "state");
// src/rendering-util/rendering-elements/shapes/stateEnd.ts
import rough42 from "roughjs";
function stateEnd(parent, node, { config: { themeVariables } }) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { cssStyles } = node;
const { lineColor, stateBorder, nodeBorder } = themeVariables;
const shapeSvg = parent.insert("g").attr("class", "node default").attr("id", node.domId || node.id);
const rc = rough42.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const roughNode = rc.circle(0, 0, 14, {
...options,
stroke: lineColor,
strokeWidth: 2
});
const innerFill = stateBorder ?? nodeBorder;
const roughInnerNode = rc.circle(0, 0, 5, {
...options,
fill: innerFill,
stroke: innerFill,
strokeWidth: 2,
fillStyle: "solid"
});
const circle2 = shapeSvg.insert(() => roughNode, ":first-child");
circle2.insert(() => roughInnerNode);
if (cssStyles) {
circle2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles) {
circle2.selectAll("path").attr("style", nodeStyles);
}
updateNodeBounds(node, circle2);
node.intersect = function(point) {
return intersect_default.circle(node, 7, point);
};
return shapeSvg;
}
__name(stateEnd, "stateEnd");
// src/rendering-util/rendering-elements/shapes/stateStart.ts
import rough43 from "roughjs";
function stateStart(parent, node, { config: { themeVariables } }) {
const { lineColor } = themeVariables;
const shapeSvg = parent.insert("g").attr("class", "node default").attr("id", node.domId || node.id);
let circle2;
if (node.look === "handDrawn") {
const rc = rough43.svg(shapeSvg);
const roughNode = rc.circle(0, 0, 14, solidStateFill(lineColor));
circle2 = shapeSvg.insert(() => roughNode);
circle2.attr("class", "state-start").attr("r", 7).attr("width", 14).attr("height", 14);
} else {
circle2 = shapeSvg.insert("circle", ":first-child");
circle2.attr("class", "state-start").attr("r", 7).attr("width", 14).attr("height", 14);
}
updateNodeBounds(node, circle2);
node.intersect = function(point) {
return intersect_default.circle(node, 7, point);
};
return shapeSvg;
}
__name(stateStart, "stateStart");
// src/rendering-util/rendering-elements/shapes/subroutine.ts
import rough44 from "roughjs";
async function subroutine(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const halfPadding = (node?.padding || 0) / 2;
const w = bbox.width + node.padding;
const h = bbox.height + node.padding;
const x = -bbox.width / 2 - halfPadding;
const y = -bbox.height / 2 - halfPadding;
const points = [
{ x: 0, y: 0 },
{ x: w, y: 0 },
{ x: w, y: -h },
{ x: 0, y: -h },
{ x: 0, y: 0 },
{ x: -8, y: 0 },
{ x: w + 8, y: 0 },
{ x: w + 8, y: -h },
{ x: -8, y: -h },
{ x: -8, y: 0 }
];
if (node.look === "handDrawn") {
const rc = rough44.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const roughNode = rc.rectangle(x - 8, y, w + 16, h, options);
const l1 = rc.line(x, y, x, y + h, options);
const l2 = rc.line(x + w, y, x + w, y + h, options);
shapeSvg.insert(() => l1, ":first-child");
shapeSvg.insert(() => l2, ":first-child");
const rect2 = shapeSvg.insert(() => roughNode, ":first-child");
const { cssStyles } = node;
rect2.attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles));
updateNodeBounds(node, rect2);
} else {
const el = insertPolygonShape(shapeSvg, w, h, points);
if (nodeStyles) {
el.attr("style", nodeStyles);
}
updateNodeBounds(node, el);
}
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(subroutine, "subroutine");
// src/rendering-util/rendering-elements/shapes/taggedRect.ts
import rough45 from "roughjs";
async function taggedRect(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const x = -w / 2;
const y = -h / 2;
const tagWidth = 0.2 * h;
const tagHeight = 0.2 * h;
const { cssStyles } = node;
const rc = rough45.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const rectPoints = [
{ x: x - tagWidth / 2, y },
{ x: x + w + tagWidth / 2, y },
{ x: x + w + tagWidth / 2, y: y + h },
{ x: x - tagWidth / 2, y: y + h }
];
const tagPoints = [
{ x: x + w - tagWidth / 2, y: y + h },
{ x: x + w + tagWidth / 2, y: y + h },
{ x: x + w + tagWidth / 2, y: y + h - tagHeight }
];
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const rectPath = createPathFromPoints(rectPoints);
const rectNode = rc.path(rectPath, options);
const tagPath = createPathFromPoints(tagPoints);
const tagNode = rc.path(tagPath, { ...options, fillStyle: "solid" });
const taggedRect2 = shapeSvg.insert(() => tagNode, ":first-child");
taggedRect2.insert(() => rectNode, ":first-child");
taggedRect2.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
taggedRect2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
taggedRect2.selectAll("path").attr("style", nodeStyles);
}
updateNodeBounds(node, taggedRect2);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, rectPoints, point);
return pos;
};
return shapeSvg;
}
__name(taggedRect, "taggedRect");
// src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts
import rough46 from "roughjs";
async function taggedWaveEdgedRectangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const waveAmplitude = h / 4;
const tagWidth = 0.2 * w;
const tagHeight = 0.2 * h;
const finalH = h + waveAmplitude;
const { cssStyles } = node;
const rc = rough46.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x: -w / 2 - w / 2 * 0.1, y: finalH / 2 },
...generateFullSineWavePoints(
-w / 2 - w / 2 * 0.1,
finalH / 2,
w / 2 + w / 2 * 0.1,
finalH / 2,
waveAmplitude,
0.8
),
{ x: w / 2 + w / 2 * 0.1, y: -finalH / 2 },
{ x: -w / 2 - w / 2 * 0.1, y: -finalH / 2 }
];
const x = -w / 2 + w / 2 * 0.1;
const y = -finalH / 2 - tagHeight * 0.4;
const tagPoints = [
{ x: x + w - tagWidth, y: (y + h) * 1.4 },
{ x: x + w, y: y + h - tagHeight },
{ x: x + w, y: (y + h) * 0.9 },
...generateFullSineWavePoints(
x + w,
(y + h) * 1.3,
x + w - tagWidth,
(y + h) * 1.5,
-h * 0.03,
0.5
)
];
const waveEdgeRectPath = createPathFromPoints(points);
const waveEdgeRectNode = rc.path(waveEdgeRectPath, options);
const taggedWaveEdgeRectPath = createPathFromPoints(tagPoints);
const taggedWaveEdgeRectNode = rc.path(taggedWaveEdgeRectPath, {
...options,
fillStyle: "solid"
});
const waveEdgeRect = shapeSvg.insert(() => taggedWaveEdgeRectNode, ":first-child");
waveEdgeRect.insert(() => waveEdgeRectNode, ":first-child");
waveEdgeRect.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
waveEdgeRect.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
waveEdgeRect.selectAll("path").attr("style", nodeStyles);
}
waveEdgeRect.attr("transform", `translate(0,${-waveAmplitude / 2})`);
label.attr(
"transform",
`translate(${-w / 2 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - waveAmplitude / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, waveEdgeRect);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(taggedWaveEdgedRectangle, "taggedWaveEdgedRectangle");
// src/rendering-util/rendering-elements/shapes/text.ts
async function text(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const totalWidth = Math.max(bbox.width + node.padding, node?.width || 0);
const totalHeight = Math.max(bbox.height + node.padding, node?.height || 0);
const x = -totalWidth / 2;
const y = -totalHeight / 2;
const rect2 = shapeSvg.insert("rect", ":first-child");
rect2.attr("class", "text").attr("style", nodeStyles).attr("rx", 0).attr("ry", 0).attr("x", x).attr("y", y).attr("width", totalWidth).attr("height", totalHeight);
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(text, "text");
// src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts
import rough47 from "roughjs";
var createCylinderPathD3 = /* @__PURE__ */ __name((x, y, width, height, rx, ry) => {
return `M${x},${y}
a${rx},${ry} 0,0,1 ${0},${-height}
l${width},${0}
a${rx},${ry} 0,0,1 ${0},${height}
M${width},${-height}
a${rx},${ry} 0,0,0 ${0},${height}
l${-width},${0}`;
}, "createCylinderPathD");
var createOuterCylinderPathD3 = /* @__PURE__ */ __name((x, y, width, height, rx, ry) => {
return [
`M${x},${y}`,
`M${x + width},${y}`,
`a${rx},${ry} 0,0,0 ${0},${-height}`,
`l${-width},0`,
`a${rx},${ry} 0,0,0 ${0},${height}`,
`l${width},0`
].join(" ");
}, "createOuterCylinderPathD");
var createInnerCylinderPathD3 = /* @__PURE__ */ __name((x, y, width, height, rx, ry) => {
return [`M${x + width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 0,${height}`].join(" ");
}, "createInnerCylinderPathD");
async function tiltedCylinder(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label, halfPadding } = await labelHelper(
parent,
node,
getNodeClasses(node)
);
const labelPadding = node.look === "neo" ? halfPadding * 2 : halfPadding;
const h = bbox.height + labelPadding;
const ry = h / 2;
const rx = ry / (2.5 + h / 50);
const w = bbox.width + rx + labelPadding;
const { cssStyles } = node;
let cylinder2;
if (node.look === "handDrawn") {
const rc = rough47.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD3(0, 0, w, h, rx, ry);
const innerPathData = createInnerCylinderPathD3(0, 0, w, h, rx, ry);
const outerNode = rc.path(outerPathData, userNodeOverrides(node, {}));
const innerLine = rc.path(innerPathData, userNodeOverrides(node, { fill: "none" }));
cylinder2 = shapeSvg.insert(() => innerLine, ":first-child");
cylinder2 = shapeSvg.insert(() => outerNode, ":first-child");
cylinder2.attr("class", "basic label-container");
if (cssStyles) {
cylinder2.attr("style", cssStyles);
}
} else {
const pathData = createCylinderPathD3(0, 0, w, h, rx, ry);
cylinder2 = shapeSvg.insert("path", ":first-child").attr("d", pathData).attr("class", "basic label-container").attr("style", handleUndefinedAttr(cssStyles)).attr("style", nodeStyles);
cylinder2.attr("class", "basic label-container");
if (cssStyles) {
cylinder2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles) {
cylinder2.selectAll("path").attr("style", nodeStyles);
}
}
cylinder2.attr("label-offset-x", rx);
cylinder2.attr("transform", `translate(${-w / 2}, ${h / 2} )`);
label.attr(
"transform",
`translate(${-(bbox.width / 2) - rx - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, cylinder2);
node.intersect = function(point) {
const pos = intersect_default.rect(node, point);
const y = pos.y - (node.y ?? 0);
if (ry != 0 && (Math.abs(y) < (node.height ?? 0) / 2 || Math.abs(y) == (node.height ?? 0) / 2 && Math.abs(pos.x - (node.x ?? 0)) > (node.width ?? 0) / 2 - rx)) {
let x = rx * rx * (1 - y * y / (ry * ry));
if (x != 0) {
x = Math.sqrt(x);
}
x = rx - x;
if (point.x - (node.x ?? 0) > 0) {
x = -x;
}
pos.x += x;
}
return pos;
};
return shapeSvg;
}
__name(tiltedCylinder, "tiltedCylinder");
// src/rendering-util/rendering-elements/shapes/trapezoid.ts
import rough48 from "roughjs";
async function trapezoid(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const w = bbox.width + node.padding;
const h = bbox.height + node.padding;
const points = [
{ x: -3 * h / 6, y: 0 },
{ x: w + 3 * h / 6, y: 0 },
{ x: w, y: -h },
{ x: 0, y: -h }
];
let polygon;
const { cssStyles } = node;
if (node.look === "handDrawn") {
const rc = rough48.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-w / 2}, ${h / 2})`);
if (cssStyles) {
polygon.attr("style", cssStyles);
}
} else {
polygon = insertPolygonShape(shapeSvg, w, h, points);
}
if (nodeStyles) {
polygon.attr("style", nodeStyles);
}
node.width = w;
node.height = h;
updateNodeBounds(node, polygon);
node.intersect = function(point) {
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(trapezoid, "trapezoid");
// src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts
import rough49 from "roughjs";
async function trapezoidalPentagon(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const minWidth = 60, minHeight = 20;
const w = Math.max(minWidth, bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const { cssStyles } = node;
const rc = rough49.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x: -w / 2 * 0.8, y: -h / 2 },
{ x: w / 2 * 0.8, y: -h / 2 },
{ x: w / 2, y: -h / 2 * 0.6 },
{ x: w / 2, y: h / 2 },
{ x: -w / 2, y: h / 2 },
{ x: -w / 2, y: -h / 2 * 0.6 }
];
const pathData = createPathFromPoints(points);
const shapeNode = rc.path(pathData, options);
const polygon = shapeSvg.insert(() => shapeNode, ":first-child");
polygon.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", nodeStyles);
}
updateNodeBounds(node, polygon);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(trapezoidalPentagon, "trapezoidalPentagon");
// src/rendering-util/rendering-elements/shapes/triangle.ts
import rough50 from "roughjs";
async function triangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const useHtmlLabels = evaluate(getConfig2().flowchart?.htmlLabels);
const w = bbox.width + (node.padding ?? 0);
const h = w + bbox.height;
const tw = w + bbox.height;
const points = [
{ x: 0, y: 0 },
{ x: tw, y: 0 },
{ x: tw / 2, y: -h }
];
const { cssStyles } = node;
const rc = rough50.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const pathData = createPathFromPoints(points);
const roughNode = rc.path(pathData, options);
const polygon = shapeSvg.insert(() => roughNode, ":first-child").attr("transform", `translate(${-h / 2}, ${h / 2})`);
if (cssStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
polygon.selectChildren("path").attr("style", nodeStyles);
}
node.width = w;
node.height = h;
updateNodeBounds(node, polygon);
label.attr(
"transform",
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))}, ${h / 2 - (bbox.height + (node.padding ?? 0) / (useHtmlLabels ? 2 : 1) - (bbox.y - (bbox.top ?? 0)))})`
);
node.intersect = function(point) {
log.info("Triangle intersect", node, points, point);
return intersect_default.polygon(node, points, point);
};
return shapeSvg;
}
__name(triangle, "triangle");
// src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts
import rough51 from "roughjs";
async function waveEdgedRectangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const waveAmplitude = h / 8;
const finalH = h + waveAmplitude;
const { cssStyles } = node;
const minWidth = 70;
const widthDif = minWidth - w;
const extraW = widthDif > 0 ? widthDif / 2 : 0;
const rc = rough51.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x: -w / 2 - extraW, y: finalH / 2 },
...generateFullSineWavePoints(
-w / 2 - extraW,
finalH / 2,
w / 2 + extraW,
finalH / 2,
waveAmplitude,
0.8
),
{ x: w / 2 + extraW, y: -finalH / 2 },
{ x: -w / 2 - extraW, y: -finalH / 2 }
];
const waveEdgeRectPath = createPathFromPoints(points);
const waveEdgeRectNode = rc.path(waveEdgeRectPath, options);
const waveEdgeRect = shapeSvg.insert(() => waveEdgeRectNode, ":first-child");
waveEdgeRect.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
waveEdgeRect.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
waveEdgeRect.selectAll("path").attr("style", nodeStyles);
}
waveEdgeRect.attr("transform", `translate(0,${-waveAmplitude / 2})`);
label.attr(
"transform",
`translate(${-w / 2 + (node.padding ?? 0) - (bbox.x - (bbox.left ?? 0))},${-h / 2 + (node.padding ?? 0) - waveAmplitude - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, waveEdgeRect);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(waveEdgedRectangle, "waveEdgedRectangle");
// src/rendering-util/rendering-elements/shapes/waveRectangle.ts
import rough52 from "roughjs";
async function waveRectangle(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
const minWidth = 100;
const minHeight = 50;
const baseWidth = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const baseHeight = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const aspectRatio = baseWidth / baseHeight;
let w = baseWidth;
let h = baseHeight;
if (w > h * aspectRatio) {
h = w / aspectRatio;
} else {
w = h * aspectRatio;
}
w = Math.max(w, minWidth);
h = Math.max(h, minHeight);
const waveAmplitude = Math.min(h * 0.2, h / 4);
const finalH = h + waveAmplitude * 2;
const { cssStyles } = node;
const rc = rough52.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const points = [
{ x: -w / 2, y: finalH / 2 },
...generateFullSineWavePoints(-w / 2, finalH / 2, w / 2, finalH / 2, waveAmplitude, 1),
{ x: w / 2, y: -finalH / 2 },
...generateFullSineWavePoints(w / 2, -finalH / 2, -w / 2, -finalH / 2, waveAmplitude, -1)
];
const waveRectPath = createPathFromPoints(points);
const waveRectNode = rc.path(waveRectPath, options);
const waveRect = shapeSvg.insert(() => waveRectNode, ":first-child");
waveRect.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
waveRect.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
waveRect.selectAll("path").attr("style", nodeStyles);
}
updateNodeBounds(node, waveRect);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, points, point);
return pos;
};
return shapeSvg;
}
__name(waveRectangle, "waveRectangle");
// src/rendering-util/rendering-elements/shapes/windowPane.ts
import rough53 from "roughjs";
async function windowPane(parent, node) {
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
const w = Math.max(bbox.width + (node.padding ?? 0) * 2, node?.width ?? 0);
const h = Math.max(bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
const rectOffset = 5;
const x = -w / 2;
const y = -h / 2;
const { cssStyles } = node;
const rc = rough53.svg(shapeSvg);
const options = userNodeOverrides(node, {});
const outerPathPoints = [
{ x: x - rectOffset, y: y - rectOffset },
{ x: x - rectOffset, y: y + h },
{ x: x + w, y: y + h },
{ x: x + w, y: y - rectOffset }
];
const path = `M${x - rectOffset},${y - rectOffset} L${x + w},${y - rectOffset} L${x + w},${y + h} L${x - rectOffset},${y + h} L${x - rectOffset},${y - rectOffset}
M${x - rectOffset},${y} L${x + w},${y}
M${x},${y - rectOffset} L${x},${y + h}`;
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const no = rc.path(path, options);
const windowPane2 = shapeSvg.insert(() => no, ":first-child");
windowPane2.attr("transform", `translate(${rectOffset / 2}, ${rectOffset / 2})`);
windowPane2.attr("class", "basic label-container");
if (cssStyles && node.look !== "handDrawn") {
windowPane2.selectAll("path").attr("style", cssStyles);
}
if (nodeStyles && node.look !== "handDrawn") {
windowPane2.selectAll("path").attr("style", nodeStyles);
}
label.attr(
"transform",
`translate(${-(bbox.width / 2) + rectOffset / 2 - (bbox.x - (bbox.left ?? 0))}, ${-(bbox.height / 2) + rectOffset / 2 - (bbox.y - (bbox.top ?? 0))})`
);
updateNodeBounds(node, windowPane2);
node.intersect = function(point) {
const pos = intersect_default.polygon(node, outerPathPoints, point);
return pos;
};
return shapeSvg;
}
__name(windowPane, "windowPane");
// src/rendering-util/rendering-elements/shapes/classBox.ts
import { select as select6 } from "d3";
import rough54 from "roughjs";
// src/diagrams/class/shapeUtil.ts
import { select as select5 } from "d3";
async function textHelper(parent, node, config, useHtmlLabels, GAP = config.class.padding ?? 12) {
const TEXT_PADDING = !useHtmlLabels ? 3 : 0;
const shapeSvg = parent.insert("g").attr("class", getNodeClasses(node)).attr("id", node.domId || node.id);
let annotationGroup = null;
let labelGroup = null;
let membersGroup = null;
let methodsGroup = null;
let annotationGroupHeight = 0;
let labelGroupHeight = 0;
let membersGroupHeight = 0;
annotationGroup = shapeSvg.insert("g").attr("class", "annotation-group text");
if (node.annotations.length > 0) {
const annotation = node.annotations[0];
await addText(annotationGroup, { text: `\xAB${annotation}\xBB` }, 0);
const annotationGroupBBox = annotationGroup.node().getBBox();
annotationGroupHeight = annotationGroupBBox.height;
}
labelGroup = shapeSvg.insert("g").attr("class", "label-group text");
await addText(labelGroup, node, 0, ["font-weight: bolder"]);
const labelGroupBBox = labelGroup.node().getBBox();
labelGroupHeight = labelGroupBBox.height;
membersGroup = shapeSvg.insert("g").attr("class", "members-group text");
let yOffset = 0;
for (const member of node.members) {
const height = await addText(membersGroup, member, yOffset, [member.parseClassifier()]);
yOffset += height + TEXT_PADDING;
}
membersGroupHeight = membersGroup.node().getBBox().height;
if (membersGroupHeight <= 0) {
membersGroupHeight = GAP / 2;
}
methodsGroup = shapeSvg.insert("g").attr("class", "methods-group text");
let methodsYOffset = 0;
for (const method of node.methods) {
const height = await addText(methodsGroup, method, methodsYOffset, [method.parseClassifier()]);
methodsYOffset += height + TEXT_PADDING;
}
let bbox = shapeSvg.node().getBBox();
if (annotationGroup !== null) {
const annotationGroupBBox = annotationGroup.node().getBBox();
annotationGroup.attr("transform", `translate(${-annotationGroupBBox.width / 2})`);
}
labelGroup.attr("transform", `translate(${-labelGroupBBox.width / 2}, ${annotationGroupHeight})`);
bbox = shapeSvg.node().getBBox();
membersGroup.attr(
"transform",
`translate(${0}, ${annotationGroupHeight + labelGroupHeight + GAP * 2})`
);
bbox = shapeSvg.node().getBBox();
methodsGroup.attr(
"transform",
`translate(${0}, ${annotationGroupHeight + labelGroupHeight + (membersGroupHeight ? membersGroupHeight + GAP * 4 : GAP * 2)})`
);
bbox = shapeSvg.node().getBBox();
return { shapeSvg, bbox };
}
__name(textHelper, "textHelper");
async function addText(parentGroup, node, yOffset, styles = []) {
const textEl = parentGroup.insert("g").attr("class", "label").attr("style", styles.join("; "));
const config = getConfig();
let useHtmlLabels = "useHtmlLabels" in node ? node.useHtmlLabels : evaluate(config.htmlLabels) ?? true;
let textContent = "";
if ("text" in node) {
textContent = node.text;
} else {
textContent = node.label;
}
if (!useHtmlLabels && textContent.startsWith("\\")) {
textContent = textContent.substring(1);
}
if (hasKatex(textContent)) {
useHtmlLabels = true;
}
const text2 = await createText(
textEl,
sanitizeText2(decodeEntities(textContent)),
{
width: calculateTextWidth(textContent, config) + 50,
// Add room for error when splitting text into multiple lines
classes: "markdown-node-label",
useHtmlLabels
},
config
);
let bbox;
let numberOfLines = 1;
if (!useHtmlLabels) {
if (styles.includes("font-weight: bolder")) {
select5(text2).selectAll("tspan").attr("font-weight", "");
}
numberOfLines = text2.children.length;
const textChild = text2.children[0];
if (text2.textContent === "" || text2.textContent.includes(">")) {
textChild.textContent = textContent[0] + textContent.substring(1).replaceAll(">", ">").replaceAll("<", "<").trim();
const preserveSpace = textContent[1] === " ";
if (preserveSpace) {
textChild.textContent = textChild.textContent[0] + " " + textChild.textContent.substring(1);
}
}
if (textChild.textContent === "undefined") {
textChild.textContent = "";
}
bbox = text2.getBBox();
} else {
const div = text2.children[0];
const dv = select5(text2);
numberOfLines = div.innerHTML.split("
").length;
if (div.innerHTML.includes("")) {
numberOfLines += div.innerHTML.split("").length - 1;
}
const images = div.getElementsByTagName("img");
if (images) {
const noImgText = textContent.replace(/]*>/g, "").trim() === "";
await Promise.all(
[...images].map(
(img) => new Promise((res) => {
function setupImage() {
img.style.display = "flex";
img.style.flexDirection = "column";
if (noImgText) {
const bodyFontSize = config.fontSize?.toString() ?? window.getComputedStyle(document.body).fontSize;
const enlargingFactor = 5;
const width = parseInt(bodyFontSize, 10) * enlargingFactor + "px";
img.style.minWidth = width;
img.style.maxWidth = width;
} else {
img.style.width = "100%";
}
res(img);
}
__name(setupImage, "setupImage");
setTimeout(() => {
if (img.complete) {
setupImage();
}
});
img.addEventListener("error", setupImage);
img.addEventListener("load", setupImage);
})
)
);
}
bbox = div.getBoundingClientRect();
dv.attr("width", bbox.width);
dv.attr("height", bbox.height);
}
textEl.attr("transform", "translate(0," + (-bbox.height / (2 * numberOfLines) + yOffset) + ")");
return bbox.height;
}
__name(addText, "addText");
// src/rendering-util/rendering-elements/shapes/classBox.ts
async function classBox(parent, node) {
const config = getConfig2();
const PADDING = config.class.padding ?? 12;
const GAP = PADDING;
const useHtmlLabels = node.useHtmlLabels ?? evaluate(config.htmlLabels) ?? true;
const classNode = node;
classNode.annotations = classNode.annotations ?? [];
classNode.members = classNode.members ?? [];
classNode.methods = classNode.methods ?? [];
const { shapeSvg, bbox } = await textHelper(parent, node, config, useHtmlLabels, GAP);
const { labelStyles, nodeStyles } = styles2String(node);
node.labelStyle = labelStyles;
node.cssStyles = classNode.styles || "";
const styles = classNode.styles?.join(";") || nodeStyles || "";
if (!node.cssStyles) {
node.cssStyles = styles.replaceAll("!important", "").split(";");
}
const renderExtraBox = classNode.members.length === 0 && classNode.methods.length === 0 && !config.class?.hideEmptyMembersBox;
const rc = rough54.svg(shapeSvg);
const options = userNodeOverrides(node, {});
if (node.look !== "handDrawn") {
options.roughness = 0;
options.fillStyle = "solid";
}
const w = bbox.width;
let h = bbox.height;
if (classNode.members.length === 0 && classNode.methods.length === 0) {
h += GAP;
} else if (classNode.members.length > 0 && classNode.methods.length === 0) {
h += GAP * 2;
}
const x = -w / 2;
const y = -h / 2;
const roughRect = rc.rectangle(
x - PADDING,
y - PADDING - (renderExtraBox ? PADDING : classNode.members.length === 0 && classNode.methods.length === 0 ? -PADDING / 2 : 0),
w + 2 * PADDING,
h + 2 * PADDING + (renderExtraBox ? PADDING * 2 : classNode.members.length === 0 && classNode.methods.length === 0 ? -PADDING : 0),
options
);
const rect2 = shapeSvg.insert(() => roughRect, ":first-child");
rect2.attr("class", "basic label-container");
const rectBBox = rect2.node().getBBox();
shapeSvg.selectAll(".text").each((_, i, nodes) => {
const text2 = select6(nodes[i]);
const transform = text2.attr("transform");
let translateY = 0;
if (transform) {
const regex = RegExp(/translate\(([^,]+),([^)]+)\)/);
const translate = regex.exec(transform);
if (translate) {
translateY = parseFloat(translate[2]);
}
}
let newTranslateY = translateY + y + PADDING - (renderExtraBox ? PADDING : classNode.members.length === 0 && classNode.methods.length === 0 ? -PADDING / 2 : 0);
if (!useHtmlLabels) {
newTranslateY -= 4;
}
let newTranslateX = x;
if (text2.attr("class").includes("label-group") || text2.attr("class").includes("annotation-group")) {
newTranslateX = -text2.node()?.getBBox().width / 2 || 0;
shapeSvg.selectAll("text").each(function(_2, i2, nodes2) {
if (window.getComputedStyle(nodes2[i2]).textAnchor === "middle") {
newTranslateX = 0;
}
});
}
text2.attr("transform", `translate(${newTranslateX}, ${newTranslateY})`);
});
const annotationGroupHeight = shapeSvg.select(".annotation-group").node().getBBox().height - (renderExtraBox ? PADDING / 2 : 0) || 0;
const labelGroupHeight = shapeSvg.select(".label-group").node().getBBox().height - (renderExtraBox ? PADDING / 2 : 0) || 0;
const membersGroupHeight = shapeSvg.select(".members-group").node().getBBox().height - (renderExtraBox ? PADDING / 2 : 0) || 0;
if (classNode.members.length > 0 || classNode.methods.length > 0 || renderExtraBox) {
const roughLine = rc.line(
rectBBox.x,
annotationGroupHeight + labelGroupHeight + y + PADDING,
rectBBox.x + rectBBox.width,
annotationGroupHeight + labelGroupHeight + y + PADDING,
options
);
const line = shapeSvg.insert(() => roughLine);
line.attr("class", "divider").attr("style", styles);
}
if (renderExtraBox || classNode.members.length > 0 || classNode.methods.length > 0) {
const roughLine = rc.line(
rectBBox.x,
annotationGroupHeight + labelGroupHeight + membersGroupHeight + y + GAP * 2 + PADDING,
rectBBox.x + rectBBox.width,
annotationGroupHeight + labelGroupHeight + membersGroupHeight + y + PADDING + GAP * 2,
options
);
const line = shapeSvg.insert(() => roughLine);
line.attr("class", "divider").attr("style", styles);
}
if (classNode.look !== "handDrawn") {
shapeSvg.selectAll("path").attr("style", styles);
}
rect2.select(":nth-child(2)").attr("style", styles);
shapeSvg.selectAll(".divider").select("path").attr("style", styles);
if (node.labelStyle) {
shapeSvg.selectAll("span").attr("style", node.labelStyle);
} else {
shapeSvg.selectAll("span").attr("style", styles);
}
if (!useHtmlLabels) {
const colorRegex = RegExp(/color\s*:\s*([^;]*)/);
const match = colorRegex.exec(styles);
if (match) {
const colorStyle = match[0].replace("color", "fill");
shapeSvg.selectAll("tspan").attr("style", colorStyle);
} else if (labelStyles) {
const match2 = colorRegex.exec(labelStyles);
if (match2) {
const colorStyle = match2[0].replace("color", "fill");
shapeSvg.selectAll("tspan").attr("style", colorStyle);
}
}
}
updateNodeBounds(node, rect2);
node.intersect = function(point) {
return intersect_default.rect(node, point);
};
return shapeSvg;
}
__name(classBox, "classBox");
// src/rendering-util/rendering-elements/shapes/kanbanItem.ts
import rough55 from "roughjs";
var colorFromPriority = /* @__PURE__ */ __name((priority) => {
switch (priority) {
case "Very High":
return "red";
case "High":
return "orange";
case "Medium":
return null;
case "Low":
return "blue";
case "Very Low":
return "lightblue";
}
}, "colorFromPriority");
async function kanbanItem(parent, kanbanNode, { config }) {
const { labelStyles, nodeStyles } = styles2String(kanbanNode);
kanbanNode.labelStyle = labelStyles || "";
const labelPaddingX = 10;
const orgWidth = kanbanNode.width;
kanbanNode.width = (kanbanNode.width ?? 200) - 10;
const {
shapeSvg,
bbox,
label: labelElTitle
} = await labelHelper(parent, kanbanNode, getNodeClasses(kanbanNode));
const padding = kanbanNode.padding || 10;
let ticketUrl = "";
let link;
if ("ticket" in kanbanNode && kanbanNode.ticket && config?.kanban?.ticketBaseUrl) {
ticketUrl = config?.kanban?.ticketBaseUrl.replace("#TICKET#", kanbanNode.ticket);
link = shapeSvg.insert("svg:a", ":first-child").attr("class", "kanban-ticket-link").attr("xlink:href", ticketUrl).attr("target", "_blank");
}
const options = {
useHtmlLabels: kanbanNode.useHtmlLabels,
labelStyle: kanbanNode.labelStyle || "",
width: kanbanNode.width,
img: kanbanNode.img,
padding: kanbanNode.padding || 8,
centerLabel: false
};
let labelEl, bbox2;
if (link) {
({ label: labelEl, bbox: bbox2 } = await insertLabel(
link,
"ticket" in kanbanNode && kanbanNode.ticket || "",
options
));
} else {
({ label: labelEl, bbox: bbox2 } = await insertLabel(
shapeSvg,
"ticket" in kanbanNode && kanbanNode.ticket || "",
options
));
}
const { label: labelElAssigned, bbox: bboxAssigned } = await insertLabel(
shapeSvg,
"assigned" in kanbanNode && kanbanNode.assigned || "",
options
);
kanbanNode.width = orgWidth;
const labelPaddingY = 10;
const totalWidth = kanbanNode?.width || 0;
const heightAdj = Math.max(bbox2.height, bboxAssigned.height) / 2;
const totalHeight = Math.max(bbox.height + labelPaddingY * 2, kanbanNode?.height || 0) + heightAdj;
const x = -totalWidth / 2;
const y = -totalHeight / 2;
labelElTitle.attr(
"transform",
"translate(" + (padding - totalWidth / 2) + ", " + (-heightAdj - bbox.height / 2) + ")"
);
labelEl.attr(
"transform",
"translate(" + (padding - totalWidth / 2) + ", " + (-heightAdj + bbox.height / 2) + ")"
);
labelElAssigned.attr(
"transform",
"translate(" + (padding + totalWidth / 2 - bboxAssigned.width - 2 * labelPaddingX) + ", " + (-heightAdj + bbox.height / 2) + ")"
);
let rect2;
const { rx, ry } = kanbanNode;
const { cssStyles } = kanbanNode;
if (kanbanNode.look === "handDrawn") {
const rc = rough55.svg(shapeSvg);
const options2 = userNodeOverrides(kanbanNode, {});
const roughNode = rx || ry ? rc.path(createRoundedRectPathD(x, y, totalWidth, totalHeight, rx || 0), options2) : rc.rectangle(x, y, totalWidth, totalHeight, options2);
rect2 = shapeSvg.insert(() => roughNode, ":first-child");
rect2.attr("class", "basic label-container").attr("style", cssStyles ? cssStyles : null);
} else {
rect2 = shapeSvg.insert("rect", ":first-child");
rect2.attr("class", "basic label-container __APA__").attr("style", nodeStyles).attr("rx", rx ?? 5).attr("ry", ry ?? 5).attr("x", x).attr("y", y).attr("width", totalWidth).attr("height", totalHeight);
const priority = "priority" in kanbanNode && kanbanNode.priority;
if (priority) {
const line = shapeSvg.append("line");
const lineX = x + 2;
const y1 = y + Math.floor((rx ?? 0) / 2);
const y2 = y + totalHeight - Math.floor((rx ?? 0) / 2);
line.attr("x1", lineX).attr("y1", y1).attr("x2", lineX).attr("y2", y2).attr("stroke-width", "4").attr("stroke", colorFromPriority(priority));
}
}
updateNodeBounds(kanbanNode, rect2);
kanbanNode.height = totalHeight;
kanbanNode.intersect = function(point) {
return intersect_default.rect(kanbanNode, point);
};
return shapeSvg;
}
__name(kanbanItem, "kanbanItem");
// src/rendering-util/rendering-elements/shapes.ts
var shapesDefs = [
{
semanticName: "Process",
name: "Rectangle",
shortName: "rect",
description: "Standard process shape",
aliases: ["proc", "process", "rectangle"],
internalAliases: ["squareRect"],
handler: squareRect2
},
{
semanticName: "Event",
name: "Rounded Rectangle",
shortName: "rounded",
description: "Represents an event",
aliases: ["event"],
internalAliases: ["roundedRect"],
handler: roundedRect
},
{
semanticName: "Terminal Point",
name: "Stadium",
shortName: "stadium",
description: "Terminal point",
aliases: ["terminal", "pill"],
handler: stadium
},
{
semanticName: "Subprocess",
name: "Framed Rectangle",
shortName: "fr-rect",
description: "Subprocess",
aliases: ["subprocess", "subproc", "framed-rectangle", "subroutine"],
handler: subroutine
},
{
semanticName: "Database",
name: "Cylinder",
shortName: "cyl",
description: "Database storage",
aliases: ["db", "database", "cylinder"],
handler: cylinder
},
{
semanticName: "Start",
name: "Circle",
shortName: "circle",
description: "Starting point",
aliases: ["circ"],
handler: circle
},
{
semanticName: "Decision",
name: "Diamond",
shortName: "diam",
description: "Decision-making step",
aliases: ["decision", "diamond", "question"],
handler: question
},
{
semanticName: "Prepare Conditional",
name: "Hexagon",
shortName: "hex",
description: "Preparation or condition step",
aliases: ["hexagon", "prepare"],
handler: hexagon
},
{
semanticName: "Data Input/Output",
name: "Lean Right",
shortName: "lean-r",
description: "Represents input or output",
aliases: ["lean-right", "in-out"],
internalAliases: ["lean_right"],
handler: lean_right
},
{
semanticName: "Data Input/Output",
name: "Lean Left",
shortName: "lean-l",
description: "Represents output or input",
aliases: ["lean-left", "out-in"],
internalAliases: ["lean_left"],
handler: lean_left
},
{
semanticName: "Priority Action",
name: "Trapezoid Base Bottom",
shortName: "trap-b",
description: "Priority action",
aliases: ["priority", "trapezoid-bottom", "trapezoid"],
handler: trapezoid
},
{
semanticName: "Manual Operation",
name: "Trapezoid Base Top",
shortName: "trap-t",
description: "Represents a manual task",
aliases: ["manual", "trapezoid-top", "inv-trapezoid"],
internalAliases: ["inv_trapezoid"],
handler: inv_trapezoid
},
{
semanticName: "Stop",
name: "Double Circle",
shortName: "dbl-circ",
description: "Represents a stop point",
aliases: ["double-circle"],
internalAliases: ["doublecircle"],
handler: doublecircle
},
{
semanticName: "Text Block",
name: "Text Block",
shortName: "text",
description: "Text block",
handler: text
},
{
semanticName: "Card",
name: "Notched Rectangle",
shortName: "notch-rect",
description: "Represents a card",
aliases: ["card", "notched-rectangle"],
handler: card
},
{
semanticName: "Lined/Shaded Process",
name: "Lined Rectangle",
shortName: "lin-rect",
description: "Lined process shape",
aliases: ["lined-rectangle", "lined-process", "lin-proc", "shaded-process"],
handler: shadedProcess
},
{
semanticName: "Start",
name: "Small Circle",
shortName: "sm-circ",
description: "Small starting point",
aliases: ["start", "small-circle"],
internalAliases: ["stateStart"],
handler: stateStart
},
{
semanticName: "Stop",
name: "Framed Circle",
shortName: "fr-circ",
description: "Stop point",
aliases: ["stop", "framed-circle"],
internalAliases: ["stateEnd"],
handler: stateEnd
},
{
semanticName: "Fork/Join",
name: "Filled Rectangle",
shortName: "fork",
description: "Fork or join in process flow",
aliases: ["join"],
internalAliases: ["forkJoin"],
handler: forkJoin
},
{
semanticName: "Collate",
name: "Hourglass",
shortName: "hourglass",
description: "Represents a collate operation",
aliases: ["hourglass", "collate"],
handler: hourglass
},
{
semanticName: "Comment",
name: "Curly Brace",
shortName: "brace",
description: "Adds a comment",
aliases: ["comment", "brace-l"],
handler: curlyBraceLeft
},
{
semanticName: "Comment Right",
name: "Curly Brace",
shortName: "brace-r",
description: "Adds a comment",
handler: curlyBraceRight
},
{
semanticName: "Comment with braces on both sides",
name: "Curly Braces",
shortName: "braces",
description: "Adds a comment",
handler: curlyBraces
},
{
semanticName: "Com Link",
name: "Lightning Bolt",
shortName: "bolt",
description: "Communication link",
aliases: ["com-link", "lightning-bolt"],
handler: lightningBolt
},
{
semanticName: "Document",
name: "Document",
shortName: "doc",
description: "Represents a document",
aliases: ["doc", "document"],
handler: waveEdgedRectangle
},
{
semanticName: "Delay",
name: "Half-Rounded Rectangle",
shortName: "delay",
description: "Represents a delay",
aliases: ["half-rounded-rectangle"],
handler: halfRoundedRectangle
},
{
semanticName: "Direct Access Storage",
name: "Horizontal Cylinder",
shortName: "h-cyl",
description: "Direct access storage",
aliases: ["das", "horizontal-cylinder"],
handler: tiltedCylinder
},
{
semanticName: "Disk Storage",
name: "Lined Cylinder",
shortName: "lin-cyl",
description: "Disk storage",
aliases: ["disk", "lined-cylinder"],
handler: linedCylinder
},
{
semanticName: "Display",
name: "Curved Trapezoid",
shortName: "curv-trap",
description: "Represents a display",
aliases: ["curved-trapezoid", "display"],
handler: curvedTrapezoid
},
{
semanticName: "Divided Process",
name: "Divided Rectangle",
shortName: "div-rect",
description: "Divided process shape",
aliases: ["div-proc", "divided-rectangle", "divided-process"],
handler: dividedRectangle
},
{
semanticName: "Extract",
name: "Triangle",
shortName: "tri",
description: "Extraction process",
aliases: ["extract", "triangle"],
handler: triangle
},
{
semanticName: "Internal Storage",
name: "Window Pane",
shortName: "win-pane",
description: "Internal storage",
aliases: ["internal-storage", "window-pane"],
handler: windowPane
},
{
semanticName: "Junction",
name: "Filled Circle",
shortName: "f-circ",
description: "Junction point",
aliases: ["junction", "filled-circle"],
handler: filledCircle
},
{
semanticName: "Loop Limit",
name: "Trapezoidal Pentagon",
shortName: "notch-pent",
description: "Loop limit step",
aliases: ["loop-limit", "notched-pentagon"],
handler: trapezoidalPentagon
},
{
semanticName: "Manual File",
name: "Flipped Triangle",
shortName: "flip-tri",
description: "Manual file operation",
aliases: ["manual-file", "flipped-triangle"],
handler: flippedTriangle
},
{
semanticName: "Manual Input",
name: "Sloped Rectangle",
shortName: "sl-rect",
description: "Manual input step",
aliases: ["manual-input", "sloped-rectangle"],
handler: slopedRect
},
{
semanticName: "Multi-Document",
name: "Stacked Document",
shortName: "docs",
description: "Multiple documents",
aliases: ["documents", "st-doc", "stacked-document"],
handler: multiWaveEdgedRectangle
},
{
semanticName: "Multi-Process",
name: "Stacked Rectangle",
shortName: "st-rect",
description: "Multiple processes",
aliases: ["procs", "processes", "stacked-rectangle"],
handler: multiRect
},
{
semanticName: "Stored Data",
name: "Bow Tie Rectangle",
shortName: "bow-rect",
description: "Stored data",
aliases: ["stored-data", "bow-tie-rectangle"],
handler: bowTieRect
},
{
semanticName: "Summary",
name: "Crossed Circle",
shortName: "cross-circ",
description: "Summary",
aliases: ["summary", "crossed-circle"],
handler: crossedCircle
},
{
semanticName: "Tagged Document",
name: "Tagged Document",
shortName: "tag-doc",
description: "Tagged document",
aliases: ["tag-doc", "tagged-document"],
handler: taggedWaveEdgedRectangle
},
{
semanticName: "Tagged Process",
name: "Tagged Rectangle",
shortName: "tag-rect",
description: "Tagged process",
aliases: ["tagged-rectangle", "tag-proc", "tagged-process"],
handler: taggedRect
},
{
semanticName: "Paper Tape",
name: "Flag",
shortName: "flag",
description: "Paper tape",
aliases: ["paper-tape"],
handler: waveRectangle
},
{
semanticName: "Odd",
name: "Odd",
shortName: "odd",
description: "Odd shape",
internalAliases: ["rect_left_inv_arrow"],
handler: rect_left_inv_arrow
},
{
semanticName: "Lined Document",
name: "Lined Document",
shortName: "lin-doc",
description: "Lined document",
aliases: ["lined-document"],
handler: linedWaveEdgedRect
}
];
var generateShapeMap = /* @__PURE__ */ __name(() => {
const undocumentedShapes = {
// States
state,
choice,
note,
// Rectangles
rectWithTitle,
labelRect,
// Icons
iconSquare,
iconCircle,
icon,
iconRounded,
imageSquare,
anchor,
// Kanban diagram
kanbanItem,
// class diagram
classBox
};
const entries = [
...Object.entries(undocumentedShapes),
...shapesDefs.flatMap((shape) => {
const aliases = [
shape.shortName,
..."aliases" in shape ? shape.aliases : [],
..."internalAliases" in shape ? shape.internalAliases : []
];
return aliases.map((alias) => [alias, shape.handler]);
})
];
return Object.fromEntries(entries);
}, "generateShapeMap");
var shapes2 = generateShapeMap();
function isValidShape(shape) {
return shape in shapes2;
}
__name(isValidShape, "isValidShape");
// src/rendering-util/rendering-elements/nodes.ts
var nodeElems = /* @__PURE__ */ new Map();
async function insertNode(elem, node, renderOptions) {
let newEl;
let el;
if (node.shape === "rect") {
if (node.rx && node.ry) {
node.shape = "roundedRect";
} else {
node.shape = "squareRect";
}
}
const shapeHandler = node.shape ? shapes2[node.shape] : void 0;
if (!shapeHandler) {
throw new Error(`No such shape: ${node.shape}. Please check your syntax.`);
}
if (node.link) {
let target;
if (renderOptions.config.securityLevel === "sandbox") {
target = "_top";
} else if (node.linkTarget) {
target = node.linkTarget || "_blank";
}
newEl = elem.insert("svg:a").attr("xlink:href", node.link).attr("target", target ?? null);
el = await shapeHandler(newEl, node, renderOptions);
} else {
el = await shapeHandler(elem, node, renderOptions);
newEl = el;
}
if (node.tooltip) {
el.attr("title", node.tooltip);
}
nodeElems.set(node.id, newEl);
if (node.haveCallback) {
newEl.attr("class", newEl.attr("class") + " clickable");
}
return newEl;
}
__name(insertNode, "insertNode");
var setNodeElem = /* @__PURE__ */ __name((elem, node) => {
nodeElems.set(node.id, elem);
}, "setNodeElem");
var clear2 = /* @__PURE__ */ __name(() => {
nodeElems.clear();
}, "clear");
var positionNode = /* @__PURE__ */ __name((node) => {
const el = nodeElems.get(node.id);
log.trace(
"Transforming node",
node.diff,
node,
"translate(" + (node.x - node.width / 2 - 5) + ", " + node.width / 2 + ")"
);
const padding = 8;
const diff = node.diff || 0;
if (node.clusterNode) {
el.attr(
"transform",
"translate(" + (node.x + diff - node.width / 2) + ", " + (node.y - node.height / 2 - padding) + ")"
);
} else {
el.attr("transform", "translate(" + node.x + ", " + node.y + ")");
}
return diff;
}, "positionNode");
export {
labelHelper,
updateNodeBounds,
createLabel_default,
isValidShape,
insertCluster,
clear,
insertNode,
setNodeElem,
clear2,
positionNode
};