diff --git a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js index 54d4ddf3ee6..c0fbe6ba05f 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js @@ -22,6 +22,7 @@ import { lean_left } from './shapes/leanLeft.js'; import { trapezoid } from './shapes/trapezoid.js'; import { inv_trapezoid } from './shapes/invertedTrapezoid.js'; import { labelRect } from './shapes/labelRect.js'; +import { history, deephistory } from './shapes/history.js'; const shapes = { state, @@ -47,6 +48,8 @@ const shapes = { trapezoid, inv_trapezoid, labelRect, + history, + deephistory, }; const nodeElems = new Map(); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/history.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/history.ts new file mode 100644 index 00000000000..fef42b50a9b --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/history.ts @@ -0,0 +1,58 @@ +import { log } from '$root/logger.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; +import intersect from '../intersect/index.js'; +import type { Node } from '$root/rendering-util/types.d.ts'; +import { + styles2String, + userNodeOverrides, +} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import rough from 'roughjs'; + +const historyBase = async (parent: SVGAElement, node: Node): Promise => { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const { shapeSvg } = await labelHelper(parent, node, getNodeClasses(node)); + + const radius = 16; + let circleElem; + const { cssStyles } = node; + + if (node.look === 'handDrawn') { + // @ts-ignore - rough is not typed + const rc = rough.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 history').attr('style', cssStyles); + } else { + circleElem = shapeSvg + .insert('circle', ':first-child') + .attr('class', 'basic label-container history') + .attr('style', nodeStyles) + .attr('r', radius) + .attr('cx', 0) + .attr('cy', 0); + } + + updateNodeBounds(node, circleElem); + + node.intersect = function (point) { + log.info('History intersect', node, radius, point); + return intersect.circle(node, radius, point); + }; + + return shapeSvg; +}; + +export const history = async (parent: SVGAElement, node: Node): Promise => { + node.label = 'H'; + node.labelStyle = 'font-weight: bold;'; + return await historyBase(parent, node); +}; + +export const deephistory = async (parent: SVGAElement, node: Node): Promise => { + node.label = 'H*'; + node.labelStyle = 'font-weight: bold;'; + return await historyBase(parent, node); +};