Merge branch 'pebr/neo-style' into alanaV11

This commit is contained in:
Per Brolin
2024-06-11 13:44:41 +02:00
41 changed files with 628 additions and 143 deletions

View File

@@ -4,16 +4,35 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/> />
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet" rel="stylesheet"
/> />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style> <style>
body { body {
/* background: rgb(221, 208, 208); */ /* background: rgb(221, 208, 208); */
/* background:#333; */ /* background: #333; */
font-family: 'Arial'; font-family: 'Arial';
/* font-size: 18px !important; */ /* font-size: 18px !important; */
} }
@@ -25,6 +44,15 @@
} }
.mermaid svg { .mermaid svg {
/* font-size: 18px !important; */ /* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
} }
.malware { .malware {
position: fixed; position: fixed;
@@ -41,34 +69,68 @@
font-family: monospace; font-family: monospace;
font-size: 72px; font-size: 72px;
} }
/* tspan {
font-size: 6px !important;
} */
</style> </style>
</head> </head>
<body> <body>
<div>Security check</div>
<pre id="diagram" class="mermaid">
flowchart LR
A-->B
</pre
>
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid2">
mindmap stateDiagram-v2
root direction LR
ch1 [*] --> Active
ch2
</pre state Active {
direction BT
[*] --> Inner
Inner --> NumLockOn : EvNumLockPressed
}
%% Outer --> Inner
</pre
> >
<script src="./packages/mermaid-mindmap/dist/mermaid-mindmap-detector.js"></script>
<script src="./packages/mermaid-mindmap/dist/mermaid-example-diagram-detector.js"></script> <pre id="diagram" class="mermaid">
<script src="./packages/mermaid/dist/mermaid.esm.mjs"></script> stateDiagram
<script> direction LR
[*] --> A
A --> B
B --> C
state B {
direction LR
a --> b
}
B --> D
</pre
>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import { layouts } from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) { mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err); console.error('Mermaid error: ', err);
}; };
mermaid.initialize({ mermaid.initialize({
startOnLoad: true, theme: 'neo',
handdrawnSeed: 12,
look: 'neo',
'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
fontFamily: 'Arial',
sequence: {
actorFontFamily: 'arial',
noteFontFamily: 'arial',
messageFontFamily: 'arial',
},
fontSize: 12,
logLevel: 0, logLevel: 0,
basePath: './packages/',
// themeVariables: {relationLabelColor: 'red'}
}); });
function callback() { function callback() {
alert('It worked'); alert('It worked');
@@ -77,6 +139,10 @@ A-->B
console.error('In parse error:'); console.error('In parse error:');
console.error(err); console.error(err);
}; };
// mermaid.test1('first_slow', 1200).then((r) => console.info(r));
// mermaid.test1('second_fast', 200).then((r) => console.info(r));
// mermaid.test1('third_fast', 200).then((r) => console.info(r));
// mermaid.test1('forth_slow', 1200).then((r) => console.info(r));
</script> </script>
</body> </body>
</html> </html>

View File

