mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-13 09:14:06 +01:00
Compare commits
9 Commits
develop
...
tooltip-po
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8d89db397 | ||
|
|
9448aec481 | ||
|
|
fcd2791b2d | ||
|
|
feed9d75bb | ||
|
|
f356836f71 | ||
|
|
ff15e51d2e | ||
|
|
ddd4763db2 | ||
|
|
6670ad7229 | ||
|
|
b4a5fe6c45 |
5
.changeset/tricky-lions-behave.md
Normal file
5
.changeset/tricky-lions-behave.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Correct tooltip placement to appear near hovered element
|
||||
@@ -1,4 +1,4 @@
|
||||
import { select, type Selection } from 'd3';
|
||||
import { select } from 'd3';
|
||||
import { log } from '../../logger.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import common from '../common/common.js';
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
import { createTooltip } from '../common/svgDrawCommon.js';
|
||||
import { ClassMember } from './classTypes.js';
|
||||
import type {
|
||||
ClassRelation,
|
||||
@@ -26,6 +27,7 @@ import type {
|
||||
} from './classTypes.js';
|
||||
import type { Node, Edge } from '../../rendering-util/types.js';
|
||||
import type { DiagramDB } from '../../diagram-api/types.js';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
const MERMAID_DOM_ID_PREFIX = 'classId-';
|
||||
let classCounter = 0;
|
||||
@@ -483,43 +485,45 @@ export class ClassDB implements DiagramDB {
|
||||
LOLLIPOP: 4,
|
||||
};
|
||||
|
||||
// Utility function to escape HTML meta-characters
|
||||
private escapeHtml(str: string): string {
|
||||
return str
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
private readonly setupToolTips = (element: Element) => {
|
||||
let tooltipElem: Selection<HTMLDivElement, unknown, HTMLElement, unknown> =
|
||||
select('.mermaidTooltip');
|
||||
// @ts-expect-error - Incorrect types
|
||||
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
||||
tooltipElem = select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
.style('opacity', 0);
|
||||
}
|
||||
const tooltipElem = createTooltip();
|
||||
|
||||
const svg = select(element).select('svg');
|
||||
|
||||
const nodes = svg.selectAll('g.node');
|
||||
const nodes = svg.selectAll('g').filter(function () {
|
||||
return select(this).attr('title') !== null;
|
||||
});
|
||||
|
||||
nodes
|
||||
.on('mouseover', (event: MouseEvent) => {
|
||||
const el = select(event.currentTarget as HTMLElement);
|
||||
const title = el.attr('title');
|
||||
// Don't try to draw a tooltip if no data is provided
|
||||
if (title === null) {
|
||||
if (!title) {
|
||||
return;
|
||||
}
|
||||
// @ts-ignore - getBoundingClientRect is not part of the d3 type definition
|
||||
const rect = this.getBoundingClientRect();
|
||||
|
||||
const rect = (event.currentTarget as Element).getBoundingClientRect();
|
||||
tooltipElem.transition().duration(200).style('opacity', '.9');
|
||||
tooltipElem
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
.html(DOMPurify.sanitize(title))
|
||||
.style('left', `${window.scrollX + rect.left + rect.width / 2}px`)
|
||||
.style('top', `${window.scrollY + rect.bottom + 4}px`);
|
||||
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', (event: MouseEvent) => {
|
||||
tooltipElem.transition().duration(500).style('opacity', 0);
|
||||
const el = select(event.currentTarget as HTMLElement);
|
||||
el.classed('hover', false);
|
||||
select(event.currentTarget as HTMLElement).classed('hover', false);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
import { select } from 'd3';
|
||||
import type { SVG, SVGGroup } from '../../diagram-api/types.js';
|
||||
import { lineBreakRegex } from './common.js';
|
||||
import type {
|
||||
@@ -135,3 +136,24 @@ export const getTextObj = (): TextObject => {
|
||||
};
|
||||
return testObject;
|
||||
};
|
||||
|
||||
export const createTooltip = () => {
|
||||
let tooltipElem = select<HTMLDivElement, unknown>('.mermaidTooltip');
|
||||
if (tooltipElem.empty()) {
|
||||
tooltipElem = select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
.style('opacity', 0)
|
||||
.style('position', 'absolute')
|
||||
.style('text-align', 'center')
|
||||
.style('max-width', '200px')
|
||||
.style('padding', '2px')
|
||||
.style('font-size', '12px')
|
||||
.style('background', '#ffffde')
|
||||
.style('border', '1px solid #333')
|
||||
.style('border-radius', '2px')
|
||||
.style('pointer-events', 'none')
|
||||
.style('z-index', '100');
|
||||
}
|
||||
return tooltipElem;
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
setDiagramTitle,
|
||||
getDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
import { createTooltip } from '../common/svgDrawCommon.js';
|
||||
import type {
|
||||
FlowClass,
|
||||
FlowEdge,
|
||||
@@ -26,7 +27,7 @@ import type {
|
||||
FlowVertex,
|
||||
FlowVertexTypeParam,
|
||||
} from './types.js';
|
||||
|
||||
import DOMPurify from 'dompurify';
|
||||
interface LinkData {
|
||||
id: string;
|
||||
}
|
||||
@@ -574,15 +575,7 @@ You have to call mermaid.initialize.`
|
||||
}
|
||||
|
||||
private setupToolTips(element: Element) {
|
||||
let tooltipElem = select('.mermaidTooltip');
|
||||
// @ts-ignore TODO: fix this
|
||||
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
||||
// @ts-ignore TODO: fix this
|
||||
tooltipElem = select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
.style('opacity', 0);
|
||||
}
|
||||
const tooltipElem = createTooltip();
|
||||
|
||||
const svg = select(element).select('svg');
|
||||
|
||||
@@ -603,7 +596,7 @@ You have to call mermaid.initialize.`
|
||||
.text(el.attr('title'))
|
||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||
.style('top', window.scrollY + rect.bottom + 'px');
|
||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||
tooltipElem.html(DOMPurify.sanitize(title));
|
||||
el.classed('hover', true);
|
||||
})
|
||||
.on('mouseout', (e: MouseEvent) => {
|
||||
|
||||
Reference in New Issue
Block a user