From a07f1f3337915e6f833d655c6af8bfb2cf7cd529 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Tue, 17 Sep 2024 21:14:16 +0530 Subject: [PATCH 01/11] chore: Run release-preview on more PR events --- .github/workflows/release-preview.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-preview.yml b/.github/workflows/release-preview.yml index 283c316fb..84808e44f 100644 --- a/.github/workflows/release-preview.yml +++ b/.github/workflows/release-preview.yml @@ -3,6 +3,7 @@ name: Preview release on: pull_request: branches: [develop] + types: [opened, synchronize, labeled, ready_for_review] concurrency: group: ${{ github.workflow }}-${{ github.event.number }} From d37d77cc1a99f02b5355fcc4ad9f5bd7136a267a Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Tue, 17 Sep 2024 21:18:21 +0530 Subject: [PATCH 02/11] chore: Remove maps in pkg.pr.new --- .github/workflows/release-preview.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release-preview.yml b/.github/workflows/release-preview.yml index 84808e44f..0157910ca 100644 --- a/.github/workflows/release-preview.yml +++ b/.github/workflows/release-preview.yml @@ -39,5 +39,8 @@ jobs: - name: Install Packages run: pnpm install --frozen-lockfile + - name: Trim maps + run: rm -rf ./**/dist/**/*.map + - name: Publish packages run: pnpx pkg-pr-new publish --pnpm './packages/*' From 522de3abd8f3a639cdd23069f18b777c9a3ebb40 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Tue, 17 Sep 2024 21:22:32 +0530 Subject: [PATCH 03/11] Revert "chore: Remove maps in pkg.pr.new" This reverts commit d37d77cc1a99f02b5355fcc4ad9f5bd7136a267a. --- .github/workflows/release-preview.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/release-preview.yml b/.github/workflows/release-preview.yml index 0157910ca..84808e44f 100644 --- a/.github/workflows/release-preview.yml +++ b/.github/workflows/release-preview.yml @@ -39,8 +39,5 @@ jobs: - name: Install Packages run: pnpm install --frozen-lockfile - - name: Trim maps - run: rm -rf ./**/dist/**/*.map - - name: Publish packages run: pnpx pkg-pr-new publish --pnpm './packages/*' From 3f5afe8daff833def69e40704c5586c1344aaa5c Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Tue, 17 Sep 2024 22:33:10 +0530 Subject: [PATCH 04/11] code refactor --- packages/mermaid/src/diagrams/flowchart/flowDb.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index 5abebc19f..94c6735c5 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -814,17 +814,17 @@ export const lex = { }; const getTypeFromVertex = (vertex: FlowVertex) => { - if (vertex?.img) { + if (vertex.img) { return 'imageSquare'; } - if (vertex?.icon) { - if (vertex?.form === 'circle') { + if (vertex.icon) { + if (vertex.form === 'circle') { return 'iconCircle'; } - if (vertex?.form === 'square') { + if (vertex.form === 'square') { return 'iconSquare'; } - if (vertex?.form === 'rounded') { + if (vertex.form === 'rounded') { return 'iconRounded'; } return 'icon'; From be9123ee2b9ecd1e6fc76825b8cff0b975bb1e88 Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Wed, 18 Sep 2024 13:10:07 +0530 Subject: [PATCH 05/11] Updated renderOptions to add direction property --- packages/mermaid-layout-elk/src/render.ts | 2 +- packages/mermaid/src/dagre-wrapper/index.js | 2 +- .../src/rendering-util/layout-algorithms/dagre/index.js | 2 +- .../src/rendering-util/rendering-elements/shapes/forkJoin.ts | 4 ++-- packages/mermaid/src/rendering-util/types.ts | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/mermaid-layout-elk/src/render.ts b/packages/mermaid-layout-elk/src/render.ts index 58be637ab..4e9f66a81 100644 --- a/packages/mermaid-layout-elk/src/render.ts +++ b/packages/mermaid-layout-elk/src/render.ts @@ -37,7 +37,7 @@ export const render = async ( // Add the element to the DOM if (!node.isGroup) { - const childNodeEl = await insertNode(nodeEl, node, { config }); + const childNodeEl = await insertNode(nodeEl, node, { config, dir: node.dir }); boundingBox = childNodeEl.node().getBBox(); child.domId = childNodeEl; child.width = boundingBox.width; diff --git a/packages/mermaid/src/dagre-wrapper/index.js b/packages/mermaid/src/dagre-wrapper/index.js index 76f3113df..86ae7e284 100644 --- a/packages/mermaid/src/dagre-wrapper/index.js +++ b/packages/mermaid/src/dagre-wrapper/index.js @@ -87,7 +87,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit // insertCluster(clusters, graph.node(v)); } else { log.info('Node - the non recursive path', v, node.id, node); - await insertNode(nodes, graph.node(v), { config: siteConfig }); + await insertNode(nodes, graph.node(v), { config: siteConfig, dir }); } } }) diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js index 6dbd62590..6f1fa7d3b 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js @@ -125,7 +125,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit // insertCluster(clusters, graph.node(v)); } else { log.trace('Node - the non recursive path XAX', v, nodes, graph.node(v), dir); - await insertNode(nodes, graph.node(v), { config: siteConfig }); + await insertNode(nodes, graph.node(v), { config: siteConfig, dir }); } } }) 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 2492412dc..fa735994f 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts @@ -1,11 +1,11 @@ import { getNodeClasses, updateNodeBounds } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '../../types.js'; +import type { Node, RenderOptions } from '../../types.js'; import type { SVG } from '../../../diagram-api/types.js'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; -export const forkJoin = (parent: SVG, node: Node, dir: string) => { +export const forkJoin = (parent: SVG, node: Node, { dir }: RenderOptions) => { const { nodeStyles } = styles2String(node); node.label = ''; const shapeSvg = parent diff --git a/packages/mermaid/src/rendering-util/types.ts b/packages/mermaid/src/rendering-util/types.ts index 0d24f6fdf..510e94b94 100644 --- a/packages/mermaid/src/rendering-util/types.ts +++ b/packages/mermaid/src/rendering-util/types.ts @@ -143,4 +143,5 @@ export type LayoutMethod = export interface RenderOptions { config: MermaidConfig; + dir: string; } From 741072a126432cec303ad44a8fb4dd98b8407def Mon Sep 17 00:00:00 2001 From: Ashish Jain Date: Wed, 18 Sep 2024 15:11:08 +0200 Subject: [PATCH 06/11] Fix new shapes tests with new syntax --- cypress/integration/rendering/newShapes.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/rendering/newShapes.spec.ts b/cypress/integration/rendering/newShapes.spec.ts index 0f539f09c..67d862ea4 100644 --- a/cypress/integration/rendering/newShapes.spec.ts +++ b/cypress/integration/rendering/newShapes.spec.ts @@ -60,7 +60,7 @@ looks.forEach((look) => { it(`without label`, () => { let flowchartCode = `flowchart ${direction}\n`; newShapesSet.forEach((newShape, index) => { - flowchartCode += ` n${index} --> n${index}${index}{ shape: ${newShape} }\n`; + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`; }); imgSnapshotTest(flowchartCode, { look }); }); From c8b9c4cebcc2a7dfb3872eddba29853bef80bfe0 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Wed, 18 Sep 2024 15:37:27 +0200 Subject: [PATCH 07/11] Adjusted styling for fork/note and stateEnd --- .../rendering-elements/shapes/forkJoin.ts | 17 ++++++++++++++--- .../rendering-elements/shapes/note.ts | 14 ++++++++++---- .../rendering-elements/shapes/stateEnd.ts | 15 +++++++++------ 3 files changed, 33 insertions(+), 13 deletions(-) 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 fa735994f..c6a34e929 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts @@ -5,7 +5,11 @@ import type { SVG } from '../../../diagram-api/types.js'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; -export const forkJoin = (parent: SVG, node: Node, { dir }: RenderOptions) => { +export const forkJoin = ( + parent: SVG, + node: Node, + { dir, config: { state, themeVariables } }: RenderOptions +) => { const { nodeStyles } = styles2String(node); node.label = ''; const shapeSvg = parent @@ -27,7 +31,10 @@ export const forkJoin = (parent: SVG, node: Node, { dir }: RenderOptions) => { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); - const options = userNodeOverrides(node, {}); + const options = userNodeOverrides(node, { + stroke: themeVariables.lineColor, + fill: themeVariables.lineColor, + }); if (node.look !== 'handDrawn') { options.roughness = 0; @@ -47,7 +54,11 @@ export const forkJoin = (parent: SVG, node: Node, { dir }: RenderOptions) => { } updateNodeBounds(node, shape); - + const padding = state?.padding ?? 0; + if (node.width && node.height) { + node.width += padding / 2 || 0; + node.height += padding / 2 || 0; + } node.intersect = function (point) { return intersect.rect(node, point); }; 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 516713ddc..2559c9b40 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts @@ -1,11 +1,15 @@ -import { log } from '../../../logger.js'; import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js'; import intersect from '../intersect/index.js'; import type { Node } from '../../types.js'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import type { RenderOptions } from '../../types'; -export const note = async (parent: SVGAElement, node: Node) => { +export const note = async ( + parent: SVGAElement, + node: Node, + { config: { themeVariables } }: RenderOptions +) => { const { labelStyles, nodeStyles } = styles2String(node); node.labelStyle = labelStyles; const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); @@ -19,11 +23,13 @@ export const note = async (parent: SVGAElement, node: Node) => { node.centerLabel = true; } - log.info('Classes = ', node.cssClasses); // add the rect // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); - const options = userNodeOverrides(node, {}); + const options = userNodeOverrides(node, { + fill: themeVariables.noteBkgColor, + stroke: themeVariables.noteBorderColor, + }); if (node.look !== 'handDrawn') { options.roughness = 0; 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 1fc554657..9c547f30f 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts @@ -3,7 +3,7 @@ import intersect from '../intersect/index.js'; import type { Node, RenderOptions } from '../../types.js'; import type { SVG } from '../../../diagram-api/types.js'; import rough from 'roughjs'; -import { solidStateFill, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; export const stateEnd = ( parent: SVG, @@ -13,7 +13,7 @@ export const stateEnd = ( const { labelStyles, nodeStyles } = styles2String(node); node.labelStyle = labelStyles; const { cssStyles } = node; - const { lineColor } = themeVariables; + const { lineColor, stateBorder, nodeBorder } = themeVariables; const shapeSvg = parent .insert('g') .attr('class', 'node default') @@ -29,14 +29,17 @@ export const stateEnd = ( } const roughNode = rc.circle(0, 0, 14, { - ...solidStateFill(lineColor), - roughness: 0.5, ...options, + stroke: lineColor, + strokeWidth: 2, }); + const innerFill = stateBorder ?? nodeBorder; const roughInnerNode = rc.circle(0, 0, 5, { - ...solidStateFill(lineColor), - fillStyle: 'solid', ...options, + fill: innerFill, + stroke: innerFill, + strokeWidth: 2, + fillStyle: 'solid', }); const circle = shapeSvg.insert(() => roughNode, ':first-child'); circle.insert(() => roughInnerNode); From c6410472c8a22b494544a89a5e824c3361ea57ac Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Wed, 18 Sep 2024 15:43:27 +0200 Subject: [PATCH 08/11] Import fix --- .../src/rendering-util/rendering-elements/shapes/note.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2559c9b40..bd36c7261 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts @@ -3,7 +3,7 @@ import intersect from '../intersect/index.js'; import type { Node } from '../../types.js'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; -import type { RenderOptions } from '../../types'; +import type { RenderOptions } from '../../types.js'; export const note = async ( parent: SVGAElement, From f035db2febde3aa8159265d1419509a98b14d7b5 Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Wed, 18 Sep 2024 21:40:55 +0530 Subject: [PATCH 09/11] fixed icon shape padding --- cypress/platform/saurabh.html | 14 +-- .../rendering-elements/shapes/icon.ts | 92 +++++++++---------- .../rendering-elements/shapes/iconCircle.ts | 54 +++++++---- .../rendering-elements/shapes/iconRounded.ts | 88 +++++++++--------- .../rendering-elements/shapes/iconSquare.ts | 86 ++++++++--------- 5 files changed, 175 insertions(+), 159 deletions(-) diff --git a/cypress/platform/saurabh.html b/cypress/platform/saurabh.html index b83aa2a3b..ecf3463c1 100644 --- a/cypress/platform/saurabh.html +++ b/cypress/platform/saurabh.html @@ -62,16 +62,18 @@
-      flowchart TD
-       B2@{ icon: "fa:bell", form: "square", pos: "t", h: 80 }
+      flowchart LR
+       B2@{ icon: "fa:address-book",  form: "square", pos: "b", h: 80 }
 
 
-       W --> B2
-       X --> B2
-       Y --> B2
-       Z --> B2
+       W --> B2 --> x1
+       X --> B2 --> x2
+       Y --> B2 --> x3
+       Z --> B2 --> x4 
        B2 --sas--> C
 
+       A --> B2
+
 
     
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts
index 051ae3119..f1c928346 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts
@@ -19,18 +19,20 @@ export const icon = async (
   const iconSize = Math.max(assetHeight, assetWidth);
   const defaultWidth = flowchart?.wrappingWidth;
   node.width = Math.max(iconSize, defaultWidth ?? 0);
-  const { nodeBorder } = themeVariables;
-  const { stylesMap } = compileStyles(node);
   const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'icon-shape default');
 
   const topLabel = node.pos === 't';
 
   const height = iconSize;
-  const width = Math.max(iconSize, bbox.width);
+  const width = iconSize;
+  const { nodeBorder } = themeVariables;
+  const { stylesMap } = compileStyles(node);
 
   const x = -width / 2;
   const y = -height / 2;
 
+  const labelPadding = node.label ? 8 : 0;
+
   // @ts-ignore - rough is not typed
   const rc = rough.svg(shapeSvg);
   const options = userNodeOverrides(node, { stroke: 'none', fill: 'none' });
@@ -42,7 +44,17 @@ export const icon = async (
 
   const iconNode = rc.rectangle(x, y, width, height, options);
 
+  const outerWidth = Math.max(width, bbox.width);
+  const outerHeight = height + bbox.height + labelPadding;
+
+  const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
+    ...options,
+    fill: 'none',
+    stroke: 'none',
+  });
+
   const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
+  const outerShape = shapeSvg.insert(() => outerNode);
 
   if (node.icon) {
     const iconElem = shapeSvg.append('g');
@@ -52,21 +64,26 @@ export const icon = async (
     const iconBBox = iconElem.node().getBBox();
     const iconWidth = iconBBox.width;
     const iconHeight = iconBBox.height;
+    const iconX = iconBBox.x;
+    const iconY = iconBBox.y;
     iconElem.attr(
       'transform',
-      `translate(${-iconWidth / 2},${topLabel ? height / 2 - iconHeight + bbox.height / 2 : -height / 2 - bbox.height / 2})`
+      `translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - iconY : -outerHeight / 2 - iconY})`
     );
     iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
   }
 
   label.attr(
     'transform',
-    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - 5 - bbox.height / 2 : height / 2 - bbox.height / 2})`
+    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
-  iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`);
+  iconShape.attr(
+    'transform',
+    `translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
+  );
 
-  updateNodeBounds(node, shapeSvg);
+  updateNodeBounds(node, outerShape);
 
   node.intersect = function (point) {
     log.info('iconSquare intersect', node, point);
@@ -75,51 +92,34 @@ export const icon = async (
     }
     const dx = node.x ?? 0;
     const dy = node.y ?? 0;
-    const nodeWidth = node.width ?? 0;
     const nodeHeight = node.height ?? 0;
-
+    let points = [];
     if (topLabel) {
-      const points = [
-        { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2,
-          y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2,
-          y: dy + nodeHeight / 2 - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width,
-          y: dy + nodeHeight / 2 - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width,
-          y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2,
-        },
-        { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 },
+      points = [
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
       ];
-      const pos = intersect.polygon(node, points, point);
-      return pos;
     } else {
-      const points = [
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy - nodeHeight / 2 },
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, y: dy - nodeHeight / 2 },
-        {
-          x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width,
-          y: dy - nodeHeight / 2 + height,
-        },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + height },
-        { x: dx + nodeWidth / 2, y: dy + nodeHeight / 2 },
-        { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 },
-        { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 - bbox.height },
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy + nodeHeight / 2 - bbox.height },
+      points = [
+        { x: dx - width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx - width / 2, y: dy - nodeHeight / 2 + height },
       ];
-      const pos = intersect.polygon(node, points, point);
-      return pos;
     }
+
+    const pos = intersect.polygon(node, points, point);
+    return pos;
   };
 
   return shapeSvg;
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts
index 2d0072d11..df7c55f53 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts
@@ -19,15 +19,13 @@ export const iconCircle = async (
   const iconSize = Math.max(assetHeight, assetWidth);
   const defaultWidth = flowchart?.wrappingWidth;
   node.width = Math.max(iconSize, defaultWidth ?? 0);
-  const { shapeSvg, bbox, halfPadding, label } = await labelHelper(
-    parent,
-    node,
-    'icon-shape default'
-  );
+  const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'icon-shape default');
+
+  const padding = 20;
+  const labelPadding = node.label ? 8 : 0;
 
   const topLabel = node.pos === 't';
 
-  const diameter = iconSize + halfPadding * 2;
   const { nodeBorder, mainBkg } = themeVariables;
   const { stylesMap } = compileStyles(node);
   // @ts-ignore - rough is not typed
@@ -39,32 +37,48 @@ export const iconCircle = async (
     options.fillStyle = 'solid';
   }
 
-  const iconNode = rc.circle(0, 0, diameter, options);
-
-  const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
   const iconElem = shapeSvg.append('g');
   if (node.icon) {
     iconElem.html(
       `${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}`
     );
-    const iconBBox = iconElem.node().getBBox();
-    const iconWidth = iconBBox.width;
-    const iconHeight = iconBBox.height;
-    iconElem.attr(
-      'transform',
-      `translate(${-iconWidth / 2},${topLabel ? diameter / 2 - iconHeight - halfPadding + bbox.height / 2 : -diameter / 2 + halfPadding - bbox.height / 2})`
-    );
-    iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
   }
+  const iconBBox = iconElem.node().getBBox();
+  const iconWidth = iconBBox.width;
+  const iconHeight = iconBBox.height;
+  const iconX = iconBBox.x;
+  const iconY = iconBBox.y;
 
+  const diameter = Math.max(iconWidth, iconHeight) + padding * 2;
+  const iconNode = rc.circle(0, 0, diameter, options);
+
+  const outerWidth = Math.max(diameter, bbox.width);
+  const outerHeight = diameter + bbox.height + labelPadding;
+
+  const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
+    ...options,
+    fill: 'none',
+    stroke: 'none',
+  });
+
+  const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
+  const outerShape = shapeSvg.insert(() => outerNode);
+  iconElem.attr(
+    'transform',
+    `translate(${-iconWidth / 2 - iconX},${topLabel ? diameter / 2 - iconHeight - padding + bbox.height / 2 - iconY : -diameter / 2 + padding - bbox.height / 2 - labelPadding / 2 - iconY})`
+  );
+  iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
   label.attr(
     'transform',
-    `translate(${-diameter / 2 + diameter / 2 - bbox.width / 2},${topLabel ? -diameter / 2 - bbox.height / 2 : diameter / 2 - bbox.height / 2})`
+    `translate(${-diameter / 2 + diameter / 2 - bbox.width / 2},${topLabel ? -diameter / 2 - bbox.height / 2 : diameter / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
-  iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`);
+  iconShape.attr(
+    'transform',
+    `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2 - labelPadding / 2})`
+  );
 
-  updateNodeBounds(node, shapeSvg);
+  updateNodeBounds(node, outerShape);
 
   node.intersect = function (point) {
     log.info('iconSquare intersect', node, point);
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts
index 8aca67682..1c5d46568 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts
@@ -1,6 +1,6 @@
 import { log } from '../../../logger.js';
 import { labelHelper, updateNodeBounds } from './util.js';
-import type { Node, RenderOptions } from '../../types.js';
+import type { Node, RenderOptions } from '../../types.d.ts';
 import type { SVG } from '../../../diagram-api/types.js';
 import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
 import rough from 'roughjs';
@@ -36,6 +36,8 @@ export const iconRounded = async (
   const x = -width / 2;
   const y = -height / 2;
 
+  const labelPadding = node.label ? 8 : 0;
+
   // @ts-ignore - rough is not typed
   const rc = rough.svg(shapeSvg);
   const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg });
@@ -47,7 +49,17 @@ export const iconRounded = async (
 
   const iconNode = rc.path(createRoundedRectPathD(x, y, width, height, 5), options);
 
+  const outerWidth = Math.max(width, bbox.width);
+  const outerHeight = height + bbox.height + labelPadding;
+
+  const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
+    ...options,
+    fill: 'none',
+    stroke: 'none',
+  });
+
   const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
+  const outerShape = shapeSvg.insert(() => outerNode);
 
   if (node.icon) {
     const iconElem = shapeSvg.append('g');
@@ -57,21 +69,26 @@ export const iconRounded = async (
     const iconBBox = iconElem.node().getBBox();
     const iconWidth = iconBBox.width;
     const iconHeight = iconBBox.height;
+    const iconX = iconBBox.x;
+    const iconY = iconBBox.y;
     iconElem.attr(
       'transform',
-      `translate(${-iconWidth / 2},${topLabel ? height / 2 - iconHeight - halfPadding + bbox.height / 2 : -height / 2 + halfPadding - bbox.height / 2})`
+      `translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - halfPadding - iconY : -outerHeight / 2 + halfPadding - iconY})`
     );
     iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
   }
 
   label.attr(
     'transform',
-    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - 5 - bbox.height / 2 : height / 2 - bbox.height / 2})`
+    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
-  iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`);
+  iconShape.attr(
+    'transform',
+    `translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
+  );
 
-  updateNodeBounds(node, shapeSvg);
+  updateNodeBounds(node, outerShape);
 
   node.intersect = function (point) {
     log.info('iconSquare intersect', node, point);
@@ -80,51 +97,34 @@ export const iconRounded = async (
     }
     const dx = node.x ?? 0;
     const dy = node.y ?? 0;
-    const nodeWidth = node.width ?? 0;
     const nodeHeight = node.height ?? 0;
-
+    let points = [];
     if (topLabel) {
-      const points = [
-        { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2,
-          y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2,
-          y: dy + nodeHeight / 2 - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width,
-          y: dy + nodeHeight / 2 - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width,
-          y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2,
-        },
-        { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 },
+      points = [
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
       ];
-      const pos = intersect.polygon(node, points, point);
-      return pos;
     } else {
-      const points = [
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy - nodeHeight / 2 },
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, y: dy - nodeHeight / 2 },
-        {
-          x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width,
-          y: dy - nodeHeight / 2 + height,
-        },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + height },
-        { x: dx + nodeWidth / 2, y: dy + nodeHeight / 2 },
-        { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 },
-        { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 - bbox.height },
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy + nodeHeight / 2 - bbox.height },
+      points = [
+        { x: dx - width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx - width / 2, y: dy - nodeHeight / 2 + height },
       ];
-      const pos = intersect.polygon(node, points, point);
-      return pos;
     }
+
+    const pos = intersect.polygon(node, points, point);
+    return pos;
   };
 
   return shapeSvg;
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts
index 9d0375874..b49d76cf6 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts
@@ -35,6 +35,8 @@ export const iconSquare = async (
   const x = -width / 2;
   const y = -height / 2;
 
+  const labelPadding = node.label ? 8 : 0;
+
   // @ts-ignore - rough is not typed
   const rc = rough.svg(shapeSvg);
   const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg });
@@ -46,7 +48,17 @@ export const iconSquare = async (
 
   const iconNode = rc.rectangle(x, y, width, height, options);
 
+  const outerWidth = Math.max(width, bbox.width);
+  const outerHeight = height + bbox.height + labelPadding;
+
+  const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
+    ...options,
+    fill: 'none',
+    stroke: 'none',
+  });
+
   const iconShape = shapeSvg.insert(() => iconNode, ':first-child');