@@ -68,7 +68,7 @@ export interface MermaidConfig {
* Defines which main look to use for the diagram. * 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. * 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.
* *

View File

@@ -29,6 +29,7 @@ const arrowTypesMap = {
arrow_cross: 'cross', arrow_cross: 'cross',
arrow_point: 'point', arrow_point: 'point',
arrow_barb: 'barb', arrow_barb: 'barb',
arrow_neo: 'barbNeo',
arrow_circle: 'circle', arrow_circle: 'circle',
aggregation: 'aggregation', aggregation: 'aggregation',
extension: 'extension', extension: 'extension',

View File

@@ -775,12 +775,12 @@ const addNodeFromVertex = (
parentDB: Map<string, string>, parentDB: Map<string, string>,
subGraphDB: Map<string, boolean>, subGraphDB: Map<string, boolean>,
config: any, config: any,
useRough: boolean look: string
): Node => { ): Node => {
let parentId = parentDB.get(vertex.id); const parentId = parentDB.get(vertex.id);
let isGroup = subGraphDB.get(vertex.id) || false; const isGroup = subGraphDB.get(vertex.id) || false;
let node = findNode(nodes, vertex.id); const node = findNode(nodes, vertex.id);
if (!node) { if (!node) {
nodes.push({ nodes.push({
id: vertex.id, id: vertex.id,
@@ -795,7 +795,7 @@ const addNodeFromVertex = (
domId: vertex.domId, domId: vertex.domId,
type: isGroup ? 'group' : undefined, type: isGroup ? 'group' : undefined,
isGroup, isGroup,
useRough, look,
}); });
} }
}; };
@@ -807,7 +807,6 @@ export const getData = () => {
// extract(getRootDocV2()); // extract(getRootDocV2());
// const diagramStates = getStates(); // const diagramStates = getStates();
const useRough = config.look === 'handdrawn';
const subGraphs = getSubGraphs(); const subGraphs = getSubGraphs();
log.info('Subgraphs - APA12', subGraphs); log.info('Subgraphs - APA12', subGraphs);
const parentDB = new Map<string, string>(); const parentDB = new Map<string, string>();
@@ -834,14 +833,14 @@ export const getData = () => {
domId: subGraph.domId, domId: subGraph.domId,
type: 'group', type: 'group',
isGroup: true, isGroup: true,
useRough, look: config.look,
}); });
} }
console.log('APA12 nodes - 1', nodes.length); console.log('APA12 nodes - 1', nodes.length);
const n = getVertices(); const n = getVertices();
n.forEach((vertex) => { n.forEach((vertex) => {
const node = addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, useRough); const node = addNodeFromVertex(vertex, nodes, parentDB, subGraphDB, config, config.look);
if (node) { if (node) {
nodes.push(node); nodes.push(node);
} }
@@ -874,14 +873,12 @@ export const getData = () => {
// domId: verawEdgertex.domId, // domId: verawEdgertex.domId,
// rawEdge: undefined, // rawEdge: undefined,
// isGroup: false, // isGroup: false,
useRough, look: config.look,
}; };
// console.log('rawEdge SPLIT', rawEdge, index); // console.log('rawEdge SPLIT', rawEdge, index);
edges.push(edge); edges.push(edge);
}); });
//const useRough = config.look === 'handdrawn';
return { nodes, edges, other: {}, config }; return { nodes, edges, other: {}, config };
}; };

View File

