mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
5237 Adding rectWith title shape
This commit is contained in:
parent
94512c0780
commit
e2e652ae0f
@ -231,6 +231,15 @@ const extract = (_doc) => {
|
||||
const look = config.look;
|
||||
resetDataFetching();
|
||||
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 { note } from './shapes/note.ts';
|
||||
import { stadium } from './shapes/stadium.js';
|
||||
import { rectWithTitle } from './shapes/rectWithTitle.js';
|
||||
import { getConfig } from '$root/diagram-api/diagramAPI.js';
|
||||
import { subroutine } from './shapes/subroutine.js';
|
||||
import { cylinder } from './shapes/cylinder.js';
|
||||
@ -36,7 +37,7 @@ const shapes = {
|
||||
choice,
|
||||
note,
|
||||
roundedRect,
|
||||
rectWithTitle: roundedRect,
|
||||
rectWithTitle,
|
||||
squareRect,
|
||||
stadium,
|
||||
subroutine,
|
||||
@ -58,6 +59,8 @@ export const insertNode = async (elem, node, dir) => {
|
||||
let newEl;
|
||||
let el;
|
||||
|
||||
console.log('node DDD', node);
|
||||
|
||||
//special check for rect shape (with or without rounded corners)
|
||||
if (node.shape === 'rect') {
|
||||
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 {
|
||||
id: string;
|
||||
label?: string;
|
||||
description?: string[];
|
||||
parentId?: string;
|
||||
position?: string; // Keep, this is for notes 'left of', 'right of', etc. Move into nodeNode
|
||||
cssStyles?: string; // Renamed from `styles` to `cssStyles`
|
||||
|
Loading…
x
Reference in New Issue
Block a user