UNPKG

mermaid

Version:

Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.

708 lines (703 loc) 29.7 kB
import { getSubGraphTitleMargins } from "./chunk-5DYCD2WN.mjs"; import { createLabel_default, createRoundedRectPathD, intersect_rect_default } from "./chunk-7INBJB4K.mjs"; import { compileStyles, styles2String, userNodeOverrides } from "./chunk-7PRAP22T.mjs"; import { createText } from "./chunk-MBY4JIJT.mjs"; import { stampColorSlot } from "./chunk-J5ZVWO5B.mjs"; import { evaluate, getConfig2 as getConfig, getEffectiveHtmlLabels } from "./chunk-O7XYJQB3.mjs"; import { log } from "./chunk-X3CZISLH.mjs"; import { __name } from "./chunk-Y2CYZVJY.mjs"; // src/rendering-util/rendering-elements/clusters.js import { select as select2 } from "d3"; import rough2 from "roughjs"; // src/rendering-util/rendering-elements/clusters/swimlane.js import { select } from "d3"; import rough from "roughjs"; var swimlane = /* @__PURE__ */ __name(async (parent, node) => { const siteConfig = getConfig(); const { theme, themeVariables, handDrawnSeed } = siteConfig; const { clusterBkg, clusterBorder, borderColorArray } = themeVariables; const laneStroke = clusterBorder; const { labelStyles, nodeStyles, borderStyles, backgroundStyles } = styles2String(node); const shapeSvg = parent.insert("g").attr("class", "cluster swimlane " + (node.cssClasses || "")).attr("id", node.id).attr("data-id", node.id).attr("data-et", "cluster").attr("data-look", node.look); stampColorSlot(shapeSvg, node.colorIndex, theme, borderColorArray); const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); const isLR = node.direction === "LR"; const labelEl = shapeSvg.insert("g").attr("class", "cluster-label swimlane-label"); const text = await createText(labelEl, node.label, { style: node.labelStyle, useHtmlLabels, isNode: true, width: node.width }); let bbox = text.getBBox(); if (useHtmlLabels) { const div = text.children[0]; const dv = select(text); bbox = div.getBoundingClientRect(); dv.attr("width", bbox.width); dv.attr("height", bbox.height); } const padding = node.padding ?? 0; const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width; if (node.width <= bbox.width + padding) { node.diff = (width - node.width) / 2 - padding; } else { node.diff = -padding; } const height = node.height; const laneTop = node.y - height / 2; const laneBottom = node.y + height / 2; const laneLeft = node.x - width / 2; const contentTop = node.swimlaneContentTop !== void 0 ? node.swimlaneContentTop : laneTop + height / 3; const titlePaddingY = isLR ? 4 : 0; const desiredTitleSize = bbox.height + 2 * titlePaddingY; let titleRect; let bodyRect; if (isLR) { const titleWidth = Math.max(desiredTitleSize, bbox.height + 2 * titlePaddingY); const bodyX = laneLeft + titleWidth; const bodyWidth = Math.max(0, width - titleWidth); if (node.look === "handDrawn") { const rc = rough.svg(shapeSvg); const titleOptions = userNodeOverrides(node, { roughness: 0.7, fill: clusterBkg, stroke: laneStroke, // fillWeight: 3, seed: handDrawnSeed }); const bodyOptions = userNodeOverrides(node, { roughness: 0.7, fill: "none", stroke: laneStroke, seed: handDrawnSeed }); const roughTitle = rc.rectangle(laneLeft, laneTop, titleWidth, height, titleOptions); titleRect = shapeSvg.insert(() => roughTitle, ":first-child").attr("class", "swimlane-title"); const roughBody = rc.rectangle(bodyX, laneTop, bodyWidth, height, bodyOptions); bodyRect = shapeSvg.insert(() => roughBody, ":first-child").attr("class", "swimlane-body"); titleRect.select("path:nth-child(2)").attr("style", borderStyles.join(";")); titleRect.select("path").attr("style", backgroundStyles.join(";").replace("fill", "stroke")); } else { titleRect = shapeSvg.insert("rect", ":first-child"); bodyRect = shapeSvg.insert("rect", ":first-child"); titleRect.attr("class", "swimlane-title").attr("style", nodeStyles).attr("x", laneLeft).attr("y", laneTop).attr("width", titleWidth).attr("height", height).attr("fill", clusterBkg).attr("stroke", laneStroke); bodyRect.attr("class", "swimlane-body").attr("style", nodeStyles).attr("x", bodyX).attr("y", laneTop).attr("width", bodyWidth).attr("height", height).attr("fill", "none").attr("stroke", laneStroke); } const labelCenterX = laneLeft + titleWidth / 2; const labelCenterY = node.y; labelEl.attr( "transform", `translate(${labelCenterX}, ${labelCenterY}) rotate(-90) translate(${-bbox.width / 2}, ${-bbox.height / 2})` ); } else { const headerMaxHeight = Math.max(0, contentTop - laneTop); const titleHeight = Math.min(desiredTitleSize, headerMaxHeight); const bodyY = laneTop + titleHeight; const contentHeight = Math.max(0, laneBottom - bodyY); const x = node.x - width / 2; if (node.look === "handDrawn") { const rc = rough.svg(shapeSvg); const titleOptions = userNodeOverrides(node, { roughness: 0.7, fill: clusterBkg, stroke: laneStroke, fillWeight: 3, seed: handDrawnSeed }); const bodyOptions = userNodeOverrides(node, { roughness: 0.7, fill: "none", stroke: laneStroke, seed: handDrawnSeed }); const roughTitle = rc.rectangle(x, laneTop, width, titleHeight, titleOptions); titleRect = shapeSvg.insert(() => roughTitle, ":first-child").attr("class", "swimlane-title"); const roughBody = rc.rectangle(x, bodyY, width, contentHeight, bodyOptions); bodyRect = shapeSvg.insert(() => roughBody, ":first-child").attr("class", "swimlane-body"); titleRect.select("path:nth-child(2)").attr("style", borderStyles.join(";")); titleRect.select("path").attr("style", backgroundStyles.join(";").replace("fill", "stroke")); } else { titleRect = shapeSvg.insert("rect", ":first-child"); bodyRect = shapeSvg.insert("rect", ":first-child"); titleRect.attr("class", "swimlane-title").attr("style", nodeStyles).attr("x", x).attr("y", laneTop).attr("width", width).attr("height", titleHeight).attr("fill", clusterBkg).attr("stroke", laneStroke); bodyRect.attr("class", "swimlane-body").attr("style", nodeStyles).attr("x", x).attr("y", bodyY).attr("width", width).attr("height", contentHeight).attr("fill", "none").attr("stroke", laneStroke); } const labelX = node.x - bbox.width / 2; const labelY = laneTop + (titleHeight - bbox.height) / 2; labelEl.attr("transform", `translate(${labelX}, ${labelY})`); } log.trace("Swimlane data ", node, JSON.stringify(node)); if (labelStyles) { const span = labelEl.select("span"); if (span) { span.attr("style", labelStyles); } } node.offsetX = 0; node.width = width; node.height = height; node.offsetY = bbox.height - padding / 2; node.intersect = function(point) { return intersect_rect_default(node, point); }; return { cluster: shapeSvg, labelBBox: bbox }; }, "swimlane"); // 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 = getConfig(); const { theme, themeVariables, handDrawnSeed } = siteConfig; const { clusterBkg, clusterBorder, borderColorArray } = themeVariables; const { labelStyles, nodeStyles, borderStyles, backgroundStyles } = styles2String(node); const shapeSvg = parent.insert("g").attr("class", "cluster " + node.cssClasses).attr("id", node.domId).attr("data-look", node.look); stampColorSlot(shapeSvg, node.colorIndex, theme, borderColorArray); const useHtmlLabels = getEffectiveHtmlLabels(siteConfig); const labelEl = shapeSvg.insert("g").attr("class", "cluster-label "); let text; if (node.labelType === "markdown") { text = await createText(labelEl, node.label, { style: node.labelStyle, useHtmlLabels, isNode: true, width: node.width }); } else { text = await createLabel_default(labelEl, node.label, node.labelStyle || "", false, true); } let bbox = text.getBBox(); if (getEffectiveHtmlLabels(siteConfig)) { const div = text.children[0]; const dv = select2(text); 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 = rough2.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.domId); 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 = getConfig(); const { theme, themeVariables, handDrawnSeed } = siteConfig; const { altBackground, borderColorArray, compositeBackground, compositeTitleBackground, nodeBorder } = themeVariables; const shapeSvg = parent.insert("g").attr("class", node.cssClasses).attr("id", node.domId).attr("data-id", node.id).attr("data-look", node.look); stampColorSlot(shapeSvg, node.colorIndex, theme, borderColorArray); const outerRectG = shapeSvg.insert("g", ":first-child"); const label = shapeSvg.insert("g").attr("class", "cluster-label"); let innerRect = shapeSvg.append("rect"); const text = await createLabel_default(label, node.label, node.labelStyle, void 0, true); let bbox = text.getBBox(); if (getEffectiveHtmlLabels(siteConfig)) { const div = text.children[0]; const dv = select2(text); 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 = rough2.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); rect2.attr("class", "outer"); innerRect.attr("class", "inner"); } 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 - (getEffectiveHtmlLabels(siteConfig) ? 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 = getConfig(); 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.domId).attr("data-look", node.look); const useHtmlLabels = getEffectiveHtmlLabels(siteConfig); const labelEl = shapeSvg.insert("g").attr("class", "cluster-label "); const text = await createText(labelEl, node.label, { style: node.labelStyle, useHtmlLabels, isNode: true, width: node.width }); let bbox = text.getBBox(); if (getEffectiveHtmlLabels(siteConfig)) { const div = text.children[0]; const dv = select2(text); 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 = rough2.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 = getConfig(); const { theme, themeVariables, handDrawnSeed } = siteConfig; const { altBackground, nodeBorder, borderColorArray } = themeVariables; const shapeSvg = parent.insert("g").attr("class", node.cssClasses).attr("id", node.domId).attr("data-look", node.look); stampColorSlot(shapeSvg, node.colorIndex, theme, borderColorArray); 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 = rough2.svg(shapeSvg); const roughOuterNode = rc.rectangle(x, y, width, height, { // The theme's own value, matching what `rect.divider` gets from CSS under the other // looks -- and the same fallback. It was hardcoded `lightgrey`, which no dark theme // ever asked for; that stayed tolerable only while the fill was sparse hatching, and // turns into a bright block on a dark canvas once it is solid. fill: altBackground ?? "#efefef", // Solid rather than roughjs's default hachure. A hachure fill is drawn as *stroked* // lines, so both of the group's paths come out with `fill="none"` and a stylesheet // cannot tell the fill from the outline -- which is the same trap documented on // `roundedWithTitle`'s inner shape in `state/styles.js`. Solid splits them the way // the composite's outer shape already does, so a region can take the palette's tint // and border without its hatching being repainted. `roundedWithTitle` fills solid // too, except for its deliberately hatched alt variant. fillStyle: "solid", roughness: 0.5, strokeLineDash: [5], stroke: nodeBorder, seed: handDrawnSeed }); rect2 = shapeSvg.insert(() => roughOuterNode, ":first-child").attr("class", "divider"); } else { rect2 = outerRectG.insert("rect", ":first-child"); let outerRectClass = "outer"; if (node.look === "neo") { outerRectClass = "divider"; } else { 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 createContainerGroup = /* @__PURE__ */ __name(async (parent, node, opts) => { log.info(`Creating ${opts.cssClass} for `, node.id, node); const siteConfig = getConfig(); const { theme, themeVariables, handDrawnSeed } = siteConfig; const { borderColorArray } = themeVariables; const { labelStyles, borderStyles } = styles2String(node); const shapeSvg = parent.insert("g").attr("class", "cluster " + opts.cssClass + " " + node.cssClasses).attr("id", node.domId ?? node.id).attr("data-look", node.look); stampColorSlot(shapeSvg, node.colorIndex, theme, borderColorArray); const useHtmlLabels = getEffectiveHtmlLabels(siteConfig); const labelEl = shapeSvg.insert("g").attr("class", "cluster-label"); let bbox = { width: 0, height: 0 }; const hasLabel = node.label?.trim(); if (hasLabel) { let text; if (node.labelType === "markdown") { text = await createText(labelEl, node.label, { style: node.labelStyle, useHtmlLabels, isNode: true, width: node.width }); } else { text = await createLabel_default(labelEl, node.label, node.labelStyle || "", false, true); } bbox = text.getBBox(); if (useHtmlLabels) { const div = text.children[0]; const dv = select2(text); 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; let rectEl; if (node.look === "handDrawn") { const rc = rough2.svg(shapeSvg); const roughOpts = userNodeOverrides(node, { roughness: opts.roughness, fill: opts.fill, stroke: opts.stroke, strokeWidth: opts.strokeWidth, seed: handDrawnSeed, ...opts.fill === "none" ? { fillWeight: 0 } : { fillStyle: "solid" }, ...opts.strokeDash ? { strokeLineDash: opts.strokeDash } : {} }); const roughNode = rc.path(createRoundedRectPathD(x, y, width, height, opts.rx), roughOpts); rectEl = shapeSvg.insert(() => roughNode, ":first-child"); rectEl.select("path:nth-child(2)").attr("style", borderStyles.join(";")); } else { rectEl = shapeSvg.insert("rect", ":first-child"); rectEl.attr("rx", opts.rx).attr("ry", opts.rx).attr("x", x).attr("y", y).attr("width", width).attr("height", height).attr("fill", opts.fill).attr("stroke", opts.stroke).attr("stroke-width", opts.strokeWidth + "px"); if (opts.strokeDash) { rectEl.attr("stroke-dasharray", opts.strokeDash.join(", ")); } } if (hasLabel) { const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig); labelEl.attr( "transform", `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 = rectEl.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 }; }, "createContainerGroup"); var flowGroup = /* @__PURE__ */ __name(async (parent, node) => { const { themeVariables } = getConfig(); const stroke = themeVariables.flowContainerStroke || themeVariables.secondaryBorderColor; return createContainerGroup(parent, node, { cssClass: "flow-cluster", rx: 10, fill: "none", stroke, strokeWidth: 0.75, roughness: 0.7 }); }, "flowGroup"); var getUsecaseSystemBoundaryGeometry = /* @__PURE__ */ __name((node, labelBBox) => { const boundaryType = node.boundaryType || "rect"; const horizontalLabelPadding = boundaryType === "package" ? 20 : node.padding; const tabHeight = boundaryType === "package" ? labelBBox.height + 10 : 0; const width = Math.max(node.width, labelBBox.width + horizontalLabelPadding); const height = boundaryType === "package" ? Math.max(node.height, tabHeight + node.padding * 2) : node.height; const x = node.x - width / 2; const y = node.y - height / 2; return { boundaryType, width, height, x, y, bodyY: y + tabHeight, bodyHeight: height - tabHeight, tabHeight, tabWidth: boundaryType === "package" ? Math.min(width, Math.max(80, labelBBox.width + 20)) : 0 }; }, "getUsecaseSystemBoundaryGeometry"); var usecaseSystemBoundary = /* @__PURE__ */ __name(async (parent, node) => { log.info("Creating usecase system boundary for ", node.id, node); const siteConfig = getConfig(); const { theme, themeVariables, handDrawnSeed } = siteConfig; const { clusterBkg, clusterBorder, borderColorArray } = themeVariables; const { labelStyles, nodeStyles } = styles2String(node); const { stylesMap } = compileStyles(node); const boundaryType = node.boundaryType || "rect"; const shapeSvg = parent.insert("g").attr( "class", `cluster usecase-system-boundary usecase-system-boundary-${boundaryType} ${node.cssClasses}` ).attr("id", typeof node.domId === "string" ? node.domId : node.id).attr("data-boundary-type", boundaryType).attr("data-look", node.look); stampColorSlot(shapeSvg, node.colorIndex, theme, borderColorArray); const useHtmlLabels = getEffectiveHtmlLabels(siteConfig); const labelEl = shapeSvg.insert("g").attr("class", "cluster-label system-boundary-title"); const text = await createText(labelEl, node.label, { style: labelStyles, useHtmlLabels, isNode: true }); let bbox = text.getBBox(); if (useHtmlLabels) { const div = text.children[0]; const dv = select2(text); bbox = div.getBoundingClientRect(); dv.attr("width", bbox.width); dv.attr("height", bbox.height); } const geometry = getUsecaseSystemBoundaryGeometry(node, bbox); const { width, height, x, y, bodyY, bodyHeight, tabHeight, tabWidth } = geometry; node.diff = node.width <= bbox.width + node.padding ? (width - node.width) / 2 - node.padding : -node.padding; const roughOptions = userNodeOverrides(node, { fill: stylesMap.get("fill") || clusterBkg, stroke: stylesMap.get("stroke") || clusterBorder, strokeWidth: stylesMap.get("stroke-width")?.replace("px", "") || 1, seed: handDrawnSeed }); if (node.look === "handDrawn") { const rc = rough2.svg(shapeSvg); const roughBody = rc.rectangle(x, bodyY, width, bodyHeight, roughOptions); shapeSvg.insert(() => roughBody, ":first-child").attr("class", "boundary-body label-container"); if (boundaryType === "package") { const roughTab = rc.rectangle(x, y, tabWidth, tabHeight, roughOptions); shapeSvg.insert(() => roughTab, ":first-child").attr("class", "boundary-tab system-boundary-package-tab label-container"); } } else { shapeSvg.insert("rect", ":first-child").attr("class", "boundary-body label-container").attr("style", nodeStyles).attr("x", x).attr("y", bodyY).attr("width", width).attr("height", bodyHeight); if (boundaryType === "package") { shapeSvg.insert("rect", ":first-child").attr("class", "boundary-tab system-boundary-package-tab label-container").attr("style", nodeStyles).attr("x", x).attr("y", y).attr("width", tabWidth).attr("height", tabHeight); } } const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig); if (boundaryType === "package") { labelEl.attr( "transform", `translate(${x + (tabWidth - bbox.width) / 2}, ${y + (tabHeight - bbox.height) / 2})` ); } else { labelEl.attr( "transform", `translate(${node.x - bbox.width / 2}, ${y + subGraphTitleTopMargin})` ); } if (labelStyles) { labelEl.attr("style", labelStyles); labelEl.select("span").attr("style", labelStyles); } node.offsetX = 0; node.width = width; node.height = height; 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 }; }, "usecaseSystemBoundary"); var squareRect = rect; var shapes = { rect, squareRect, roundedWithTitle, noteGroup, divider, kanbanSection, flowGroup, usecaseSystemBoundary, swimlane }; var UNTITLED_CLUSTER_SHAPES = /* @__PURE__ */ new Set(["noteGroup", "divider"]); var clusterPaintsTitle = /* @__PURE__ */ __name((shape) => !UNTITLED_CLUSTER_SHAPES.has(shape ?? "rect"), "clusterPaintsTitle"); 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"); export { clusterPaintsTitle, insertCluster, clear };