mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-16 18:54:12 +01:00
5237 Adding rectWith title shape
This commit is contained in:
@@ -231,6 +231,15 @@ const extract = (_doc) => {
|
|||||||
const look = config.look;
|
const look = config.look;
|
||||||
resetDataFetching();
|
resetDataFetching();
|
||||||
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look);
|
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look);
|
||||||
|
nodes.forEach((node) => {
|
||||||
|
if (Array.isArray(node.label)) {
|
||||||
|
// add the rest as description
|
||||||
|
node.description = node.label.slice(1);
|
||||||
|
// add first description as label
|
||||||
|
node.label = node.label[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('nodes after extract', nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { forkJoin } from './shapes/forkJoin.ts';
|
|||||||
import { choice } from './shapes/choice.ts';
|
import { choice } from './shapes/choice.ts';
|
||||||
import { note } from './shapes/note.ts';
|
import { note } from './shapes/note.ts';
|
||||||
import { stadium } from './shapes/stadium.js';
|
import { stadium } from './shapes/stadium.js';
|
||||||
|
import { rectWithTitle } from './shapes/rectWithTitle.js';
|
||||||
import { getConfig } from '$root/diagram-api/diagramAPI.js';
|
import { getConfig } from '$root/diagram-api/diagramAPI.js';
|
||||||
import { subroutine } from './shapes/subroutine.js';
|
import { subroutine } from './shapes/subroutine.js';
|
||||||
import { cylinder } from './shapes/cylinder.js';
|
import { cylinder } from './shapes/cylinder.js';
|
||||||
@@ -36,7 +37,7 @@ const shapes = {
|
|||||||
choice,
|
choice,
|
||||||
note,
|
note,
|
||||||
roundedRect,
|
roundedRect,
|
||||||
rectWithTitle: roundedRect,
|
rectWithTitle,
|
||||||
squareRect,
|
squareRect,
|
||||||
stadium,
|
stadium,
|
||||||
subroutine,
|
subroutine,
|
||||||
@@ -58,6 +59,8 @@ export const insertNode = async (elem, node, dir) => {
|
|||||||
let newEl;
|
let newEl;
|
||||||
let el;
|
let el;
|
||||||
|
|
||||||
|
console.log('node DDD', node);
|
||||||
|
|
||||||
//special check for rect shape (with or without rounded corners)
|
//special check for rect shape (with or without rounded corners)
|
||||||
if (node.shape === 'rect') {
|
if (node.shape === 'rect') {
|
||||||
if (node.rx && node.ry) {
|
if (node.rx && node.ry) {
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
import type { Node, RectOptions } from '$root/rendering-util/types.d.ts';
|
||||||
|
import { select } from 'd3';
|
||||||
|
import { evaluate } from '$root/diagrams/common/common.js';
|
||||||
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
|
import createLabel from '../createLabel.js';
|
||||||
|
import intersect from '../intersect/index.js';
|
||||||
|
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
|
||||||
|
import rough from 'roughjs';
|
||||||
|
import { getConfig } from '$root/diagram-api/diagramAPI.js';
|
||||||
|
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||||
|
import { log } from '$root/logger.js';
|
||||||
|
|
||||||
|
export const rectWithTitle = async (parent: SVGElement, node: Node) => {
|
||||||
|
let classes;
|
||||||
|
if (!node.cssClasses) {
|
||||||
|
classes = 'node default';
|
||||||
|
} else {
|
||||||
|
classes = 'node ' + node.cssClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add outer g element
|
||||||
|
const shapeSvg = parent
|
||||||
|
// @ts-ignore - d3 typings are not correct
|
||||||
|
.insert('g')
|
||||||
|
.attr('class', classes)
|
||||||
|
.attr('id', node.domId || node.id);
|
||||||
|
|
||||||
|
// Create the title label and insert it after the rect
|
||||||
|
const g = shapeSvg.insert('g');
|
||||||
|
|
||||||
|
const label = shapeSvg.insert('g').attr('class', 'label');
|
||||||
|
|
||||||
|
const description = node.description;
|
||||||
|
|
||||||
|
let title = node.label;
|
||||||
|
|
||||||
|
const text = label.node().appendChild(createLabel(title, node.labelStyle, true, true));
|
||||||
|
let bbox = { width: 0, height: 0 };
|
||||||
|
if (evaluate(getConfig()?.flowchart?.htmlLabels)) {
|
||||||
|
const div = text.children[0];
|
||||||
|
const dv = select(text);
|
||||||
|
bbox = div.getBoundingClientRect();
|
||||||
|
dv.attr('width', bbox.width);
|
||||||
|
dv.attr('height', bbox.height);
|
||||||
|
}
|
||||||
|
log.info('Text 2', description);
|
||||||
|
const textRows = description || [];
|
||||||
|
let titleBox = text.getBBox();
|
||||||
|
const descr = label
|
||||||
|
.node()
|
||||||
|
.appendChild(
|
||||||
|
createLabel(textRows.join ? textRows.join('<br/>') : textRows, node.labelStyle, true, true)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (evaluate(getConfig()?.flowchart?.htmlLabels)) {
|
||||||
|
const div = descr.children[0];
|
||||||
|
const dv = select(descr);
|
||||||
|
bbox = div.getBoundingClientRect();
|
||||||
|
dv.attr('width', bbox.width);
|
||||||
|
dv.attr('height', bbox.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
const halfPadding = (node.padding || 0) / 2;
|
||||||
|
select(descr).attr(
|
||||||
|
'transform',
|
||||||
|
'translate( ' +
|
||||||
|
(bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) +
|
||||||
|
', ' +
|
||||||
|
(titleBox.height + halfPadding + 5) +
|
||||||
|
')'
|
||||||
|
);
|
||||||
|
select(text).attr(
|
||||||
|
'transform',
|
||||||
|
'translate( ' +
|
||||||
|
(bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) +
|
||||||
|
', ' +
|
||||||
|
0 +
|
||||||
|
')'
|
||||||
|
);
|
||||||
|
// Get the size of the label
|
||||||
|
|
||||||
|
// Bounding box for title and text
|
||||||
|
bbox = label.node().getBBox();
|
||||||
|
|
||||||
|
// Center the label
|
||||||
|
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 rect;
|
||||||
|
let innerLine;
|
||||||
|
if (node.look === 'handdrawn') {
|
||||||
|
// @ts-ignore No typings for rough
|
||||||
|
const rc = rough.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');
|
||||||
|
rect = shapeSvg.insert(() => {
|
||||||
|
log.debug('Rough node insert CXC', roughNode);
|
||||||
|
return roughNode;
|
||||||
|
}, ':first-child');
|
||||||
|
} else {
|
||||||
|
rect = g.insert('rect', ':first-child');
|
||||||
|
innerLine = g.insert('line');
|
||||||
|
rect
|
||||||
|
.attr('class', 'outer title-state')
|
||||||
|
.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, rect);
|
||||||
|
|
||||||
|
node.intersect = function (point) {
|
||||||
|
return intersect.rect(node, point);
|
||||||
|
};
|
||||||
|
|
||||||
|
return shapeSvg;
|
||||||
|
};
|
||||||
@@ -13,6 +13,7 @@ export type CheckFitFunction = (text: MarkdownLine) => boolean;
|
|||||||
interface Node {
|
interface Node {
|
||||||
id: string;
|
id: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
description?: string[];
|
||||||
parentId?: string;
|
parentId?: string;
|
||||||
position?: string; // Keep, this is for notes 'left of', 'right of', etc. Move into nodeNode
|
position?: string; // Keep, this is for notes 'left of', 'right of', etc. Move into nodeNode
|
||||||
cssStyles?: string; // Renamed from `styles` to `cssStyles`
|
cssStyles?: string; // Renamed from `styles` to `cssStyles`
|
||||||
|
|||||||
Reference in New Issue
Block a user