@@ -54,39 +54,23 @@ export function stateDomId(itemId = '', counter = 0, type = '', typeSpacer = DOM
return `${DOMID_STATE}-${itemId}${typeStr}-${counter}`; 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; // graphItemCount = 0;
log.trace('items', doc); log.trace('items', doc);
doc.forEach((item) => { doc.forEach((item) => {
switch (item.stmt) { switch (item.stmt) {
case STMT_STATE: case STMT_STATE:
dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough, look); dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, look);
break; break;
case DEFAULT_STATE_TYPE: case DEFAULT_STATE_TYPE:
dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, useRough, look); dataFetcher(parentParsedItem, item, diagramStates, nodes, edges, altFlag, look);
break; break;
case STMT_RELATION: case STMT_RELATION:
{ {
dataFetcher( dataFetcher(parentParsedItem, item.state1, diagramStates, nodes, edges, altFlag, look);
parentParsedItem, dataFetcher(parentParsedItem, item.state2, diagramStates, nodes, edges, altFlag, look);
item.state1,
diagramStates,
nodes,
edges,
altFlag,
useRough,
look
);
dataFetcher(
parentParsedItem,
item.state2,
diagramStates,
nodes,
edges,
altFlag,
useRough,
look
);
const edgeData = { const edgeData = {
id: 'edge' + graphItemCount, id: 'edge' + graphItemCount,
start: item.state1.id, start: item.state1.id,
@@ -101,7 +85,6 @@ const setupDoc = (parentParsedItem, doc, diagramStates, nodes, edges, altFlag, u
labelType: G_EDGE_LABELTYPE, labelType: G_EDGE_LABELTYPE,
thickness: G_EDGE_THICKNESS, thickness: G_EDGE_THICKNESS,
classes: CSS_EDGE, classes: CSS_EDGE,
useRough,
look, look,
}; };
edges.push(edgeData); edges.push(edgeData);
@@ -225,16 +208,7 @@ function getClassesFromDbInfo(dbInfoItem) {
} }
} }
} }
export const dataFetcher = ( export const dataFetcher = (parent, parsedItem, diagramStates, nodes, edges, altFlag, look) => {
parent,
parsedItem,
diagramStates,
nodes,
edges,
altFlag,
useRough,
look
) => {
const itemId = parsedItem.id; const itemId = parsedItem.id;
const classStr = getClassesFromDbInfo(diagramStates.get(itemId)); const classStr = getClassesFromDbInfo(diagramStates.get(itemId));
@@ -324,7 +298,6 @@ export const dataFetcher = (
padding: 8, padding: 8,
rx: 10, rx: 10,
ry: 10, ry: 10,
useRough,
look, look,
}; };
@@ -354,7 +327,6 @@ export const dataFetcher = (
type: newNode.type, type: newNode.type,
isGroup: newNode.type === 'group', isGroup: newNode.type === 'group',
padding: 0, //getConfig().flowchart.padding padding: 0, //getConfig().flowchart.padding
useRough,
look, look,
position: parsedItem.note.position, position: parsedItem.note.position,
}; };
@@ -369,7 +341,6 @@ export const dataFetcher = (
type: 'group', type: 'group',
isGroup: true, isGroup: true,
padding: 16, //getConfig().flowchart.padding padding: 16, //getConfig().flowchart.padding
useRough,
look, look,
position: parsedItem.note.position, position: parsedItem.note.position,
}; };
@@ -410,7 +381,6 @@ export const dataFetcher = (
labelpos: G_EDGE_LABELPOS, labelpos: G_EDGE_LABELPOS,
labelType: G_EDGE_LABELTYPE, labelType: G_EDGE_LABELTYPE,
thickness: G_EDGE_THICKNESS, thickness: G_EDGE_THICKNESS,
useRough,
look, look,
}); });
} else { } else {
@@ -419,7 +389,7 @@ export const dataFetcher = (
} }
if (parsedItem.doc) { if (parsedItem.doc) {
log.trace('Adding nodes children '); log.trace('Adding nodes children ');
setupDoc(parsedItem, parsedItem.doc, diagramStates, nodes, edges, !altFlag, useRough, look); setupDoc(parsedItem, parsedItem.doc, diagramStates, nodes, edges, !altFlag, look);
} }
}; };

View File

@@ -581,10 +581,10 @@ export const getData = () => {
// } // }
const diagramStates = getStates(); const diagramStates = getStates();
const config = getConfig(); const config = getConfig();
const useRough = config.look === 'handdrawn';
const look = config.look; const look = config.look;
resetDataFetching(); resetDataFetching();
dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, useRough, look); dataFetcher(undefined, getRootDocV2(), diagramStates, nodes, edges, true, look);
return { nodes, edges, other: {}, config }; return { nodes, edges, other: {}, config };
}; };

View File

@@ -333,7 +333,7 @@ const setupDoc = (g, parentParsedItem, doc, diagramStates, diagramDb, altFlag) =
counter: graphItemCount, counter: graphItemCount,
}), }),
arrowhead: 'normal', arrowhead: 'normal',
arrowTypeEnd: 'arrow_barb', arrowTypeEnd: 'arrow_neo',
style: G_EDGE_STYLE, style: G_EDGE_STYLE,
labelStyle: '', labelStyle: '',
label: common.sanitizeText(item.description, getConfig()), label: common.sanitizeText(item.description, getConfig()),

View File

