Merge branch 'neo-new-shapes' of github.com:Mermaid-Chart/alana-mermaid into neo-new-shapes

This commit is contained in:
Knut Sveidqvist
2024-09-20 15:10:43 +02:00
17 changed files with 109 additions and 43 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@mermaid-chart/mermaid",
"version": "11.2.0-b.3",
"version": "11.2.0-b.4",
"description": "Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.",
"type": "module",
"module": "./dist/mermaid.core.mjs",

View File

@@ -161,6 +161,7 @@ export const addVertex = function (
if (!doc.label?.trim() && vertex.text === id) {
vertex.text = '';
}
vertex.constrainedImage = !!doc.constrainedImage;
}
if (doc.w) {
vertex.assetWidth = Number(doc.w);
@@ -900,6 +901,9 @@ const addNodeFromVertex = (
img: vertex.img,
assetWidth: vertex.assetWidth,
assetHeight: vertex.assetHeight,
imageAspectRatio: vertex.imageAspectRatio,
defaultWidth: vertex.defaultWidth,
constrainedImage: vertex.constrainedImage,
});
}
};

View File

@@ -17,6 +17,9 @@ export interface FlowVertex {
img?: string;
assetWidth?: number;
assetHeight?: number;
defaultWidth?: number;
imageAspectRatio?: number;
constrainedImage?: boolean;
}
export interface FlowText {

View File

@@ -55,9 +55,9 @@ export const icon = async (
const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
const outerShape = shapeSvg.insert(() => outerNode);
const iconElem = shapeSvg.append('g');
if (node.icon) {
const iconElem = shapeSvg.append('g');
iconElem.html(
`<g>${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}</g>`
);
@@ -71,6 +71,7 @@ export const icon = async (
`translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - iconY : -outerHeight / 2 - iconY})`
);
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
iconElem.attr('class', 'icon');
}
label.attr(
@@ -83,6 +84,14 @@ export const icon = async (
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
if (stylesMap.get('stroke')) {
iconElem.selectAll('path').attr('style', `fill: ${stylesMap.get('stroke')}`);
}
if (stylesMap.get('fill')) {
iconShape.selectAll('path').attr('style', `stroke: ${stylesMap.get('fill')}`);
}
updateNodeBounds(node, outerShape);
node.intersect = function (point) {

View File

@@ -21,7 +21,7 @@ export const iconCircle = async (
node.width = Math.max(iconSize, defaultWidth ?? 0);
const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'icon-shape default');
const padding = 20;
const padding = node.look === 'neo' ? 30 : 20;
const labelPadding = node.label ? 8 : 0;
const topLabel = node.pos === 't';
@@ -65,19 +65,28 @@ export const iconCircle = async (
const outerShape = shapeSvg.insert(() => outerNode);
iconElem.attr(
'transform',
`translate(${-iconWidth / 2 - iconX},${topLabel ? diameter / 2 - iconHeight - padding + bbox.height / 2 - iconY : -diameter / 2 + padding - bbox.height / 2 - labelPadding / 2 - iconY})`
`translate(${-iconWidth / 2 - iconX},${topLabel ? diameter / 2 - iconHeight - padding + bbox.height / 2 - iconY + labelPadding / 2 : -diameter / 2 + padding - bbox.height / 2 - labelPadding / 2 - iconY})`
);
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
iconElem.attr('class', 'icon');
label.attr(
'transform',
`translate(${-bbox.width / 2},${topLabel ? -diameter / 2 - bbox.height / 2 : diameter / 2 - bbox.height / 2 + labelPadding / 2})`
`translate(${-bbox.width / 2},${topLabel ? -diameter / 2 - bbox.height / 2 - labelPadding / 2 : diameter / 2 - bbox.height / 2 + labelPadding / 2})`
);
iconShape.attr(
'transform',
`translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2 - labelPadding / 2})`
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
if (stylesMap.get('stroke')) {
iconElem.selectAll('path').attr('style', `fill: ${stylesMap.get('stroke')}`);
}
if (stylesMap.get('fill')) {
iconShape.selectAll('path').attr('style', `stroke: ${stylesMap.get('fill')}`);
}
updateNodeBounds(node, outerShape);
node.intersect = function (point) {

View File

@@ -28,8 +28,10 @@ export const iconRounded = async (
const topLabel = node.pos === 't';
const height = iconSize + halfPadding * 2;
const width = iconSize + halfPadding * 2;
const padding = node.look === 'neo' ? halfPadding * 2 : halfPadding;
const height = iconSize + padding * 2;
const width = iconSize + padding * 2;
const { nodeBorder, mainBkg } = themeVariables;
const { stylesMap } = compileStyles(node);
@@ -60,9 +62,9 @@ export const iconRounded = async (
const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
const outerShape = shapeSvg.insert(() => outerNode);
const iconElem = shapeSvg.append('g');
if (node.icon) {
const iconElem = shapeSvg.append('g');
iconElem.html(
`<g>${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}</g>`
);
@@ -73,9 +75,10 @@ export const iconRounded = async (
const iconY = iconBBox.y;
iconElem.attr(
'transform',
`translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - halfPadding - iconY : -outerHeight / 2 + halfPadding - iconY})`
`translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - padding - iconY : -outerHeight / 2 + padding - iconY})`
);
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
iconElem.attr('class', 'icon');
}
label.attr(
@@ -88,6 +91,14 @@ export const iconRounded = async (
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
if (stylesMap.get('stroke')) {
iconElem.selectAll('path').attr('style', `fill: ${stylesMap.get('stroke')}`);
}
if (stylesMap.get('fill')) {
iconShape.selectAll('path').attr('style', `stroke: ${stylesMap.get('fill')}`);
}
updateNodeBounds(node, outerShape);
node.intersect = function (point) {

View File

@@ -27,8 +27,10 @@ export const iconSquare = async (
const topLabel = node.pos === 't';
const height = iconSize + halfPadding * 2;
const width = iconSize + halfPadding * 2;
const padding = node.look === 'neo' ? halfPadding * 2 : halfPadding;
const height = iconSize + padding * 2;
const width = iconSize + padding * 2;
const { nodeBorder, mainBkg } = themeVariables;
const { stylesMap } = compileStyles(node);
@@ -59,9 +61,9 @@ export const iconSquare = async (
const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
const outerShape = shapeSvg.insert(() => outerNode);
const iconElem = shapeSvg.append('g');
if (node.icon) {
const iconElem = shapeSvg.append('g');
iconElem.html(
`<g>${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}</g>`
);
@@ -72,9 +74,10 @@ export const iconSquare = async (
const iconY = iconBBox.y;
iconElem.attr(
'transform',
`translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - halfPadding - iconY : -outerHeight / 2 + halfPadding - iconY})`
`translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - padding - iconY : -outerHeight / 2 + padding - iconY})`
);
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
iconElem.attr('class', 'icon');
}
label.attr(
@@ -87,6 +90,14 @@ export const iconSquare = async (
`translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
);
if (stylesMap.get('stroke')) {
iconElem.selectAll('path').attr('style', `fill: ${stylesMap.get('stroke')}`);
}
if (stylesMap.get('fill')) {
iconShape.selectAll('path').attr('style', `stroke: ${stylesMap.get('fill')}`);
}
updateNodeBounds(node, outerShape);
node.intersect = function (point) {

View File

@@ -17,18 +17,22 @@ export const imageSquare = async (
const imageNaturalWidth = Number(img.naturalWidth.toString().replace('px', ''));
const imageNaturalHeight = Number(img.naturalHeight.toString().replace('px', ''));
node.imageAspectRatio = imageNaturalWidth / imageNaturalHeight;
const { labelStyles } = styles2String(node);
node.labelStyle = labelStyles;
const defaultWidth = flowchart?.wrappingWidth;
node.defaultWidth = flowchart?.wrappingWidth;
const imageWidth = Math.max(
node.label ? (defaultWidth ?? 0) : 0,
node?.assetWidth ?? imageNaturalWidth
);
const imageHeight = node?.assetHeight ?? imageNaturalHeight;
const imageHeight = node.constrainedImage
? imageWidth / node.imageAspectRatio
: (node?.assetHeight ?? imageNaturalHeight);
node.width = Math.max(imageWidth, defaultWidth ?? 0);
const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'image-shape default');

View File

@@ -69,6 +69,9 @@ export interface Node {
img?: string;
assetWidth?: number;
assetHeight?: number;
defaultWidth?: number;
imageAspectRatio?: number;
constrainedImage?: boolean;
}
// Common properties for any edge in the system
@@ -100,6 +103,7 @@ export interface Edge {
pattern?: string;
thickness?: 'normal' | 'thick' | 'invisible' | 'dotted';
look?: string;
showPoints?: boolean;
}
export interface RectOptions {

View File

@@ -2036,7 +2036,7 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file)
description: |
Defines how mermaid renders curves for flowcharts.
type: string
enum: ['basis', 'linear', 'cardinal','rounded']
enum: ['basis', 'linear', 'cardinal', 'rounded']
default: 'rounded'
edgeDebug:
description: |

View File

@@ -115,6 +115,16 @@ const getStyles = (
stroke-width: 1px;
}
[data-look="neo"].icon-shape .icon path {
fill: ${options.useGradient ? 'url(' + svgId + '-gradient)' : options.nodeBorder};
filter: ${options.dropShadow};
}
[data-look="neo"].icon-shape path {
stroke: ${options.useGradient ? 'url(' + svgId + '-gradient)' : options.nodeBorder};
filter: ${options.dropShadow};
}
${userStyles}
`;
};

View File

@@ -10,6 +10,7 @@ export interface NodeMetaData {
img?: string;
w?: string;
h?: string;
constrainedImage?: boolean;
}
export interface Point {