+  const outerShape = shapeSvg.insert(() => outerNode);
 
   if (node.icon) {
     const iconElem = shapeSvg.append('g');
@@ -56,21 +68,26 @@ export const iconSquare = async (
     const iconBBox = iconElem.node().getBBox();
     const iconWidth = iconBBox.width;
     const iconHeight = iconBBox.height;
+    const iconX = iconBBox.x;
+    const iconY = iconBBox.y;
     iconElem.attr(
       'transform',
-      `translate(${-iconWidth / 2},${topLabel ? height / 2 - iconHeight - halfPadding + bbox.height / 2 : -height / 2 + halfPadding - bbox.height / 2})`
+      `translate(${-iconWidth / 2 - iconX},${topLabel ? outerHeight / 2 - iconHeight - halfPadding - iconY : -outerHeight / 2 + halfPadding - iconY})`
     );
     iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
   }
 
   label.attr(
     'transform',
-    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - 5 - bbox.height / 2 : height / 2 - bbox.height / 2})`
+    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
-  iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`);
+  iconShape.attr(
+    'transform',
+    `translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
+  );
 
-  updateNodeBounds(node, shapeSvg);
+  updateNodeBounds(node, outerShape);
 
   node.intersect = function (point) {
     log.info('iconSquare intersect', node, point);
@@ -79,51 +96,34 @@ export const iconSquare = async (
     }
     const dx = node.x ?? 0;
     const dy = node.y ?? 0;
-    const nodeWidth = node.width ?? 0;
     const nodeHeight = node.height ?? 0;
-
+    let points = [];
     if (topLabel) {
-      const points = [
-        { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2,
-          y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2,
-          y: dy + nodeHeight / 2 - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width,
-          y: dy + nodeHeight / 2 - bbox.height / 2,
-        },
-        {
-          x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width,
-          y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2,
-        },
-        { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 },
+      points = [
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
       ];
-      const pos = intersect.polygon(node, points, point);
-      return pos;
     } else {
-      const points = [
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy - nodeHeight / 2 },
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, y: dy - nodeHeight / 2 },
-        {
-          x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width,
-          y: dy - nodeHeight / 2 + height,
-        },
-        { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + height },
-        { x: dx + nodeWidth / 2, y: dy + nodeHeight / 2 },
-        { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 },
-        { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 - bbox.height },
-        { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy + nodeHeight / 2 - bbox.height },
+      points = [
+        { x: dx - width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + height },
+        { x: dx - width / 2, y: dy - nodeHeight / 2 + height },
       ];
-      const pos = intersect.polygon(node, points, point);
-      return pos;
     }
+
+    const pos = intersect.polygon(node, points, point);
+    return pos;
   };
 
   return shapeSvg;

From a52949318aa539e2d2e9375f1844450f21f34fa5 Mon Sep 17 00:00:00 2001
From: saurabhg772244 
Date: Wed, 18 Sep 2024 21:51:22 +0530
Subject: [PATCH 10/11] updated icon shapes

---
 .../src/rendering-util/rendering-elements/shapes/icon.ts        | 2 +-
 .../src/rendering-util/rendering-elements/shapes/iconCircle.ts  | 2 +-
 .../src/rendering-util/rendering-elements/shapes/iconRounded.ts | 2 +-
 .../src/rendering-util/rendering-elements/shapes/iconSquare.ts  | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts
index f1c928346..d7ad58de9 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts
@@ -75,7 +75,7 @@ export const icon = async (
 
   label.attr(
     'transform',
-    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
+    `translate(${-bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
   iconShape.attr(
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts
index df7c55f53..e7551ca65 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts
@@ -70,7 +70,7 @@ export const iconCircle = async (
   iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder);
   label.attr(
     'transform',
-    `translate(${-diameter / 2 + diameter / 2 - bbox.width / 2},${topLabel ? -diameter / 2 - bbox.height / 2 : diameter / 2 - bbox.height / 2 + labelPadding / 2})`
+    `translate(${-bbox.width / 2},${topLabel ? -diameter / 2 - bbox.height / 2 : diameter / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
   iconShape.attr(
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts
index 1c5d46568..0f5d6199d 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts
@@ -80,7 +80,7 @@ export const iconRounded = async (
 
   label.attr(
     'transform',
-    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
+    `translate(${-bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
   iconShape.attr(
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts
index b49d76cf6..cb465c031 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts
@@ -79,7 +79,7 @@ export const iconSquare = async (
 
   label.attr(
     'transform',
-    `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
+    `translate(${-bbox.width / 2},${topLabel ? -height / 2 - bbox.height / 2 - labelPadding / 2 : height / 2 - bbox.height / 2 + labelPadding / 2})`
   );
 
   iconShape.attr(

From cb85d50f6157ab9f7cdaeda50fbcba4467ce12eb Mon Sep 17 00:00:00 2001
From: omkarht 
Date: Wed, 18 Sep 2024 21:55:12 +0530
Subject: [PATCH 11/11] updated imageSquare Shape

---
 .../mermaid/src/diagrams/flowchart/flowDb.ts  |   4 +-
 .../rendering-elements/shapes/imageSquare.ts  | 140 +++++++++---------
 2 files changed, 74 insertions(+), 70 deletions(-)

diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts
index 94c6735c5..149dec92c 100644
--- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts
+++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts
@@ -146,7 +146,7 @@ export const addVertex = function (
     }
     if (doc?.icon) {
       vertex.icon = doc?.icon;
-      if (!doc.label) {
+      if (!doc.label?.trim() && vertex.text === id) {
         vertex.text = '';
       }
     }
@@ -158,7 +158,7 @@ export const addVertex = function (
     }
     if (doc?.img) {
       vertex.img = doc?.img;
-      if (!doc.label) {
+      if (!doc.label?.trim() && vertex.text === id) {
         vertex.text = '';
       }
     }
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts
index 2e2690c50..551223ef4 100644
--- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts
+++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts
@@ -1,15 +1,16 @@
 import { log } from '../../../logger.js';
 import { labelHelper, updateNodeBounds } from './util.js';
-import type { Node } from '../../types.js';
+import type { Node, RenderOptions } from '../../types.d.ts';
 import type { SVG } from '../../../diagram-api/types.js';
 import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
 import rough from 'roughjs';
 import intersect from '../intersect/index.js';
-import { createPathFromPoints } from './util.js';
-import { getConfig } from '../../../diagram-api/diagramAPI.js';
 
-export const imageSquare = async (parent: SVG, node: Node) => {
-  //image dimensions
+export const imageSquare = async (
+  parent: SVG,
+  node: Node,
+  { config: { flowchart } }: RenderOptions
+) => {
   const img = new Image();
   img.src = node?.img ?? '';
   await img.decode();
@@ -17,49 +18,26 @@ export const imageSquare = async (parent: SVG, node: Node) => {
   const imageNaturalWidth = Number(img.naturalWidth.toString().replace('px', ''));
   const imageNaturalHeight = Number(img.naturalHeight.toString().replace('px', ''));
 
-  const defaultWidth = getConfig().flowchart?.wrappingWidth;
+  const { labelStyles } = styles2String(node);
+
+  node.labelStyle = labelStyles;
+
+  const defaultWidth = flowchart?.wrappingWidth;
+
   const imageWidth = Math.max(
     node.label ? (defaultWidth ?? 0) : 0,
     node?.assetWidth ?? imageNaturalWidth
   );
   const imageHeight = node?.assetHeight ?? imageNaturalHeight;
-
-  const imagePoints = [
-    { x: -imageWidth / 2, y: -imageHeight },
-    { x: imageWidth / 2, y: -imageHeight },
-    { x: imageWidth / 2, y: 0 },
-    { x: -imageWidth / 2, y: 0 },
-  ];
-
-  //label dimensions
-  const { labelStyles, nodeStyles } = styles2String(node);
-  node.labelStyle = labelStyles;
-
-  // const { shapeSvg, bbox, halfPadding, label } = await labelHelper(
-  //   parent,
-  //   node,
-  //   'icon-shape default'
-  // );
-
-  const { cssStyles } = node;
-  // const defaultHeight = bbox.height;
-  // node.height = Math.max(node.height ?? 0, node.label ? (defaultHeight ?? 0) : 0, imageHeight);
-  const labelWidth = Math.max(node.width ?? 0, node.label ? (defaultWidth ?? 0) : 0, imageWidth);
-  node.width = node.label ? labelWidth : 0;
+  node.width = Math.max(imageWidth, defaultWidth ?? 0);
   const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'image-shape default');
 
-  // const width = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0);
-  const height = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0);
-  const labelHeight = node.label ? height : 0;
+  const topLabel = node.pos === 't';
 
-  const imagePosition = node?.pos ?? 'b';
+  const x = -imageWidth / 2;
+  const y = -imageHeight / 2;
 
-  const labelPoints = [
-    { x: -labelWidth / 2, y: 0 },
-    { x: labelWidth / 2, y: 0 },
-    { x: labelWidth / 2, y: labelHeight },
-    { x: -labelWidth / 2, y: labelHeight },
-  ];
+  const labelPadding = node.label ? 8 : 0;
 
   // @ts-ignore - rough is not typed
   const rc = rough.svg(shapeSvg);
@@ -70,18 +48,20 @@ export const imageSquare = async (parent: SVG, node: Node) => {
     options.fillStyle = 'solid';
   }
 
-  const imagePath = createPathFromPoints(imagePoints);
-  const imagePathNode = rc.path(imagePath, options);
+  const imageNode = rc.rectangle(x, y, imageWidth, imageHeight, options);
 
-  const linePath = createPathFromPoints(labelPoints);
-  const lineNode = rc.path(linePath, { ...options });
+  const outerWidth = Math.max(imageWidth, bbox.width);
+  const outerHeight = imageHeight + bbox.height + labelPadding;
 
-  const imageShape = shapeSvg.insert(() => lineNode, ':first-child').attr('opacity', 0);
-  imageShape.insert(() => imagePathNode, ':first-child');
+  const outerNode = rc.rectangle(-outerWidth / 2, -outerHeight / 2, outerWidth, outerHeight, {
+    ...options,
+    fill: 'none',
+    stroke: 'none',
+  });
 
-  imageShape.attr('transform', `translate(${0},${(imageHeight - labelHeight) / 2})`);
+  const iconShape = shapeSvg.insert(() => imageNode, ':first-child');
+  const outerShape = shapeSvg.insert(() => outerNode);
 
-  // Image operations
   if (node.img) {
     const image = shapeSvg.append('image');
 
@@ -91,34 +71,58 @@ export const imageSquare = async (parent: SVG, node: Node) => {
     image.attr('height', imageHeight);
     image.attr('preserveAspectRatio', 'none');
 
-    const yPos =
-      imagePosition === 'b' ? -imageHeight / 2 - labelHeight / 2 : (-imageHeight + labelHeight) / 2;
-    image.attr('transform', `translate(${-imageWidth / 2}, ${yPos})`);
+    image.attr(
+      'transform',
+      `translate(${-imageWidth / 2},${topLabel ? outerHeight / 2 - imageHeight : -outerHeight / 2})`
+    );
   }
 
-  if (cssStyles && node.look !== 'handDrawn') {
-    imageShape.selectAll('path').attr('style', cssStyles);
-  }
+  label.attr(
+    'transform',
+    `translate(${-bbox.width / 2},${topLabel ? -imageHeight / 2 - bbox.height / 2 - labelPadding / 2 : imageHeight / 2 - bbox.height / 2 + labelPadding / 2})`
+  );
 
-  if (nodeStyles && node.look !== 'handDrawn') {
-    imageShape.selectAll('path').attr('style', nodeStyles);
-  }
+  iconShape.attr(
+    'transform',
+    `translate(${0},${topLabel ? bbox.height / 2 + labelPadding / 2 : -bbox.height / 2 - labelPadding / 2})`
+  );
 
-  const yPos =
-    imagePosition === 'b'
-      ? (imageHeight + labelHeight) / 2 - bbox.height - (bbox.y - (bbox.top ?? 0))
-      : -(imageHeight + labelHeight) / 2 + (node?.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0));
-
-  label.attr('transform', `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${yPos})`);
-
-  updateNodeBounds(node, imageShape);
+  updateNodeBounds(node, outerShape);
 
   node.intersect = function (point) {
-    log.info('imageSquare intersect', node, point);
+    log.info('iconSquare intersect', node, point);
+    if (!node.label) {
+      return intersect.rect(node, point);
+    }
+    const dx = node.x ?? 0;
+    const dy = node.y ?? 0;
+    const nodeHeight = node.height ?? 0;
+    let points = [];
+    if (topLabel) {
+      points = [
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + imageWidth / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx + imageWidth / 2, y: dy + nodeHeight / 2 },
+        { x: dx - imageWidth / 2, y: dy + nodeHeight / 2 },
+        { x: dx - imageWidth / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + bbox.height + labelPadding },
+      ];
+    } else {
+      points = [
+        { x: dx - imageWidth / 2, y: dy - nodeHeight / 2 },
+        { x: dx + imageWidth / 2, y: dy - nodeHeight / 2 },
+        { x: dx + imageWidth / 2, y: dy - nodeHeight / 2 + imageHeight },
+        { x: dx + bbox.width / 2, y: dy - nodeHeight / 2 + imageHeight },
+        { x: dx + bbox.width / 2 / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy + nodeHeight / 2 },
+        { x: dx - bbox.width / 2, y: dy - nodeHeight / 2 + imageHeight },
+        { x: dx - imageWidth / 2, y: dy - nodeHeight / 2 + imageHeight },
+      ];
+    }
 
-    const combinedPoints = [...imagePoints, ...labelPoints];
-
-    const pos = intersect.polygon(node, combinedPoints, point);
+    const pos = intersect.polygon(node, points, point);
     return pos;
   };