All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.dist.chunks.mermaid.core.chunk-HKLBG3BQ.mjs Maven / Gradle / Ivy

Go to download

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 };




© 2015 - 2024 Weber Informatics LLC | Privacy Policy