ui: add source toggle to mermaid and svg blocks (#24652)
* ui: add source toggle to mermaid and svg blocks Add a toggle button next to copy and preview that switches a rendered mermaid or svg block to its source code and back. The button is shared by both block types and the rendered view stays the default. The source view reuses the code block scroll container and the highlighted code element captured at transform time, so it matches the app code blocks without highlighting again. Make tall diagrams scroll like text code blocks: safe centering keeps the diagram centered when it fits and falls back to start alignment when it overflows, so the top stays reachable instead of clipping above. Keep the block header opaque and layered above the scrolled diagram, and ignore header clicks in the zoom handler, so a button click never falls through to the zoom dialog. * ui: transparent diagram block header, address review from @allozaur
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
DATA_ERROR_HANDLED_ATTR,
|
||||
BOOL_TRUE_STRING,
|
||||
SETTINGS_KEYS,
|
||||
CODE_BLOCK_HEADER_CLASS,
|
||||
MERMAID_WRAPPER_CLASS,
|
||||
MERMAID_BLOCK_CLASS,
|
||||
MERMAID_LANGUAGE,
|
||||
@@ -53,7 +54,11 @@
|
||||
SVG_TAG_PREFIX,
|
||||
SVG_SOURCE_ATTR,
|
||||
SVG_RENDERED_ATTR,
|
||||
SVG_INLINE_SHADOW_STYLE
|
||||
SVG_INLINE_SHADOW_STYLE,
|
||||
TOGGLE_SOURCE_BTN_CLASS,
|
||||
DIAGRAM_VIEW_MODE_ATTR,
|
||||
DIAGRAM_VIEW_RENDERED,
|
||||
DIAGRAM_VIEW_SOURCE
|
||||
} from '$lib/constants';
|
||||
import { ColorMode, UrlProtocol } from '$lib/enums';
|
||||
import { FileTypeText } from '$lib/enums/files.enums';
|
||||
@@ -501,6 +506,23 @@
|
||||
async function handleMermaidClick(event: MouseEvent) {
|
||||
const target = event.target as HTMLElement;
|
||||
|
||||
// Toggle a diagram block between its rendered view and its source view.
|
||||
// Shared by mermaid and svg, css drives the visibility from the wrapper mode.
|
||||
const toggleBtn = target.closest(`.${TOGGLE_SOURCE_BTN_CLASS}`);
|
||||
if (toggleBtn) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const wrapper = toggleBtn.closest(`.${MERMAID_WRAPPER_CLASS}, .${SVG_WRAPPER_CLASS}`);
|
||||
if (!wrapper) return;
|
||||
|
||||
const isSource = wrapper.getAttribute(DIAGRAM_VIEW_MODE_ATTR) === DIAGRAM_VIEW_SOURCE;
|
||||
const next = isSource ? DIAGRAM_VIEW_RENDERED : DIAGRAM_VIEW_SOURCE;
|
||||
wrapper.setAttribute(DIAGRAM_VIEW_MODE_ATTR, next);
|
||||
toggleBtn.setAttribute('aria-pressed', String(!isSource));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if clicking on copy or preview button in mermaid block
|
||||
const copyBtn = target.closest(`.${MERMAID_WRAPPER_CLASS} .copy-code-btn`);
|
||||
const previewBtn = target.closest(`.${MERMAID_WRAPPER_CLASS} .preview-code-btn`);
|
||||
@@ -573,6 +595,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
// A click on the header chrome targets the action buttons, never the
|
||||
// diagram. Guard so a header click can not fall through to the click to
|
||||
// zoom branches below, whatever the scroll position or stacking.
|
||||
if (target.closest(`.${CODE_BLOCK_HEADER_CLASS}`)) return;
|
||||
|
||||
// Open preview when clicking the svg block itself. A final block carries its
|
||||
// source, a streaming block does not and is mirrored live into the dialog.
|
||||
const svgEl = target.closest(`.${SVG_BLOCK_CLASS}`);
|
||||
|
||||
Reference in New Issue
Block a user