@@ -79,7 +79,12 @@ export const draw = async function (
data4Layout.nodeSpacing = conf?.nodeSpacing || 50; data4Layout.nodeSpacing = conf?.nodeSpacing || 50;
// @ts-expect-error TODO: Will be fixed after config refactor // @ts-expect-error TODO: Will be fixed after config refactor
data4Layout.rankSpacing = conf?.rankSpacing || 50; 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; data4Layout.diagramId = id;
// console.log('REF1:', data4Layout); // console.log('REF1:', data4Layout);
await render(data4Layout, svg, element, positions); await render(data4Layout, svg, element, positions);

View File

@@ -127,22 +127,23 @@ g.stateGroup line {
} }
.statediagram-cluster rect.outer { .statediagram-cluster rect.outer {
rx: 5px; rx: ${options.radius}px;
ry: 5px; ry: ${options.radius}px;
} }
.statediagram-state .divider { .statediagram-state .divider {
stroke: ${options.stateBorder || options.nodeBorder}; stroke: ${options.stateBorder || options.nodeBorder};
} }
.statediagram-state .title-state { .statediagram-state .title-state {
rx: 5px; rx: ${options.radius}px;
ry: 5px; ry: ${options.radius}px;
} }
.statediagram-cluster.statediagram-cluster .inner { .statediagram-cluster.statediagram-cluster .inner {
fill: ${options.compositeBackground || options.background}; fill: ${options.compositeBackground || options.background};
} }
.statediagram-cluster.statediagram-cluster-alt .inner { .statediagram-cluster.statediagram-cluster-alt .inner {
fill: ${options.altBackground ? options.altBackground : '#efefef'}; fill: ${options.altBackground ? options.altBackground : '#efefef'};
} }
.statediagram-cluster .inner { .statediagram-cluster .inner {
@@ -151,9 +152,16 @@ g.stateGroup line {
} }
.statediagram-state rect.basic { .statediagram-state rect.basic {
rx: 5px; rx: ${options.radius}px;
ry: 5px; ry: ${options.radius}px;
} }
.state-shadow-neo {
filter: drop-shadow( 1px 2px 2px rgba(185,185,185,1.0) );
}
.statediagram-state rect.divider { .statediagram-state rect.divider {
stroke-dasharray: 10,10; stroke-dasharray: 10,10;
fill: ${options.altBackground ? options.altBackground : '#efefef'}; fill: ${options.altBackground ? options.altBackground : '#efefef'};

View File

@@ -10,12 +10,16 @@ import createLabel from './createLabel.js';
import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; import { createRoundedRectPathD } from './shapes/roundedRectPath.ts';
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; 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) => { const rect = (parent, node) => {
log.info('Creating subgraph rect for ', node.id, node); log.info('Creating subgraph rect for ', node.id, node);
const siteConfig = getConfig(); const siteConfig = getConfig();
const { themeVariables, handdrawnSeed } = siteConfig; const { themeVariables, handdrawnSeed } = siteConfig;
const { clusterBkg, clusterBorder } = themeVariables; const { clusterBkg, clusterBorder } = themeVariables;
let { useRough } = node;
// Add outer g element // Add outer g element
const shapeSvg = parent.insert('g').attr('class', 'cluster').attr('id', node.id); 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)); log.trace('Data ', node, JSON.stringify(node));
let rect; let rect;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore TODO: Fix rough typings // @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { const options = userNodeOverrides(node, {
@@ -215,10 +219,10 @@ const roundedWithTitle = (parent, node) => {
const innerY = node.y - node.height / 2 - halfPadding + bbox.height - 1; const innerY = node.y - node.height / 2 - halfPadding + bbox.height - 1;
const height = node.height + padding; const height = node.height + padding;
const innerHeight = node.height + padding - bbox.height - 3; const innerHeight = node.height + padding - bbox.height - 3;
const look = siteConfig.look;
// add the rect // add the rect
let rect; let rect;
if (node.useRough) { if (node.look === 'handdrawn') {
const isAlt = node.cssClasses.includes('statediagram-cluster-alt'); const isAlt = node.cssClasses.includes('statediagram-cluster-alt');
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const roughOuterNode = const roughOuterNode =
@@ -244,9 +248,16 @@ const roundedWithTitle = (parent, node) => {
innerRect = shapeSvg.insert(() => roughInnerNode); innerRect = shapeSvg.insert(() => roughInnerNode);
} else { } else {
rect = outerRectG.insert('rect', ':first-child'); 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 // center the rect around its coordinate
rect rect
.attr('class', 'outer') .attr('class', outerRectClass)
.attr('x', x) .attr('x', x)
.attr('y', y) .attr('y', y)
.attr('width', width) .attr('width', width)
@@ -259,16 +270,12 @@ const roundedWithTitle = (parent, node) => {
.attr('height', innerHeight); .attr('height', innerHeight);
} }
// Center the label let diff = bbox.height - (innerY - y) / 2;
let correction = calcLabelOffsetCorrection(diff, bbox.height);
label.attr( label.attr(
'transform', 'transform',
`translate(${node.x - bbox.width / 2}, ${ `translate(${node.x - bbox.width / 2}, ${(innerY - y) / 2 - correction})`
node.y -
node.height / 2 -
node.padding +
bbox.height / 2 -
(evaluate(siteConfig.flowchart.htmlLabels) ? 5 : 3)
})`
); );
const rectBox = rect.node().getBBox(); const rectBox = rect.node().getBBox();
@@ -300,7 +307,7 @@ const divider = (parent, node) => {
const y = node.y - node.height / 2; const y = node.y - node.height / 2;
const width = node.width + padding; const width = node.width + padding;
const height = node.height + padding; const height = node.height + padding;
if (node.useRough) { if (node.look === 'handdrawn') {
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const roughNode = rc.rectangle(x, y, width, height, { const roughNode = rc.rectangle(x, y, width, height, {
fill: 'lightgrey', fill: 'lightgrey',

View File

@@ -594,11 +594,10 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
default: default:
strokeClasses += ' edge-pattern-solid'; strokeClasses += ' edge-pattern-solid';
} }
let useRough = edge.useRough;
let svgPath; let svgPath;
let path = ''; let path = '';
let linePath = lineFunction(lineData); let linePath = lineFunction(lineData);
if (useRough) { if (edge.look === 'handdrawn') {
const rc = rough.svg(elem); const rc = rough.svg(elem);
const ld = Object.assign([], lineData); const ld = Object.assign([], lineData);
// const svgPathNode = rc.path(lineFunction(ld.splice(0, ld.length-1)), { // const svgPathNode = rc.path(lineFunction(ld.splice(0, ld.length-1)), {

View File

@@ -277,6 +277,20 @@ const barb = (elem, type, id) => {
.append('path') .append('path')
.attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z'); .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 // TODO rename the class diagram markers to something shape descriptive and semantic free
const markers = { const markers = {
@@ -289,5 +303,6 @@ const markers = {
circle, circle,
cross, cross,
barb, barb,
barbNeo,
}; };
export default insertMarkers; export default insertMarkers;

View File

@@ -22,7 +22,7 @@ export const choice = (parent: SVG, node: Node) => {
]; ];
let choice; let choice;
if (node.useRough) { if (node.look === 'handdrawn') {
// @ts-ignore TODO: Fix rough typings // @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const pointArr = points.map(function (d) { const pointArr = points.map(function (d) {

View File

@@ -15,9 +15,9 @@ export const circle = async (parent: SVGAElement, node: Node): Promise<SVGAEleme
const radius = bbox.width / 2 + halfPadding; const radius = bbox.width / 2 + halfPadding;
let circleElem; let circleElem;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -68,9 +68,9 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
const h = bbox.height + ry + node.padding; const h = bbox.height + ry + node.padding;
let cylinder: d3.Selection<SVGPathElement | SVGGElement, unknown, null, undefined>; let cylinder: d3.Selection<SVGPathElement | SVGGElement, unknown, null, undefined>;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry); const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);

View File

@@ -18,9 +18,9 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise<SVG
const innerRadius = bbox.width / 2 + halfPadding; const innerRadius = bbox.width / 2 + halfPadding;
let circleGroup; let circleGroup;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 }); const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 });

View File

@@ -1,12 +1,15 @@
import { log } from '$root/logger.js';
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; import type { Node, RectOptions } from '$root/rendering-util/types.d.ts';
import { createRoundedRectPathD } from './roundedRectPath.js'; import { createRoundedRectPathD } from './roundedRectPath.js';
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import { getConfig } from '$root/diagram-api/diagramAPI.js';
export const drawRect = async (parent: SVGAElement, node: Node, options: RectOptions) => { export const drawRect = async (parent: SVGAElement, node: Node, options: RectOptions) => {
const { themeVariables, handdrawnSeed, look } = getConfig();
const { nodeBorder, mainBkg } = themeVariables;
const { shapeSvg, bbox, halfPadding } = await labelHelper( const { shapeSvg, bbox, halfPadding } = await labelHelper(
parent, parent,
node, node,
@@ -14,21 +17,22 @@ export const drawRect = async (parent: SVGAElement, node: Node, options: RectOpt
true true
); );
const totalWidth = Math.max(bbox.width + node.padding, node?.width || 0); const totalWidth = Math.max(bbox.width + options.labelPaddingX * 2, node?.width || 0);
const totalHeight = Math.max(bbox.height + node.padding, node?.height || 0); const totalHeight = Math.max(bbox.height + options.labelPaddingY * 2, node?.height || 0);
const x = -totalWidth / 2; const x = -totalWidth / 2;
const y = -totalHeight / 2; const y = -totalHeight / 2;
let rect; 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 //use options rx, ry overrides if present
if (options && options.rx && options.ry) { if (options && options.rx && options.ry) {
rx = options.rx; rx = options.rx;
ry = options.ry; ry = options.ry;
} }
if (node.look === 'handdrawn') {
if (useRough) {
// @ts-ignore TODO: Fix rough typings // @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); 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 = shapeSvg.insert(() => roughNode, ':first-child');
rect.attr('class', 'basic label-container').attr('style', cssStyles); 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 { } else {
rect = shapeSvg.insert('rect', ':first-child'); rect = shapeSvg.insert('rect', ':first-child');

View File

@@ -25,7 +25,7 @@ export const forkJoin = (parent: SVG, node: Node, dir: string) => {
const y = (-1 * height) / 2; const y = (-1 * height) / 2;
let shape; let shape;
if (node.useRough) { if (node.look === 'handdrawn') {
// @ts-ignore TODO: Fix rough typings // @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const roughNode = rc.rectangle(x, y, width, height, solidStateFill(lineColor)); const roughNode = rc.rectangle(x, y, width, height, solidStateFill(lineColor));

View File

@@ -56,9 +56,9 @@ export const hexagon = async (parent: SVGAElement, node: Node): Promise<SVGAElem
]; ];
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>; let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -43,9 +43,9 @@ export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise<SV
]; ];
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>; let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -42,9 +42,9 @@ export const lean_left = async (parent: SVGAElement, node: Node): Promise<SVGAEl
]; ];
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>; let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -42,9 +42,9 @@ export const lean_right = async (parent: SVGAElement, node: Node): Promise<SVGAE
]; ];
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>; let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -21,14 +21,14 @@ export const note = async (parent: SVGAElement, node: Node) => {
); );
log.info('Classes = ', node.cssClasses); log.info('Classes = ', node.cssClasses);
const { cssStyles, useRough } = node; const { cssStyles } = node;
let rect; let rect;
const totalWidth = bbox.width + node.padding; const totalWidth = bbox.width + node.padding;
const totalHeight = bbox.height + node.padding; const totalHeight = bbox.height + node.padding;
const x = -bbox.width / 2 - halfPadding; const x = -bbox.width / 2 - halfPadding;
const y = -bbox.height / 2 - halfPadding; const y = -bbox.height / 2 - halfPadding;
if (useRough) { if (node.look === 'handdrawn') {
// add the rect // add the rect
// @ts-ignore TODO: Fix rough typings // @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);

View File

@@ -38,9 +38,9 @@ export const question = async (parent: SVGAElement, node: Node): Promise<SVGAEle
]; ];
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>; let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -42,9 +42,9 @@ export const rect_left_inv_arrow = async (
]; ];
let polygon; let polygon;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -1,10 +1,16 @@
import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; import type { Node, RectOptions } from '$root/rendering-util/types.d.ts';
import { drawRect } from './drawRect.js'; import { drawRect } from './drawRect.js';
import { getConfig } from '$root/diagram-api/diagramAPI.js';
export const roundedRect = async (parent: SVGAElement, node: Node) => { export const roundedRect = async (parent: SVGAElement, node: Node) => {
const { look } = getConfig();
node.look = look;
const options = { const options = {
rx: 5, rx: node.look === 'neo' ? 1 : 5,
ry: 5, ry: node.look === 'neo' ? 1 : 5,
labelPaddingX: node.padding * 2,
labelPaddingY: node.padding * 1,
classes: '', classes: '',
} as RectOptions; } as RectOptions;

View File

@@ -58,8 +58,8 @@ export const stadium = async (parent: SVGAElement, node: Node) => {
const w = bbox.width + h / 4 + node.padding; const w = bbox.width + h / 4 + node.padding;
let rect; let rect;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -1,10 +1,14 @@
import type { Node } from '$root/rendering-util/types.d.ts'; import type { Node } from '$root/rendering-util/types.d.ts';
import { drawRect } from './drawRect.js'; import { drawRect } from './drawRect.js';
import { getConfig } from '$root/diagram-api/diagramAPI.js';
export const state = async (parent: SVGAElement, node: Node) => { export const state = async (parent: SVGAElement, node: Node) => {
const { look } = getConfig();
node.look = look;
const options = { const options = {
rx: 5, rx: node.look === 'neo' ? 2 : 5,
ry: 5, ry: node.look === 'neo' ? 2 : 5,
classes: 'flowchart-node', classes: 'flowchart-node',
}; };
return drawRect(parent, node, options); return drawRect(parent, node, options);

View File

@@ -17,7 +17,7 @@ export const stateEnd = (parent: SVG, node: Node) => {
let circle; let circle;
let innerCircle; let innerCircle;
if (node.useRough) { if (node.look === 'handdrawn') {
// @ts-ignore TODO: Fix rough typings // @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const roughNode = rc.circle(0, 0, 14, { ...solidStateFill(lineColor), roughness: 0.5 }); const roughNode = rc.circle(0, 0, 14, { ...solidStateFill(lineColor), roughness: 0.5 });

View File

@@ -17,7 +17,7 @@ export const stateStart = (parent: SVG, node: Node) => {
.attr('id', node.domId || node.id); .attr('id', node.domId || node.id);
let circle; let circle;
if (node.useRough) { if (node.look === 'handdrawn') {
// @ts-ignore TODO: Fix rough typings // @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const roughNode = rc.circle(0, 0, 14, solidStateFill(lineColor)); const roughNode = rc.circle(0, 0, 14, solidStateFill(lineColor));

View File

@@ -40,7 +40,7 @@ export const subroutine = async (parent: SVGAElement, node: Node) => {
const x = -bbox.width / 2 - halfPadding; const x = -bbox.width / 2 - halfPadding;
const y = -bbox.height / 2 - halfPadding; const y = -bbox.height / 2 - halfPadding;
let rect; let rect;
const { cssStyles, useRough } = node; const { cssStyles } = node;
const points = [ const points = [
{ x: 0, y: 0 }, { x: 0, y: 0 },
{ x: w, y: 0 }, { x: w, y: 0 },
@@ -54,7 +54,7 @@ export const subroutine = async (parent: SVGAElement, node: Node) => {
{ x: -8, y: 0 }, { x: -8, y: 0 },
]; ];
if (useRough) { if (node.look === 'handdrawn') {
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -42,10 +42,10 @@ export const trapezoid = async (parent: SVGAElement, node: Node): Promise<SVGAEl
]; ];
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>; let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
const { cssStyles, useRough } = node; const { cssStyles } = node;
if (useRough) { if (node.look === 'handdrawn') {
console.log('Trapezoid: Inside use useRough'); console.log('Trapezoid: Inside use handdrawn');
// @ts-ignore // @ts-ignore
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {}); const options = userNodeOverrides(node, {});

View File

@@ -46,7 +46,6 @@ interface Node {
rx?: number; // Used for rounded corners in Rect, Ellipse, etc.Maybe it to specialized RectNode, EllipseNode, etc. rx?: number; // Used for rounded corners in Rect, Ellipse, etc.Maybe it to specialized RectNode, EllipseNode, etc.
ry?: number; ry?: number;
useRough?: boolean;
useHtmlLabels?: boolean; useHtmlLabels?: boolean;
centerLabel?: boolean; //keep for now. centerLabel?: boolean; //keep for now.
//Candidate for removal, maybe rely on labelStyle or a specific property labelPosition: Top, Center, Bottom //Candidate for removal, maybe rely on labelStyle or a specific property labelPosition: Top, Center, Bottom
@@ -61,6 +60,9 @@ interface Node {
// Flowchart specific properties // Flowchart specific properties
x?: number; x?: number;
y?: number; y?: number;
// Added look to handle
look?: string;
} }
// Common properties for any edge in the system // Common properties for any edge in the system
@@ -91,12 +93,15 @@ interface Edge {
minlen?: number; minlen?: number;
pattern?: string; pattern?: string;
thickness?: 'normal' | 'thick' | 'invisible'; thickness?: 'normal' | 'thick' | 'invisible';
useRough?: boolean;
look?: string;
} }
interface RectOptions { interface RectOptions {
rx: number; rx: number;
ry: number; ry: number;
labelPaddingX: number;
labelPaddingY: number;
classes: string; classes: string;
} }

View File

@@ -69,7 +69,9 @@ const getStyles = (
} }
${diagramStyles} ${diagramStyles}
.node .neo-node {
stroke: ${options.nodeBorder};
}
${userStyles} ${userStyles}
`; `;
}; };

View File

@@ -3,6 +3,7 @@ import { getThemeVariables as darkThemeVariables } from './theme-dark.js';
import { getThemeVariables as defaultThemeVariables } from './theme-default.js'; import { getThemeVariables as defaultThemeVariables } from './theme-default.js';
import { getThemeVariables as forestThemeVariables } from './theme-forest.js'; import { getThemeVariables as forestThemeVariables } from './theme-forest.js';
import { getThemeVariables as neutralThemeVariables } from './theme-neutral.js'; import { getThemeVariables as neutralThemeVariables } from './theme-neutral.js';
import { getThemeVariables as neoThemeVariables } from './theme-neo.js';
export default { export default {
base: { base: {
@@ -20,4 +21,7 @@ export default {
neutral: { neutral: {
getThemeVariables: neutralThemeVariables, getThemeVariables: neutralThemeVariables,
}, },
neo: {
getThemeVariables: neoThemeVariables,
},
}; };

View File

@@ -20,7 +20,7 @@ class Theme {
this.noteTextColor = '#333'; this.noteTextColor = '#333';
this.THEME_COLOR_LIMIT = 12; this.THEME_COLOR_LIMIT = 12;
this.radius = 5;
// dark // dark
this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif';

View File

@@ -29,6 +29,7 @@ class Theme {
this.labelBackground = '#181818'; this.labelBackground = '#181818';
this.textColor = '#ccc'; this.textColor = '#ccc';
this.THEME_COLOR_LIMIT = 12; this.THEME_COLOR_LIMIT = 12;
this.radius = 5;
/* Flowchart variables */ /* Flowchart variables */
this.nodeBkg = 'calculated'; this.nodeBkg = 'calculated';

View File

@@ -37,6 +37,7 @@ class Theme {
this.labelBackground = '#e8e8e8'; this.labelBackground = '#e8e8e8';
this.textColor = '#333'; this.textColor = '#333';
this.THEME_COLOR_LIMIT = 12; this.THEME_COLOR_LIMIT = 12;
this.radius = 5;
/* Flowchart variables */ /* Flowchart variables */

View File

@@ -31,6 +31,7 @@ class Theme {
this.lineColor = invert(this.background); this.lineColor = invert(this.background);
this.textColor = invert(this.background); this.textColor = invert(this.background);
this.THEME_COLOR_LIMIT = 12; this.THEME_COLOR_LIMIT = 12;
this.radius = 5;
/* Flowchart variables */ /* Flowchart variables */
this.nodeBkg = 'calculated'; this.nodeBkg = 'calculated';

View File

@@ -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;
};

View File

@@ -42,6 +42,7 @@ class Theme {
this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif'; this.fontFamily = '"trebuchet ms", verdana, arial, sans-serif';
this.fontSize = '16px'; this.fontSize = '16px';
this.THEME_COLOR_LIMIT = 12; this.THEME_COLOR_LIMIT = 12;
this.radius = 5;
/* Flowchart variables */ /* Flowchart variables */