From 2eddee90e0c1483234b1899e899eb537e9a460e5 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Mon, 22 Jul 2024 12:52:16 +0200 Subject: [PATCH] MC-1730 Adding mc theme --- packages/mermaid-layout-elk/package.json | 2 +- packages/mermaid/package.json | 2 +- packages/mermaid/src/themes/index.js | 4 + packages/mermaid/src/themes/theme-mc.js | 380 +++++++++++++++++++++++ 4 files changed, 386 insertions(+), 2 deletions(-) create mode 100644 packages/mermaid/src/themes/theme-mc.js diff --git a/packages/mermaid-layout-elk/package.json b/packages/mermaid-layout-elk/package.json index 84de2025d..60445739b 100644 --- a/packages/mermaid-layout-elk/package.json +++ b/packages/mermaid-layout-elk/package.json @@ -1,6 +1,6 @@ { "name": "@mermaid-chart/layout-elk", - "version": "0.0.5", + "version": "0.0.8", "description": "ELK layout engine for mermaid", "module": "dist/mermaid-layout-elk.core.mjs", "types": "dist/packages/mermaid-layout-elk/src/index.d.ts", diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index 257cf7780..ceabddc07 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -1,6 +1,6 @@ { "name": "@mermaid-chart/mermaid", - "version": "11.0.0-b.46", + "version": "11.0.0-b.47", "description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "type": "module", "module": "./dist/mermaid.core.mjs", diff --git a/packages/mermaid/src/themes/index.js b/packages/mermaid/src/themes/index.js index aeb5431d0..aecb4290c 100644 --- a/packages/mermaid/src/themes/index.js +++ b/packages/mermaid/src/themes/index.js @@ -5,6 +5,7 @@ import { getThemeVariables as forestThemeVariables } from './theme-forest.js'; import { getThemeVariables as neutralThemeVariables } from './theme-neutral.js'; import { getThemeVariables as neoThemeVariables } from './theme-neo.js'; import { getThemeVariables as neoDarkThemeVariables } from './theme-neo-dark.js'; +import { getThemeVariables as mcThemeVariables } from './theme-mc.js'; export default { base: { @@ -28,4 +29,7 @@ export default { 'neo-dark': { getThemeVariables: neoDarkThemeVariables, }, + mc: { + getThemeVariables: mcThemeVariables, + }, }; diff --git a/packages/mermaid/src/themes/theme-mc.js b/packages/mermaid/src/themes/theme-mc.js new file mode 100644 index 000000000..7f83abb7e --- /dev/null +++ b/packages/mermaid/src/themes/theme-mc.js @@ -0,0 +1,380 @@ +import { darken, lighten, adjust, invert, isDark } 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 = '#ECECFE'; + this.secondaryColor = '#E9E9F1'; + this.mainBkg = '#ffffff'; + + 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 = '12px'; + + // Neo-specific + this.nodeBorder = '#000000'; + this.stateBorder = '#000000'; + this.useGradient = true; + this.gradientStart = '#0042eb'; + this.gradientStop = '#eb0042'; + // this.dropShadow = 'drop-shadow( 1px 2px 2px rgba(185,185,185,1))'; + // this.dropShadow = 'drop-shadow(0px 2px 2px rgba(0, 0, 0, 0.25));'; + this.dropShadow = 'drop-shadow( 0px 1px 2px rgba(0, 0, 0, 0.25));'; + this.tertiaryColor = '#ffffff'; + } + 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; + this.tertiaryColor = this.tertiaryColor || adjust(this.primaryColor, { h: 180, l: 5 }); + + this.primaryBorderColor = this.primaryBorderColor || '#BCBCFB'; + 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 || '#f0f0f0'; + 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; +};