mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-14 21:09:50 +02:00
#1295 Adding support for multiline descriptions for states
This commit is contained in:
@@ -49,20 +49,10 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid" style="width: 50%; height: 20%;">
|
<div class="mermaid" style="width: 50%; height: 20%;">
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
state Active {
|
|
||||||
[*] --> NumLockOff
|
[*] --> S1
|
||||||
NumLockOff --> NumLockOn : EvNumLockPressed
|
state "Some long name" as S1: The description<br/>continues
|
||||||
NumLockOn --> NumLockOff : EvNumLockPressed
|
|
||||||
--
|
|
||||||
[*] --> CapsLockOff
|
|
||||||
CapsLockOff --> CapsLockOn : EvCapsLockPressed
|
|
||||||
CapsLockOn --> CapsLockOff : EvCapsLockPressed
|
|
||||||
--
|
|
||||||
[*] --> ScrollLockOff
|
|
||||||
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
|
|
||||||
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid2 mermaid-apa" style="width: 100%; height: 20%;">
|
<div class="mermaid2 mermaid-apa" style="width: 100%; height: 20%;">
|
||||||
stateDiagram
|
stateDiagram
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
const createLabel = (vertexText, style) => {
|
const createLabel = (vertexText, style, isTitle) => {
|
||||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||||
svgLabel.setAttribute('style', style.replace('color:', 'fill:'));
|
svgLabel.setAttribute('style', style.replace('color:', 'fill:'));
|
||||||
let rows = [];
|
let rows = [];
|
||||||
@@ -11,6 +11,11 @@ const createLabel = (vertexText, style) => {
|
|||||||
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||||
tspan.setAttribute('dy', '1em');
|
tspan.setAttribute('dy', '1em');
|
||||||
tspan.setAttribute('x', '0');
|
tspan.setAttribute('x', '0');
|
||||||
|
if (isTitle) {
|
||||||
|
tspan.setAttribute('class', 'title-row');
|
||||||
|
} else {
|
||||||
|
tspan.setAttribute('class', 'row');
|
||||||
|
}
|
||||||
tspan.textContent = rows[j].trim();
|
tspan.textContent = rows[j].trim();
|
||||||
svgLabel.appendChild(tspan);
|
svgLabel.appendChild(tspan);
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
import intersect from './intersect/index.js';
|
import intersect from './intersect/index.js';
|
||||||
|
import { select } from 'd3';
|
||||||
import { logger } from '../logger'; // eslint-disable-line
|
import { logger } from '../logger'; // eslint-disable-line
|
||||||
import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util';
|
import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util';
|
||||||
|
import createLabel from './createLabel';
|
||||||
import note from './shapes/note';
|
import note from './shapes/note';
|
||||||
|
|
||||||
const question = (parent, node) => {
|
const question = (parent, node) => {
|
||||||
@@ -269,6 +271,76 @@ const rect = (parent, node) => {
|
|||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
};
|
||||||
|
const rectWithTitle = (parent, node) => {
|
||||||
|
// const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes);
|
||||||
|
|
||||||
|
let classes;
|
||||||
|
if (!node.classes) {
|
||||||
|
classes = 'node default';
|
||||||
|
} else {
|
||||||
|
classes = 'node ' + node.classes;
|
||||||
|
}
|
||||||
|
// Add outer g element
|
||||||
|
const shapeSvg = parent
|
||||||
|
.insert('g')
|
||||||
|
.attr('class', classes)
|
||||||
|
.attr('id', node.id);
|
||||||
|
|
||||||
|
// Create the title label and insert it after the rect
|
||||||
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
// const innerRect = shapeSvg.insert('rect');
|
||||||
|
const innerLine = shapeSvg.insert('line');
|
||||||
|
|
||||||
|
const label = shapeSvg.insert('g').attr('class', 'label');
|
||||||
|
|
||||||
|
const text = label.node().appendChild(createLabel(node.labelText[0], node.labelStyle, true));
|
||||||
|
const textRows = node.labelText.slice(1, node.labelText.length);
|
||||||
|
let titleBox = text.getBBox();
|
||||||
|
const descr = label
|
||||||
|
.node()
|
||||||
|
.appendChild(createLabel(textRows.join('<br/>'), node.labelStyle, true));
|
||||||
|
|
||||||
|
logger.info(descr);
|
||||||
|
const halfPadding = node.padding / 2;
|
||||||
|
select(descr).attr('transform', 'translate( 0' + ', ' + (titleBox.height + halfPadding) + ')');
|
||||||
|
// Get the size of the label
|
||||||
|
|
||||||
|
// Bounding box for title and text
|
||||||
|
const bbox = label.node().getBBox();
|
||||||
|
|
||||||
|
// Center the label
|
||||||
|
label.attr(
|
||||||
|
'transform',
|
||||||
|
'translate(' + -bbox.width / 2 + ', ' + (-bbox.height / 2 - halfPadding + 3) + ')'
|
||||||
|
);
|
||||||
|
|
||||||
|
rect
|
||||||
|
.attr('class', 'outer title-state')
|
||||||
|
.attr('x', -bbox.width / 2 - halfPadding)
|
||||||
|
.attr('y', -bbox.height / 2 - halfPadding)
|
||||||
|
.attr('width', bbox.width + node.padding)
|
||||||
|
.attr('height', bbox.height + node.padding);
|
||||||
|
// innerRect
|
||||||
|
// .attr('class', 'inner')
|
||||||
|
// .attr('x', -bbox.width / 2 - halfPadding)
|
||||||
|
// .attr('y', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding)
|
||||||
|
// .attr('width', bbox.width + node.padding)
|
||||||
|
// .attr('height', bbox.height + node.padding - titleBox.height - halfPadding);
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
const stadium = (parent, node) => {
|
const stadium = (parent, node) => {
|
||||||
const { shapeSvg, bbox } = labelHelper(parent, node);
|
const { shapeSvg, bbox } = labelHelper(parent, node);
|
||||||
@@ -368,6 +440,7 @@ const end = (parent, node) => {
|
|||||||
const shapes = {
|
const shapes = {
|
||||||
question,
|
question,
|
||||||
rect,
|
rect,
|
||||||
|
rectWithTitle,
|
||||||
circle,
|
circle,
|
||||||
stadium,
|
stadium,
|
||||||
hexagon,
|
hexagon,
|
||||||
|
@@ -54,7 +54,12 @@ const setupNode = (g, parent, node, altFlag) => {
|
|||||||
|
|
||||||
// Description
|
// Description
|
||||||
if (node.description) {
|
if (node.description) {
|
||||||
nodeDb[node.id].description = node.description;
|
if (Array.isArray(node.description)) {
|
||||||
|
nodeDb[node.id].shape = 'rectWithTitle';
|
||||||
|
nodeDb[node.id].description = node.description;
|
||||||
|
} else {
|
||||||
|
nodeDb[node.id].description = node.description;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save data for description and group so that for instance a statement without description overwrites
|
// Save data for description and group so that for instance a statement without description overwrites
|
||||||
|
@@ -90,6 +90,14 @@ g.stateGroup line {
|
|||||||
rx: 5px;
|
rx: 5px;
|
||||||
ry: 5px;
|
ry: 5px;
|
||||||
}
|
}
|
||||||
|
.statediagram-state .divider {
|
||||||
|
stroke: $nodeBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statediagram-state .title-state {
|
||||||
|
rx: 5px;
|
||||||
|
ry: 5px;
|
||||||
|
}
|
||||||
.statediagram-cluster.statediagram-cluster .inner {
|
.statediagram-cluster.statediagram-cluster .inner {
|
||||||
fill: white;
|
fill: white;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user