diff --git a/cypress/platform/per.html b/cypress/platform/per.html index e84cea2d0..e6a88642a 100644 --- a/cypress/platform/per.html +++ b/cypress/platform/per.html @@ -4,16 +4,35 @@ + + + + + + + -
Security check
-
-flowchart LR
-A-->B
-        
-            mindmap
-          root
-            ch1
-            ch2
-        
Active + + state Active { + direction BT + [*] --> Inner + Inner --> NumLockOn : EvNumLockPressed + } + %% Outer --> Inner + - - - - diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 4749d7c70..88897345f 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -68,7 +68,7 @@ export interface MermaidConfig { * Defines which main look to use for the diagram. * */ - look?: 'classic' | 'handdrawn' | 'slick'; + look?: 'classic' | 'handdrawn' | 'neo'; /** * Defines the seed to be used when using handdrawn look. This is important for the automated tests as they will always find differences without the seed. The default value is 0 which gives a random seed. * diff --git a/packages/mermaid/src/dagre-wrapper/edgeMarker.ts b/packages/mermaid/src/dagre-wrapper/edgeMarker.ts index 778a7708d..fdd19dc72 100644 --- a/packages/mermaid/src/dagre-wrapper/edgeMarker.ts +++ b/packages/mermaid/src/dagre-wrapper/edgeMarker.ts @@ -29,6 +29,7 @@ const arrowTypesMap = { arrow_cross: 'cross', arrow_point: 'point', arrow_barb: 'barb', + arrow_neo: 'barbNeo', arrow_circle: 'circle', aggregation: 'aggregation', extension: 'extension', diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index b2c38efe8..8bb3d0778 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -775,12 +775,12 @@ const addNodeFromVertex = ( parentDB: Map, subGraphDB: Map, config: any, - useRough: boolean + look: string ): Node => { - let parentId = parentDB.get(vertex.id); - let isGroup = subGraphDB.get(vertex.id) || false; + const parentId = parentDB.get(vertex.id); + const isGroup = subGraphDB.get(vertex.id) || false; - let node = findNode(nodes, vertex.id); + const node = findNode(nodes, vertex.id); if (!node) { nodes.push({ id: vertex.id, @@ -795,7 +795,7 @@ const addNodeFromVertex = ( domId: vertex.domId, type: isGroup ? 'group' : undefined, isGroup, - useRough, + look, }); } }; @@ -807,7 +807,6 @@ export const getData = () => { // extract(getRootDocV2()); // const diagramStates = getStates(); - const useRough = config.look === 'handdrawn'; const subGraphs = getSubGraphs(); log.info('Subgraphs - APA12', subGraphs); const parentDB = new Map(); @@ -834,14 +833,14 @@ export const getData = () => { domId: subGraph.domId, type: 'group', isGroup: true, - useRough, + look: config.look, }); } console.log('APA12 nodes - 1', nodes.length); const n = getVertices(); n.forEach((vertex) => { - const node = addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, useRough); + const node = addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, config.look); if (node) { nodes.push(node); } @@ -874,14 +873,12 @@ export const getData = () => { // domId: verawEdgertex.domId, // rawEdge: undefined, // isGroup: false, - useRough, + look: config.look, }; // console.log('rawEdge SPLIT', rawEdge, index); edges.push(edge); }); - //const useRough = config.look === 'handdrawn'; - return { nodes, edges, other: {}, config }; }; diff --git a/packages/mermaid/src/diagrams/state/dataFetcher.js b/packages/mermaid/src/diagrams/state/dataFetcher.js index 3bdf1abe0..6e4738038 100644 --- a/packages/mermaid/src/diagrams/state/dataFetcher.js +++ b/packages/mermaid/src/diagrams/state/dataFetcher.js @@ -54,39 +54,23 @@ export function stateDomId(itemId = '', counter = 0, type = '', typeSpacer = DOM return `${DOMID_STATE}-${itemId}${typeStr}-${counter}`; } -const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, useRough, look) => { +const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, look) => { // graphItemCount = 0; log.trace('items', doc); doc.forEach((item) => { switch (item.stmt) { case STMT_STATE: - dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough, look); + dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, look); + break; case DEFAULT_STATE_TYPE: - dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough, look); + dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, look); + break; case STMT_RELATION: { - dataFetcher( - parentParsedItem, - item.state1, - diagramStates, - nodes, - edges, - altFlag, - useRough, - look - ); - dataFetcher( - parentParsedItem, - item.state2, - diagramStates, - nodes, - edges, - altFlag, - useRough, - look - ); + dataFetcher(parentParsedItem, item.state1, diagramStates, nodes, edges, altFlag, look); + dataFetcher(parentParsedItem, item.state2, diagramStates, nodes, edges, altFlag, look); const edgeData = { id: 'edge' + graphItemCount, start: item.state1.id, @@ -101,7 +85,6 @@ const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, u labelType: G_EDGE_LABELTYPE, thickness: G_EDGE_THICKNESS, classes: CSS_EDGE, - useRough, look, }; edges.push(edgeData); @@ -225,16 +208,7 @@ function getClassesFromDbInfo(dbInfoItem) { } } } -export const dataFetcher = ( - parent, - parsedItem, - diagramStates, - nodes, - edges, - altFlag, - useRough, - look -) => { +export const dataFetcher = (parent, parsedItem, diagramStates, nodes, edges, altFlag, look) => { const itemId = parsedItem.id; const classStr = getClassesFromDbInfo(diagramStates.get(itemId)); @@ -324,7 +298,6 @@ export const dataFetcher = ( padding: 8, rx: 10, ry: 10, - useRough, look, }; @@ -354,7 +327,6 @@ export const dataFetcher = ( type: newNode.type, isGroup: newNode.type === 'group', padding: 0, //getConfig().flowchart.padding - useRough, look, position: parsedItem.note.position, }; @@ -369,7 +341,6 @@ export const dataFetcher = ( type: 'group', isGroup: true, padding: 16, //getConfig().flowchart.padding - useRough, look, position: parsedItem.note.position, }; @@ -410,7 +381,6 @@ export const dataFetcher = ( labelpos: G_EDGE_LABELPOS, labelType: G_EDGE_LABELTYPE, thickness: G_EDGE_THICKNESS, - useRough, look, }); } else { @@ -419,7 +389,7 @@ export const dataFetcher = ( } if (parsedItem.doc) { log.trace('Adding nodes children '); - setupDoc(parsedItem, parsedItem.doc, diagramStates, nodes, edges, !altFlag, useRough, look); + setupDoc(parsedItem, parsedItem.doc, diagramStates, nodes, edges, !altFlag, look); } }; diff --git a/packages/mermaid/src/diagrams/state/stateDb.js b/packages/mermaid/src/diagrams/state/stateDb.js index f6bddf0ea..2d8ae7c3e 100644 --- a/packages/mermaid/src/diagrams/state/stateDb.js +++ b/packages/mermaid/src/diagrams/state/stateDb.js @@ -581,10 +581,10 @@ export const getData = () => { // } const diagramStates = getStates(); const config = getConfig(); - const useRough = config.look === 'handdrawn'; const look = config.look; resetDataFetching(); - dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, useRough, look); + dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look); + return { nodes, edges, other: {}, config }; }; diff --git a/packages/mermaid/src/diagrams/state/stateRenderer-v2.js b/packages/mermaid/src/diagrams/state/stateRenderer-v2.js index 0ecc0a73a..02ee6b2d2 100644 --- a/packages/mermaid/src/diagrams/state/stateRenderer-v2.js +++ b/packages/mermaid/src/diagrams/state/stateRenderer-v2.js @@ -333,7 +333,7 @@ const setupDoc = (g, parentParsedItem, doc, diagramStates, diagramDb, altFlag) = counter: graphItemCount, }), arrowhead: 'normal', - arrowTypeEnd: 'arrow_barb', + arrowTypeEnd: 'arrow_neo', style: G_EDGE_STYLE, labelStyle: '', label: common.sanitizeText(item.description, getConfig()), diff --git a/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts b/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts index d3b13473a..a0b9f92ef 100644 --- a/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts +++ b/packages/mermaid/src/diagrams/state/stateRenderer-v3-unified.ts @@ -79,7 +79,12 @@ export const draw = async function ( data4Layout.nodeSpacing = conf?.nodeSpacing || 50; // @ts-expect-error TODO: Will be fixed after config refactor data4Layout.rankSpacing = conf?.rankSpacing || 50; - data4Layout.markers = ['barb']; + const config = getConfig(); + if (config.look === 'neo') { + data4Layout.markers = ['barbNeo']; + } else { + data4Layout.markers = ['barb']; + } data4Layout.diagramId = id; // console.log('REF1:', data4Layout); await render(data4Layout, svg, element, positions); diff --git a/packages/mermaid/src/diagrams/state/styles.js b/packages/mermaid/src/diagrams/state/styles.js index fe3d7078b..16f769506 100644 --- a/packages/mermaid/src/diagrams/state/styles.js +++ b/packages/mermaid/src/diagrams/state/styles.js @@ -127,22 +127,23 @@ g.stateGroup line { } .statediagram-cluster rect.outer { - rx: 5px; - ry: 5px; + rx: ${options.radius}px; + ry: ${options.radius}px; } .statediagram-state .divider { stroke: ${options.stateBorder || options.nodeBorder}; } .statediagram-state .title-state { - rx: 5px; - ry: 5px; + rx: ${options.radius}px; + ry: ${options.radius}px; } .statediagram-cluster.statediagram-cluster .inner { fill: ${options.compositeBackground || options.background}; } .statediagram-cluster.statediagram-cluster-alt .inner { fill: ${options.altBackground ? options.altBackground : '#efefef'}; + } .statediagram-cluster .inner { @@ -151,9 +152,16 @@ g.stateGroup line { } .statediagram-state rect.basic { - rx: 5px; - ry: 5px; + rx: ${options.radius}px; + ry: ${options.radius}px; } + + +.state-shadow-neo { + filter: drop-shadow( 1px 2px 2px rgba(185,185,185,1.0) ); +} + + .statediagram-state rect.divider { stroke-dasharray: 10,10; fill: ${options.altBackground ? options.altBackground : '#efefef'}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 29fbc886e..0c96868a7 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -10,12 +10,16 @@ import createLabel from './createLabel.js'; import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; +// Helper function to calculate the offset correction for the label +const calcLabelOffsetCorrection = (diff) => { + return diff * 0.75 - 6; +}; + const rect = (parent, node) => { log.info('Creating subgraph rect for ', node.id, node); const siteConfig = getConfig(); const { themeVariables, handdrawnSeed } = siteConfig; const { clusterBkg, clusterBorder } = themeVariables; - let { useRough } = node; // Add outer g element const shapeSvg = parent.insert('g').attr('class', 'cluster').attr('id', node.id); @@ -60,7 +64,7 @@ const rect = (parent, node) => { log.trace('Data ', node, JSON.stringify(node)); let rect; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, { @@ -215,10 +219,10 @@ const roundedWithTitle = (parent, node) => { const innerY = node.y - node.height / 2 - halfPadding + bbox.height - 1; const height = node.height + padding; const innerHeight = node.height + padding - bbox.height - 3; - + const look = siteConfig.look; // add the rect let rect; - if (node.useRough) { + if (node.look === 'handdrawn') { const isAlt = node.cssClasses.includes('statediagram-cluster-alt'); const rc = rough.svg(shapeSvg); const roughOuterNode = @@ -244,9 +248,16 @@ const roundedWithTitle = (parent, node) => { innerRect = shapeSvg.insert(() => roughInnerNode); } else { rect = outerRectG.insert('rect', ':first-child'); + let outerRectClass = 'outer'; + if (look === 'neo') { + outerRectClass = 'outer state-shadow-neo'; + } else { + outerRectClass = 'outer'; + } + // center the rect around its coordinate rect - .attr('class', 'outer') + .attr('class', outerRectClass) .attr('x', x) .attr('y', y) .attr('width', width) @@ -259,16 +270,12 @@ const roundedWithTitle = (parent, node) => { .attr('height', innerHeight); } - // Center the label + let diff = bbox.height - (innerY - y) / 2; + let correction = calcLabelOffsetCorrection(diff, bbox.height); + label.attr( 'transform', - `translate(${node.x - bbox.width / 2}, ${ - node.y - - node.height / 2 - - node.padding + - bbox.height / 2 - - (evaluate(siteConfig.flowchart.htmlLabels) ? 5 : 3) - })` + `translate(${node.x - bbox.width / 2}, ${(innerY - y) / 2 - correction})` ); const rectBox = rect.node().getBBox(); @@ -300,7 +307,7 @@ const divider = (parent, node) => { const y = node.y - node.height / 2; const width = node.width + padding; const height = node.height + padding; - if (node.useRough) { + if (node.look === 'handdrawn') { const rc = rough.svg(shapeSvg); const roughNode = rc.rectangle(x, y, width, height, { fill: 'lightgrey', diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index c8e9a948a..68bb061ec 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -594,11 +594,10 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod default: strokeClasses += ' edge-pattern-solid'; } - let useRough = edge.useRough; let svgPath; let path = ''; let linePath = lineFunction(lineData); - if (useRough) { + if (edge.look === 'handdrawn') { const rc = rough.svg(elem); const ld = Object.assign([], lineData); // const svgPathNode = rc.path(lineFunction(ld.splice(0, ld.length-1)), { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/markers.js b/packages/mermaid/src/rendering-util/rendering-elements/markers.js index 00d45e47d..42c0536da 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/markers.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/markers.js @@ -277,6 +277,20 @@ const barb = (elem, type, id) => { .append('path') .attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z'); }; +const barbNeo = (elem, type, id) => { + elem + .append('defs') + .append('marker') + .attr('id', id + '_' + type + '-barbEnd') + .attr('refX', 19) + .attr('refY', 7) + .attr('markerWidth', 20) + .attr('markerHeight', 14) + .attr('markerUnits', 'strokeWidth') + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 19,7 L11,14 L13,7 L11,0 Z'); +}; // TODO rename the class diagram markers to something shape descriptive and semantic free const markers = { @@ -289,5 +303,6 @@ const markers = { circle, cross, barb, + barbNeo, }; export default insertMarkers; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts index 8248f3ddd..809b543ed 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts @@ -22,7 +22,7 @@ export const choice = (parent: SVG, node: Node) => { ]; let choice; - if (node.useRough) { + if (node.look === 'handdrawn') { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); const pointArr = points.map(function (d) { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts index 48054cce3..1b3fdf47a 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts @@ -15,9 +15,9 @@ export const circle = async (parent: SVGAElement, node: Node): Promise { const h = bbox.height + ry + node.padding; let cylinder: d3.Selection; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts index d3bda9c86..8cbbe75ff 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts @@ -18,9 +18,9 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise { + const { themeVariables, handdrawnSeed, look } = getConfig(); + const { nodeBorder, mainBkg } = themeVariables; + const { shapeSvg, bbox, halfPadding } = await labelHelper( parent, node, @@ -14,21 +17,22 @@ export const drawRect = async (parent: SVGAElement, node: Node, options: RectOpt true ); - const totalWidth = Math.max(bbox.width + node.padding, node?.width || 0); - const totalHeight = Math.max(bbox.height + node.padding, node?.height || 0); + const totalWidth = Math.max(bbox.width + options.labelPaddingX * 2, node?.width || 0); + const totalHeight = Math.max(bbox.height + options.labelPaddingY * 2, node?.height || 0); const x = -totalWidth / 2; const y = -totalHeight / 2; let rect; - let { rx, ry, cssStyles, useRough } = node; + node.look = look; + let { rx, ry } = node; + const { cssStyles } = node; //use options rx, ry overrides if present if (options && options.rx && options.ry) { rx = options.rx; ry = options.ry; } - - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); @@ -40,6 +44,21 @@ export const drawRect = async (parent: SVGAElement, node: Node, options: RectOpt rect = shapeSvg.insert(() => roughNode, ':first-child'); rect.attr('class', 'basic label-container').attr('style', cssStyles); + } else if (node.look === 'neo') { + // TODO: Take theme and look into account + rect = shapeSvg.insert('rect', ':first-child'); + + rect + .attr('class', 'basic label-container state-shadow-neo') + .attr('style', cssStyles) + .attr('rx', rx) + .attr('data-id', 'abc') + .attr('data-et', 'node') + .attr('ry', ry) + .attr('x', x) + .attr('y', y) + .attr('width', totalWidth) + .attr('height', totalHeight); } else { rect = shapeSvg.insert('rect', ':first-child'); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts index 8ec8ab50c..309be032b 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts @@ -25,7 +25,7 @@ export const forkJoin = (parent: SVG, node: Node, dir: string) => { const y = (-1 * height) / 2; let shape; - if (node.useRough) { + if (node.look === 'handdrawn') { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); const roughNode = rc.rectangle(x, y, width, height, solidStateFill(lineColor)); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts index 0678e6013..2a05ac4cf 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts @@ -56,9 +56,9 @@ export const hexagon = async (parent: SVGAElement, node: Node): Promise; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts index 2f5e2796d..e6a547f20 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts @@ -43,9 +43,9 @@ export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts index dad213357..81a317e88 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts @@ -42,9 +42,9 @@ export const lean_left = async (parent: SVGAElement, node: Node): Promise; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts index c1dfbdbac..bb49621f6 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts @@ -42,9 +42,9 @@ export const lean_right = async (parent: SVGAElement, node: Node): Promise; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts index 5843f558b..79c7129a1 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts @@ -21,14 +21,14 @@ export const note = async (parent: SVGAElement, node: Node) => { ); log.info('Classes = ', node.cssClasses); - const { cssStyles, useRough } = node; + const { cssStyles } = node; let rect; const totalWidth = bbox.width + node.padding; const totalHeight = bbox.height + node.padding; const x = -bbox.width / 2 - halfPadding; const y = -bbox.height / 2 - halfPadding; - if (useRough) { + if (node.look === 'handdrawn') { // add the rect // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts index c72e567cf..274ccc398 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts @@ -38,9 +38,9 @@ export const question = async (parent: SVGAElement, node: Node): Promise; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts index c73e00b37..b7b8fafa7 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts @@ -42,9 +42,9 @@ export const rect_left_inv_arrow = async ( ]; let polygon; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts index 636116132..5229b606c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts @@ -1,10 +1,16 @@ import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; import { drawRect } from './drawRect.js'; +import { getConfig } from '$root/diagram-api/diagramAPI.js'; export const roundedRect = async (parent: SVGAElement, node: Node) => { + const { look } = getConfig(); + node.look = look; const options = { - rx: 5, - ry: 5, + rx: node.look === 'neo' ? 1 : 5, + ry: node.look === 'neo' ? 1 : 5, + + labelPaddingX: node.padding * 2, + labelPaddingY: node.padding * 1, classes: '', } as RectOptions; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts index 102e49069..e1155082c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts @@ -58,8 +58,8 @@ export const stadium = async (parent: SVGAElement, node: Node) => { const w = bbox.width + h / 4 + node.padding; let rect; - const { cssStyles, useRough } = node; - if (useRough) { + const { cssStyles } = node; + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts index 73d119045..f1bc733d6 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts @@ -1,10 +1,14 @@ import type { Node } from '$root/rendering-util/types.d.ts'; import { drawRect } from './drawRect.js'; +import { getConfig } from '$root/diagram-api/diagramAPI.js'; export const state = async (parent: SVGAElement, node: Node) => { + const { look } = getConfig(); + node.look = look; + const options = { - rx: 5, - ry: 5, + rx: node.look === 'neo' ? 2 : 5, + ry: node.look === 'neo' ? 2 : 5, classes: 'flowchart-node', }; return drawRect(parent, node, options); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts index 5f93d7a41..4d4d21d86 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts @@ -17,7 +17,7 @@ export const stateEnd = (parent: SVG, node: Node) => { let circle; let innerCircle; - if (node.useRough) { + if (node.look === 'handdrawn') { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); const roughNode = rc.circle(0, 0, 14, { ...solidStateFill(lineColor), roughness: 0.5 }); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts index c045266fd..575e7d2b0 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts @@ -17,7 +17,7 @@ export const stateStart = (parent: SVG, node: Node) => { .attr('id', node.domId || node.id); let circle; - if (node.useRough) { + if (node.look === 'handdrawn') { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); const roughNode = rc.circle(0, 0, 14, solidStateFill(lineColor)); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts index 4046cfcc9..0bdf0e019 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts @@ -40,7 +40,7 @@ export const subroutine = async (parent: SVGAElement, node: Node) => { const x = -bbox.width / 2 - halfPadding; const y = -bbox.height / 2 - halfPadding; let rect; - const { cssStyles, useRough } = node; + const { cssStyles } = node; const points = [ { x: 0, y: 0 }, { x: w, y: 0 }, @@ -54,7 +54,7 @@ export const subroutine = async (parent: SVGAElement, node: Node) => { { x: -8, y: 0 }, ]; - if (useRough) { + if (node.look === 'handdrawn') { // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts index 1a6a2d1c2..61cc030ad 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts @@ -42,10 +42,10 @@ export const trapezoid = async (parent: SVGAElement, node: Node): Promise; - const { cssStyles, useRough } = node; + const { cssStyles } = node; - if (useRough) { - console.log('Trapezoid: Inside use useRough'); + if (node.look === 'handdrawn') { + console.log('Trapezoid: Inside use handdrawn'); // @ts-ignore const rc = rough.svg(shapeSvg); const options = userNodeOverrides(node, {}); diff --git a/packages/mermaid/src/rendering-util/types.d.ts b/packages/mermaid/src/rendering-util/types.d.ts index d8d127c42..949928a82 100644 --- a/packages/mermaid/src/rendering-util/types.d.ts +++ b/packages/mermaid/src/rendering-util/types.d.ts @@ -46,7 +46,6 @@ interface Node { rx?: number; // Used for rounded corners in Rect, Ellipse, etc.Maybe it to specialized RectNode, EllipseNode, etc. ry?: number; - useRough?: boolean; useHtmlLabels?: boolean; centerLabel?: boolean; //keep for now. //Candidate for removal, maybe rely on labelStyle or a specific property labelPosition: Top, Center, Bottom @@ -61,6 +60,9 @@ interface Node { // Flowchart specific properties x?: number; y?: number; + + // Added look to handle + look?: string; } // Common properties for any edge in the system @@ -91,12 +93,15 @@ interface Edge { minlen?: number; pattern?: string; thickness?: 'normal' | 'thick' | 'invisible'; - useRough?: boolean; + + look?: string; } interface RectOptions { rx: number; ry: number; + labelPaddingX: number; + labelPaddingY: number; classes: string; } diff --git a/packages/mermaid/src/styles.ts b/packages/mermaid/src/styles.ts index fde079450..d106971ad 100644 --- a/packages/mermaid/src/styles.ts +++ b/packages/mermaid/src/styles.ts @@ -69,7 +69,9 @@ const getStyles = ( } ${diagramStyles} - + .node .neo-node { + stroke: ${options.nodeBorder}; + } ${userStyles} `; }; diff --git a/packages/mermaid/src/themes/index.js b/packages/mermaid/src/themes/index.js index 6ffe6274d..979d83bfa 100644 --- a/packages/mermaid/src/themes/index.js +++ b/packages/mermaid/src/themes/index.js @@ -3,6 +3,7 @@ import { getThemeVariables as darkThemeVariables } from './theme-dark.js'; import { getThemeVariables as defaultThemeVariables } from './theme-default.js'; import { getThemeVariables as forestThemeVariables } from './theme-forest.js'; import { getThemeVariables as neutralThemeVariables } from './theme-neutral.js'; +import { getThemeVariables as neoThemeVariables } from './theme-neo.js'; export default { base: { @@ -20,4 +21,7 @@ export default { neutral: { getThemeVariables: neutralThemeVariables, }, + neo: { + getThemeVariables: neoThemeVariables, + }, }; diff --git a/packages/mermaid/src/themes/theme-base.js b/packages/mermaid/src/themes/theme-base.js index dde3b9ecf..f06ab80b1 100644 --- a/packages/mermaid/src/themes/theme-base.js +++ b/packages/mermaid/src/themes/theme-base.js @@ -20,7 +20,7 @@ class Theme { this.noteTextColor = '#333'; this.THEME_COLOR_LIMIT = 12; - + this.radius = 5; // dark this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; diff --git a/packages/mermaid/src/themes/theme-dark.js b/packages/mermaid/src/themes/theme-dark.js index 24ba128b5..e06de0453 100644 --- a/packages/mermaid/src/themes/theme-dark.js +++ b/packages/mermaid/src/themes/theme-dark.js @@ -29,6 +29,7 @@ class Theme { this.labelBackground = '#181818'; this.textColor = '#ccc'; this.THEME_COLOR_LIMIT = 12; + this.radius = 5; /* Flowchart variables */ this.nodeBkg = 'calculated'; diff --git a/packages/mermaid/src/themes/theme-default.js b/packages/mermaid/src/themes/theme-default.js index d95ccf59e..858a6ad41 100644 --- a/packages/mermaid/src/themes/theme-default.js +++ b/packages/mermaid/src/themes/theme-default.js @@ -37,6 +37,7 @@ class Theme { this.labelBackground = '#e8e8e8'; this.textColor = '#333'; this.THEME_COLOR_LIMIT = 12; + this.radius = 5; /* Flowchart variables */ diff --git a/packages/mermaid/src/themes/theme-forest.js b/packages/mermaid/src/themes/theme-forest.js index 4bb7d2441..0e85c6f2c 100644 --- a/packages/mermaid/src/themes/theme-forest.js +++ b/packages/mermaid/src/themes/theme-forest.js @@ -31,6 +31,7 @@ class Theme { this.lineColor = invert(this.background); this.textColor = invert(this.background); this.THEME_COLOR_LIMIT = 12; + this.radius = 5; /* Flowchart variables */ this.nodeBkg = 'calculated'; diff --git a/packages/mermaid/src/themes/theme-neo.js b/packages/mermaid/src/themes/theme-neo.js new file mode 100644 index 000000000..01b8aaf5c --- /dev/null +++ b/packages/mermaid/src/themes/theme-neo.js @@ -0,0 +1,373 @@ +import { darken, lighten, adjust, invert, isDark, toRgba } from 'khroma'; +import { mkBorder } from './theme-helpers.js'; +import { + oldAttributeBackgroundColorEven, + oldAttributeBackgroundColorOdd, +} from './erDiagram-oldHardcodedValues.js'; + +class Theme { + constructor() { + /** # Base variables */ + /** + * - Background - used to know what the background color is of the diagram. This is used for + * deducing colors for instance line color. Default value is #f4f4f4. + */ + this.background = '#ffffff'; + + this.primaryColor = '#cccccc'; + //this.mainBkg = '#ffffff'; + this.mainBkg = '#ecedfe'; + + this.noteBkgColor = '#fff5ad'; + this.noteTextColor = '#333'; + + this.THEME_COLOR_LIMIT = 12; + this.radius = 3; + // dark + + this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; + this.fontSize = '10px'; + + // Neo-specific + this.nodeBorder = 'none'; + this.stateBorder = 'none'; + } + updateColors() { + // The || is to make sure that if the variable has been defined by a user override that value is to be used + + /* Main */ + this.primaryTextColor = this.primaryTextColor || (this.darkMode ? '#eee' : '#333'); // invert(this.primaryColor); + this.secondaryColor = this.secondaryColor || adjust(this.primaryColor, { h: -120 }); + this.tertiaryColor = this.tertiaryColor || adjust(this.primaryColor, { h: 180, l: 5 }); + + this.primaryBorderColor = this.primaryBorderColor || mkBorder(this.primaryColor, this.darkMode); + this.secondaryBorderColor = + this.secondaryBorderColor || mkBorder(this.secondaryColor, this.darkMode); + this.tertiaryBorderColor = + this.tertiaryBorderColor || mkBorder(this.tertiaryColor, this.darkMode); + this.noteBorderColor = this.noteBorderColor || mkBorder(this.noteBkgColor, this.darkMode); + this.noteBkgColor = this.noteBkgColor || '#fff5ad'; + this.noteTextColor = this.noteTextColor || '#333'; + + this.secondaryTextColor = this.secondaryTextColor || invert(this.secondaryColor); + this.tertiaryTextColor = this.tertiaryTextColor || invert(this.tertiaryColor); + this.lineColor = this.lineColor || invert(this.background); + this.arrowheadColor = this.arrowheadColor || invert(this.background); + this.textColor = this.textColor || this.primaryTextColor; + + // TODO: should this instead default to secondaryBorderColor? + this.border2 = this.border2 || this.tertiaryBorderColor; + + /* Flowchart variables */ + this.nodeBkg = this.nodeBkg || this.primaryColor; + this.mainBkg = this.mainBkg || this.primaryColor; + this.nodeBorder = this.nodeBorder || this.primaryBorderColor; + this.clusterBkg = this.clusterBkg || this.tertiaryColor; + this.clusterBorder = this.clusterBorder || this.tertiaryBorderColor; + this.defaultLinkColor = this.defaultLinkColor || this.lineColor; + this.titleColor = this.titleColor || this.tertiaryTextColor; + this.edgeLabelBackground = + this.edgeLabelBackground || + (this.darkMode ? darken(this.secondaryColor, 30) : this.secondaryColor); + this.nodeTextColor = this.nodeTextColor || this.primaryTextColor; + /* Sequence Diagram variables */ + + // this.actorBorder = lighten(this.border1, 0.5); + this.actorBorder = this.actorBorder || this.primaryBorderColor; + this.actorBkg = this.actorBkg || this.mainBkg; + this.actorTextColor = this.actorTextColor || this.primaryTextColor; + this.actorLineColor = this.actorLineColor || this.actorBorder; + this.labelBoxBkgColor = this.labelBoxBkgColor || this.actorBkg; + this.signalColor = this.signalColor || this.textColor; + this.signalTextColor = this.signalTextColor || this.textColor; + this.labelBoxBorderColor = this.labelBoxBorderColor || this.actorBorder; + this.labelTextColor = this.labelTextColor || this.actorTextColor; + this.loopTextColor = this.loopTextColor || this.actorTextColor; + this.activationBorderColor = this.activationBorderColor || darken(this.secondaryColor, 10); + this.activationBkgColor = this.activationBkgColor || this.secondaryColor; + this.sequenceNumberColor = this.sequenceNumberColor || invert(this.lineColor); + + /* Gantt chart variables */ + + this.sectionBkgColor = this.sectionBkgColor || this.tertiaryColor; + this.altSectionBkgColor = this.altSectionBkgColor || 'white'; + this.sectionBkgColor = this.sectionBkgColor || this.secondaryColor; + this.sectionBkgColor2 = this.sectionBkgColor2 || this.primaryColor; + this.excludeBkgColor = this.excludeBkgColor || '#eeeeee'; + this.taskBorderColor = this.taskBorderColor || this.primaryBorderColor; + this.taskBkgColor = this.taskBkgColor || this.primaryColor; + this.activeTaskBorderColor = this.activeTaskBorderColor || this.primaryColor; + this.activeTaskBkgColor = this.activeTaskBkgColor || lighten(this.primaryColor, 23); + this.gridColor = this.gridColor || 'lightgrey'; + this.doneTaskBkgColor = this.doneTaskBkgColor || 'lightgrey'; + this.doneTaskBorderColor = this.doneTaskBorderColor || 'grey'; + this.critBorderColor = this.critBorderColor || '#ff8888'; + this.critBkgColor = this.critBkgColor || 'red'; + this.todayLineColor = this.todayLineColor || 'red'; + this.taskTextColor = this.taskTextColor || this.textColor; + this.taskTextOutsideColor = this.taskTextOutsideColor || this.textColor; + this.taskTextLightColor = this.taskTextLightColor || this.textColor; + this.taskTextColor = this.taskTextColor || this.primaryTextColor; + this.taskTextDarkColor = this.taskTextDarkColor || this.textColor; + this.taskTextClickableColor = this.taskTextClickableColor || '#003163'; + + /* Sequence Diagram variables */ + + this.personBorder = this.personBorder || this.primaryBorderColor; + this.personBkg = this.personBkg || this.mainBkg; + + /* state colors */ + this.transitionColor = this.transitionColor || this.lineColor; + this.transitionLabelColor = this.transitionLabelColor || this.textColor; + /* The color of the text tables of the states*/ + this.stateLabelColor = this.stateLabelColor || this.stateBkg || this.primaryTextColor; + + this.stateBkg = this.stateBkg || this.mainBkg; + this.labelBackgroundColor = this.labelBackgroundColor || this.stateBkg; + this.compositeBackground = this.compositeBackground || this.background || this.tertiaryColor; + this.altBackground = this.altBackground || this.tertiaryColor; + this.compositeTitleBackground = this.compositeTitleBackground || this.mainBkg; + this.compositeBorder = this.compositeBorder || this.nodeBorder; + this.innerEndBackground = this.nodeBorder; + this.errorBkgColor = this.errorBkgColor || this.tertiaryColor; + this.errorTextColor = this.errorTextColor || this.tertiaryTextColor; + this.transitionColor = this.transitionColor || this.lineColor; + this.specialStateColor = this.lineColor; + + /* Color Scale */ + /* Each color-set will have a background, a foreground and a border color */ + this.cScale0 = this.cScale0 || this.primaryColor; + this.cScale1 = this.cScale1 || this.secondaryColor; + this.cScale2 = this.cScale2 || this.tertiaryColor; + this.cScale3 = this.cScale3 || adjust(this.primaryColor, { h: 30 }); + this.cScale4 = this.cScale4 || adjust(this.primaryColor, { h: 60 }); + this.cScale5 = this.cScale5 || adjust(this.primaryColor, { h: 90 }); + this.cScale6 = this.cScale6 || adjust(this.primaryColor, { h: 120 }); + this.cScale7 = this.cScale7 || adjust(this.primaryColor, { h: 150 }); + this.cScale8 = this.cScale8 || adjust(this.primaryColor, { h: 210, l: 150 }); + this.cScale9 = this.cScale9 || adjust(this.primaryColor, { h: 270 }); + this.cScale10 = this.cScale10 || adjust(this.primaryColor, { h: 300 }); + this.cScale11 = this.cScale11 || adjust(this.primaryColor, { h: 330 }); + if (this.darkMode) { + for (let i = 0; i < this.THEME_COLOR_LIMIT; i++) { + this['cScale' + i] = darken(this['cScale' + i], 75); + } + } else { + for (let i = 0; i < this.THEME_COLOR_LIMIT; i++) { + this['cScale' + i] = darken(this['cScale' + i], 25); + } + } + + // Setup the inverted color for the set + for (let i = 0; i < this.THEME_COLOR_LIMIT; i++) { + this['cScaleInv' + i] = this['cScaleInv' + i] || invert(this['cScale' + i]); + } + // Setup the peer color for the set, useful for borders + for (let i = 0; i < this.THEME_COLOR_LIMIT; i++) { + if (this.darkMode) { + this['cScalePeer' + i] = this['cScalePeer' + i] || lighten(this['cScale' + i], 10); + } else { + this['cScalePeer' + i] = this['cScalePeer' + i] || darken(this['cScale' + i], 10); + } + } + + // Setup the label color for the set + this.scaleLabelColor = this.scaleLabelColor || this.labelTextColor; + + for (let i = 0; i < this.THEME_COLOR_LIMIT; i++) { + this['cScaleLabel' + i] = this['cScaleLabel' + i] || this.scaleLabelColor; + } + + const multiplier = this.darkMode ? -4 : -1; + for (let i = 0; i < 5; i++) { + this['surface' + i] = + this['surface' + i] || + adjust(this.mainBkg, { h: 180, s: -15, l: multiplier * (5 + i * 3) }); + this['surfacePeer' + i] = + this['surfacePeer' + i] || + adjust(this.mainBkg, { h: 180, s: -15, l: multiplier * (8 + i * 3) }); + } + + /* class */ + this.classText = this.classText || this.textColor; + + /* user-journey */ + this.fillType0 = this.fillType0 || this.primaryColor; + this.fillType1 = this.fillType1 || this.secondaryColor; + this.fillType2 = this.fillType2 || adjust(this.primaryColor, { h: 64 }); + this.fillType3 = this.fillType3 || adjust(this.secondaryColor, { h: 64 }); + this.fillType4 = this.fillType4 || adjust(this.primaryColor, { h: -64 }); + this.fillType5 = this.fillType5 || adjust(this.secondaryColor, { h: -64 }); + this.fillType6 = this.fillType6 || adjust(this.primaryColor, { h: 128 }); + this.fillType7 = this.fillType7 || adjust(this.secondaryColor, { h: 128 }); + + /* pie */ + this.pie1 = this.pie1 || this.primaryColor; + this.pie2 = this.pie2 || this.secondaryColor; + this.pie3 = this.pie3 || this.tertiaryColor; + this.pie4 = this.pie4 || adjust(this.primaryColor, { l: -10 }); + this.pie5 = this.pie5 || adjust(this.secondaryColor, { l: -10 }); + this.pie6 = this.pie6 || adjust(this.tertiaryColor, { l: -10 }); + this.pie7 = this.pie7 || adjust(this.primaryColor, { h: +60, l: -10 }); + this.pie8 = this.pie8 || adjust(this.primaryColor, { h: -60, l: -10 }); + this.pie9 = this.pie9 || adjust(this.primaryColor, { h: 120, l: 0 }); + this.pie10 = this.pie10 || adjust(this.primaryColor, { h: +60, l: -20 }); + this.pie11 = this.pie11 || adjust(this.primaryColor, { h: -60, l: -20 }); + this.pie12 = this.pie12 || adjust(this.primaryColor, { h: 120, l: -10 }); + this.pieTitleTextSize = this.pieTitleTextSize || '25px'; + this.pieTitleTextColor = this.pieTitleTextColor || this.taskTextDarkColor; + this.pieSectionTextSize = this.pieSectionTextSize || '17px'; + this.pieSectionTextColor = this.pieSectionTextColor || this.textColor; + this.pieLegendTextSize = this.pieLegendTextSize || '17px'; + this.pieLegendTextColor = this.pieLegendTextColor || this.taskTextDarkColor; + this.pieStrokeColor = this.pieStrokeColor || 'black'; + this.pieStrokeWidth = this.pieStrokeWidth || '2px'; + this.pieOuterStrokeWidth = this.pieOuterStrokeWidth || '2px'; + this.pieOuterStrokeColor = this.pieOuterStrokeColor || 'black'; + this.pieOpacity = this.pieOpacity || '0.7'; + + /* quadrant-graph */ + this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; + this.quadrant2Fill = this.quadrant2Fill || adjust(this.primaryColor, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.primaryColor, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.primaryColor, { r: 15, g: 15, b: 15 }); + this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.primaryTextColor, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.primaryTextColor, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.primaryTextColor, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; + this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; + this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; + this.quadrantInternalBorderStrokeFill = + this.quadrantInternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantExternalBorderStrokeFill = + this.quadrantExternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantTitleFill = this.quadrantTitleFill || this.primaryTextColor; + + /* xychart */ + this.xyChart = { + backgroundColor: this.xyChart?.backgroundColor || this.background, + titleColor: this.xyChart?.titleColor || this.primaryTextColor, + xAxisTitleColor: this.xyChart?.xAxisTitleColor || this.primaryTextColor, + xAxisLabelColor: this.xyChart?.xAxisLabelColor || this.primaryTextColor, + xAxisTickColor: this.xyChart?.xAxisTickColor || this.primaryTextColor, + xAxisLineColor: this.xyChart?.xAxisLineColor || this.primaryTextColor, + yAxisTitleColor: this.xyChart?.yAxisTitleColor || this.primaryTextColor, + yAxisLabelColor: this.xyChart?.yAxisLabelColor || this.primaryTextColor, + yAxisTickColor: this.xyChart?.yAxisTickColor || this.primaryTextColor, + yAxisLineColor: this.xyChart?.yAxisLineColor || this.primaryTextColor, + plotColorPalette: + this.xyChart?.plotColorPalette || + '#FFF4DD,#FFD8B1,#FFA07A,#ECEFF1,#D6DBDF,#C3E0A8,#FFB6A4,#FFD74D,#738FA7,#FFFFF0', + }; + + /* requirement-diagram */ + this.requirementBackground = this.requirementBackground || this.primaryColor; + this.requirementBorderColor = this.requirementBorderColor || this.primaryBorderColor; + this.requirementBorderSize = this.requirementBorderSize || '1'; + this.requirementTextColor = this.requirementTextColor || this.primaryTextColor; + this.relationColor = this.relationColor || this.lineColor; + this.relationLabelBackground = + this.relationLabelBackground || + (this.darkMode ? darken(this.secondaryColor, 30) : this.secondaryColor); + this.relationLabelColor = this.relationLabelColor || this.actorTextColor; + + /* git */ + this.git0 = this.git0 || this.primaryColor; + this.git1 = this.git1 || this.secondaryColor; + this.git2 = this.git2 || this.tertiaryColor; + this.git3 = this.git3 || adjust(this.primaryColor, { h: -30 }); + this.git4 = this.git4 || adjust(this.primaryColor, { h: -60 }); + this.git5 = this.git5 || adjust(this.primaryColor, { h: -90 }); + this.git6 = this.git6 || adjust(this.primaryColor, { h: +60 }); + this.git7 = this.git7 || adjust(this.primaryColor, { h: +120 }); + if (this.darkMode) { + this.git0 = lighten(this.git0, 25); + this.git1 = lighten(this.git1, 25); + this.git2 = lighten(this.git2, 25); + this.git3 = lighten(this.git3, 25); + this.git4 = lighten(this.git4, 25); + this.git5 = lighten(this.git5, 25); + this.git6 = lighten(this.git6, 25); + this.git7 = lighten(this.git7, 25); + } else { + this.git0 = darken(this.git0, 25); + this.git1 = darken(this.git1, 25); + this.git2 = darken(this.git2, 25); + this.git3 = darken(this.git3, 25); + this.git4 = darken(this.git4, 25); + this.git5 = darken(this.git5, 25); + this.git6 = darken(this.git6, 25); + this.git7 = darken(this.git7, 25); + } + this.gitInv0 = this.gitInv0 || invert(this.git0); + this.gitInv1 = this.gitInv1 || invert(this.git1); + this.gitInv2 = this.gitInv2 || invert(this.git2); + this.gitInv3 = this.gitInv3 || invert(this.git3); + this.gitInv4 = this.gitInv4 || invert(this.git4); + this.gitInv5 = this.gitInv5 || invert(this.git5); + this.gitInv6 = this.gitInv6 || invert(this.git6); + this.gitInv7 = this.gitInv7 || invert(this.git7); + this.branchLabelColor = + this.branchLabelColor || (this.darkMode ? 'black' : this.labelTextColor); + this.gitBranchLabel0 = this.gitBranchLabel0 || this.branchLabelColor; + this.gitBranchLabel1 = this.gitBranchLabel1 || this.branchLabelColor; + this.gitBranchLabel2 = this.gitBranchLabel2 || this.branchLabelColor; + this.gitBranchLabel3 = this.gitBranchLabel3 || this.branchLabelColor; + this.gitBranchLabel4 = this.gitBranchLabel4 || this.branchLabelColor; + this.gitBranchLabel5 = this.gitBranchLabel5 || this.branchLabelColor; + this.gitBranchLabel6 = this.gitBranchLabel6 || this.branchLabelColor; + this.gitBranchLabel7 = this.gitBranchLabel7 || this.branchLabelColor; + + this.tagLabelColor = this.tagLabelColor || this.primaryTextColor; + this.tagLabelBackground = this.tagLabelBackground || this.primaryColor; + this.tagLabelBorder = this.tagBorder || this.primaryBorderColor; + this.tagLabelFontSize = this.tagLabelFontSize || '10px'; + this.commitLabelColor = this.commitLabelColor || this.secondaryTextColor; + this.commitLabelBackground = this.commitLabelBackground || this.secondaryColor; + this.commitLabelFontSize = this.commitLabelFontSize || '10px'; + + /* -------------------------------------------------- */ + /* EntityRelationship diagrams */ + + this.attributeBackgroundColorOdd = + this.attributeBackgroundColorOdd || oldAttributeBackgroundColorOdd; + this.attributeBackgroundColorEven = + this.attributeBackgroundColorEven || oldAttributeBackgroundColorEven; + /* -------------------------------------------------- */ + } + calculate(overrides) { + if (typeof overrides !== 'object') { + // Calculate colors form base colors + this.updateColors(); + return; + } + + const keys = Object.keys(overrides); + + // Copy values from overrides, this is mainly for base colors + keys.forEach((k) => { + this[k] = overrides[k]; + }); + + // Calculate colors form base colors + this.updateColors(); + // Copy values from overrides again in case of an override of derived value + keys.forEach((k) => { + this[k] = overrides[k]; + }); + } +} + +export const getThemeVariables = (userOverrides) => { + const theme = new Theme(); + theme.calculate(userOverrides); + return theme; +}; diff --git a/packages/mermaid/src/themes/theme-neutral.js b/packages/mermaid/src/themes/theme-neutral.js index 4134a985b..323cf4444 100644 --- a/packages/mermaid/src/themes/theme-neutral.js +++ b/packages/mermaid/src/themes/theme-neutral.js @@ -42,6 +42,7 @@ class Theme { this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; this.fontSize = '16px'; this.THEME_COLOR_LIMIT = 12; + this.radius = 5; /* Flowchart variables */