diff --git a/packages/mermaid/src/diagrams/treemap/db.ts b/packages/mermaid/src/diagrams/treemap/db.ts index 0f8aa8397..c22bbc4cb 100644 --- a/packages/mermaid/src/diagrams/treemap/db.ts +++ b/packages/mermaid/src/diagrams/treemap/db.ts @@ -16,7 +16,7 @@ const defaultTreemapData: TreemapData = { nodes: [], levels: new Map(), }; - +let outerNodes: TreemapNode[] = []; let data: TreemapData = structuredClone(defaultTreemapData); const getConfig = () => { @@ -32,17 +32,22 @@ const addNode = (node: TreemapNode, level: number) => { data.nodes.push(node); data.levels.set(node, level); + if (level === 0) { + outerNodes.push(node); + } + // Set the root node if this is a level 0 node and we don't have a root yet if (level === 0 && !data.root) { data.root = node; } }; -const getRoot = (): TreemapNode | undefined => data.root; +const getRoot = (): TreemapNode | undefined => ({ name: '', children: outerNodes }); const clear = () => { commonClear(); data = structuredClone(defaultTreemapData); + outerNodes = []; }; export const db: TreemapDB = { diff --git a/packages/mermaid/src/diagrams/treemap/renderer.ts b/packages/mermaid/src/diagrams/treemap/renderer.ts index c13b1c40b..b7b78904c 100644 --- a/packages/mermaid/src/diagrams/treemap/renderer.ts +++ b/packages/mermaid/src/diagrams/treemap/renderer.ts @@ -1,11 +1,14 @@ import type { Diagram } from '../../Diagram.js'; import type { DiagramRenderer, DrawDefinition } from '../../diagram-api/types.js'; import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; +import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js'; import { configureSvgSize } from '../../setupGraphViewbox.js'; import type { TreemapDB, TreemapNode } from './types.js'; import { scaleOrdinal, treemap, hierarchy, format, select } from 'd3'; +import { getConfig } from '../../config.js'; -const DEFAULT_INNER_PADDING = 5; // Default for inner padding between cells/sections +const DEFAULT_INNER_PADDING = 10; // Default for inner padding between cells/sections +const SECTION_INNER_PADDING = 10; // Default for inner padding between cells/sections const SECTION_HEADER_HEIGHT = 25; /** @@ -17,7 +20,9 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { const treemapInnerPadding = config.padding !== undefined ? config.padding : DEFAULT_INNER_PADDING; const title = treemapDb.getDiagramTitle(); const root = treemapDb.getRoot(); - + // const theme = config.getThemeVariables(); + const { themeVariables } = getConfig(); + console.log('root', root); if (!root) { return; } @@ -27,8 +32,8 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { const svg = selectSvgElement(id); // Use config dimensions or defaults - const width = config.nodeWidth ? config.nodeWidth * 10 : 960; - const height = config.nodeHeight ? config.nodeHeight * 10 : 500; + const width = config.nodeWidth ? config.nodeWidth * SECTION_INNER_PADDING : 960; + const height = config.nodeHeight ? config.nodeHeight * SECTION_INNER_PADDING : 500; const svgWidth = width; const svgHeight = height + titleHeight; @@ -42,16 +47,49 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { // Create color scale const colorScale = scaleOrdinal().range([ - '#8dd3c7', - '#ffffb3', - '#bebada', - '#fb8072', - '#80b1d3', - '#fdb462', - '#b3de69', - '#fccde5', - '#d9d9d9', - '#bc80bd', + 'transparent', + themeVariables.cScale0, + themeVariables.cScale1, + themeVariables.cScale2, + themeVariables.cScale3, + themeVariables.cScale4, + themeVariables.cScale5, + themeVariables.cScale6, + themeVariables.cScale7, + themeVariables.cScale8, + themeVariables.cScale9, + themeVariables.cScale10, + themeVariables.cScale11, + ]); + const colorScalePeer = scaleOrdinal().range([ + 'transparent', + themeVariables.cScalePeer0, + themeVariables.cScalePeer1, + themeVariables.cScalePeer2, + themeVariables.cScalePeer3, + themeVariables.cScalePeer4, + themeVariables.cScalePeer5, + themeVariables.cScalePeer6, + themeVariables.cScalePeer7, + themeVariables.cScalePeer8, + themeVariables.cScalePeer9, + themeVariables.cScalePeer10, + themeVariables.cScalePeer11, + ]); + const colorScaleLabel = scaleOrdinal().range([ + 'transparent', + themeVariables.cScaleLabel0, + themeVariables.cScaleLabel1, + themeVariables.cScaleLabel2, + themeVariables.cScaleLabel3, + themeVariables.cScaleLabel4, + themeVariables.cScaleLabel5, + themeVariables.cScaleLabel6, + themeVariables.cScaleLabel7, + themeVariables.cScaleLabel8, + themeVariables.cScaleLabel9, + themeVariables.cScaleLabel10, + themeVariables.cScaleLabel11, ]); // Draw the title if it exists @@ -80,8 +118,13 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { // Create treemap layout const treemapLayout = treemap() .size([width, height]) - .paddingTop((d) => (d.children && d.children.length > 0 ? SECTION_HEADER_HEIGHT : 0)) + .paddingTop((d) => + d.children && d.children.length > 0 ? SECTION_HEADER_HEIGHT + SECTION_INNER_PADDING : 0 + ) .paddingInner(treemapInnerPadding) + .paddingLeft((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0)) + .paddingRight((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0)) + .paddingBottom((d) => (d.children && d.children.length > 0 ? SECTION_INNER_PADDING : 0)) .round(true); // Apply the treemap layout to the hierarchy @@ -103,11 +146,22 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { .attr('width', (d) => d.x1 - d.x0) .attr('height', SECTION_HEADER_HEIGHT) .attr('class', 'treemapSectionHeader') + // .attr('fill', (d) => colorScale(d.data.name)) + .attr('fill', 'none') + .attr('fill-opacity', 0.6) + // .attr('stroke', (d) => colorScale(d.data.name)) + .attr('stroke-width', 0.6); + + sections + .append('rect') + .attr('width', (d) => d.x1 - d.x0) + .attr('height', (d) => d.y1 - d.y0) + .attr('class', 'treemapSection') .attr('fill', (d) => colorScale(d.data.name)) .attr('fill-opacity', 0.6) - .attr('stroke', (d) => colorScale(d.data.name)) - .attr('stroke-width', 1); - + .attr('stroke', (d) => colorScalePeer(d.data.name)) + .attr('stroke-width', 2.0) + .attr('stroke-opacity', 0.4); // Add section labels sections .append('text') @@ -118,7 +172,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { .text((d) => d.data.name) .attr('font-weight', 'bold') .style('font-size', '12px') - .style('fill', '#000000') + .style('fill', (d) => colorScaleLabel(d.data.name)) .each(function (d) { const self = select(this); const originalText = d.data.name; @@ -173,7 +227,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { .text((d) => (d.value ? valueFormat(d.value) : '')) .attr('font-style', 'italic') .style('font-size', '10px') - .style('fill', '#000000'); + .style('fill', (d) => colorScaleLabel(d.data.name)); } // Draw the leaf nodes @@ -193,13 +247,18 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { .attr('height', (d) => d.y1 - d.y0) .attr('class', 'treemapLeaf') .attr('fill', (d) => { - let current = d; - while (current.depth > 1 && current.parent) { - current = current.parent; - } - return colorScale(current.data.name); + // Leaves inherit color from their immediate parent section's name. + // If a leaf is the root itself (no parent), it uses its own name. + return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name); }) - .attr('fill-opacity', 0.8); + .attr('fill-opacity', 0.2) + .attr('stroke', (d) => { + // Leaves inherit color from their immediate parent section's name. + // If a leaf is the root itself (no parent), it uses its own name. + return d.parent ? colorScale(d.parent.data.name) : colorScale(d.data.name); + }) + .attr('stroke-width', 2.0) + .attr('stroke-opacity', 0.3); // Add clip paths to prevent text from extending outside nodes cell @@ -215,7 +274,9 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { .attr('class', 'treemapLabel') .attr('x', 4) .attr('y', 14) - .style('font-size', '11px') + .style('font-size', '34px') + .style('fill', (d) => colorScaleLabel(d.data.name)) + // .style('stroke', (d) => colorScaleLabel(d.data.name)) .attr('clip-path', (d, i) => `url(#clip-${id}-${i})`) .text((d) => d.data.name); @@ -246,6 +307,25 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { } }); } + + setupViewPortForSVG(svg, 0, 'flowchart', config?.useMaxWidth || false); + const viewBox = svg.attr('viewBox'); + const viewBoxParts = viewBox.split(' '); + const viewBoxWidth = viewBoxParts[2]; + const viewBoxHeight = viewBoxParts[3]; + const viewBoxX = viewBoxParts[0]; + const viewBoxY = viewBoxParts[1]; + + const viewBoxWidthNumber = Number(viewBoxWidth); + const viewBoxHeightNumber = Number(viewBoxHeight); + const viewBoxXNumber = Number(viewBoxX); + const viewBoxYNumber = Number(viewBoxY); + + // Adjust the viewBox to account for the title height + svg.attr( + 'viewBox', + `${viewBoxXNumber} ${viewBoxYNumber + SECTION_HEADER_HEIGHT} ${viewBoxWidthNumber} ${viewBoxHeightNumber - SECTION_HEADER_HEIGHT}` + ); }; export const renderer: DiagramRenderer = { draw }; diff --git a/packages/mermaid/src/diagrams/treemap/styles.ts b/packages/mermaid/src/diagrams/treemap/styles.ts index 5c80e7810..20f917bac 100644 --- a/packages/mermaid/src/diagrams/treemap/styles.ts +++ b/packages/mermaid/src/diagrams/treemap/styles.ts @@ -22,9 +22,8 @@ export const getStyles: DiagramStylesProvider = ({ return ` .treemapNode { - fill: pink; - stroke: black; - stroke-width: 1; + // stroke: black; + // stroke-width: 1; } .packetByte { font-size: ${options.byteFontSize};