mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-13 04:34:21 -10:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5107fe8502 |
No files matched your search
@@ -484,6 +484,41 @@ describe("mermaid in the markdown preview", () => {
|
||||
expect(document.activeElement).toBe(button);
|
||||
});
|
||||
|
||||
it("redraws the full-screen view when the diagram is redrawn behind it", async () => {
|
||||
const html = document.documentElement;
|
||||
const previous = html.dataset.colorTheme;
|
||||
try {
|
||||
html.dataset.colorTheme = "one-dark";
|
||||
const root = preview(SEQ);
|
||||
await renderMermaidIn(root).done;
|
||||
root.querySelector<HTMLButtonElement>('[data-mermaid-tools] button[aria-label="Full screen"]')!.click();
|
||||
const overlay = document.querySelector<HTMLElement>("[data-mermaid-preview]")!;
|
||||
const pan = overlay.querySelector<HTMLElement>(".pan-zoom-content")!;
|
||||
const before = overlay.querySelector("svg")!;
|
||||
pan.parentElement!.dispatchEvent(
|
||||
new WheelEvent("wheel", { deltaY: -120, ctrlKey: true, bubbles: true, cancelable: true }),
|
||||
);
|
||||
const zoomed = pan.style.transform;
|
||||
|
||||
html.dataset.colorTheme = "solarized-dark";
|
||||
m.render.mockImplementationOnce(async (id: string) => ({ svg: `<svg id="${id}"><text>redrawn</text></svg>` }));
|
||||
await renderMermaidIn(root).done;
|
||||
const after = overlay.querySelector("svg")!;
|
||||
expect(after).not.toBe(before);
|
||||
expect(after.textContent).toBe("redrawn");
|
||||
expect(after.parentElement).toBe(pan);
|
||||
expect(pan.style.transform).toBe(zoomed);
|
||||
|
||||
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" }));
|
||||
html.dataset.colorTheme = "one-dark";
|
||||
await renderMermaidIn(root).done;
|
||||
expect(document.querySelector("[data-mermaid-preview]")).toBeNull();
|
||||
} finally {
|
||||
if (previous === undefined) delete html.dataset.colorTheme;
|
||||
else html.dataset.colorTheme = previous;
|
||||
}
|
||||
});
|
||||
|
||||
it("saves a diagram as a PNG through the file dialog", async () => {
|
||||
const context = { fillStyle: "", scale: vi.fn(), fillRect: vi.fn(), drawImage: vi.fn() };
|
||||
const getContext = vi
|
||||
|
||||
@@ -27,10 +27,12 @@ export function attachDiagramTools(block: HTMLElement, svg: SVGSVGElement): void
|
||||
tools.className = styles.tools!;
|
||||
tools.setAttribute(TOOLS_ATTR, "");
|
||||
tools.append(
|
||||
toolButton("fullscreen", tx("Full screen"), (button) => openDiagramPreview(svg, button)),
|
||||
toolButton("fullscreen", tx("Full screen"), (button) => openDiagramPreview(block, svg, button)),
|
||||
toolButton("download", tx("Download image"), () => void saveDiagram(svg)),
|
||||
);
|
||||
block.append(tools);
|
||||
// Redrawn (a theme change, an edit) while shown full screen: the preview follows.
|
||||
if (preview?.block === block) preview.redraw(svg);
|
||||
}
|
||||
|
||||
function toolButton(icon: ToolIcon, label: string, onClick: (button: HTMLButtonElement) => void): HTMLButtonElement {
|
||||
@@ -49,13 +51,15 @@ function toolButton(icon: ToolIcon, label: string, onClick: (button: HTMLButtonE
|
||||
}
|
||||
|
||||
let closeActive: (() => void) | null = null;
|
||||
/** The block shown full screen, and how to show its newest drawing. */
|
||||
let preview: { block: HTMLElement; redraw: (svg: SVGSVGElement) => void } | null = null;
|
||||
|
||||
/**
|
||||
* The diagram over the whole window, fitted and centered: drag pans it anywhere,
|
||||
* ⌘/Ctrl+wheel zooms, double-click resets. Escape (or a click outside, or Close)
|
||||
* returns to the page, with focus back on the button that opened it.
|
||||
*/
|
||||
function openDiagramPreview(svg: SVGSVGElement, returnTo?: HTMLElement): void {
|
||||
function openDiagramPreview(block: HTMLElement, svg: SVGSVGElement, returnTo?: HTMLElement): void {
|
||||
closeActive?.();
|
||||
const returnFocus = returnTo ?? (document.activeElement instanceof HTMLElement ? document.activeElement : null);
|
||||
const overlay = document.createElement("div");
|
||||
@@ -71,6 +75,7 @@ function openDiagramPreview(svg: SVGSVGElement, returnTo?: HTMLElement): void {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
if (closeActive === close) closeActive = null;
|
||||
if (preview?.redraw === redraw) preview = null;
|
||||
document.removeEventListener("keydown", onKey, true);
|
||||
layer.release();
|
||||
overlay.remove();
|
||||
@@ -93,7 +98,7 @@ function openDiagramPreview(svg: SVGSVGElement, returnTo?: HTMLElement): void {
|
||||
|
||||
const tools = document.createElement("div");
|
||||
tools.className = styles.previewTools!;
|
||||
const download = toolButton("download", tx("Download image"), () => void saveDiagram(svg));
|
||||
const download = toolButton("download", tx("Download image"), () => void saveDiagram(current));
|
||||
tools.append(download, toolButton("close", tx("Close"), close));
|
||||
overlay.append(tools);
|
||||
|
||||
@@ -106,7 +111,10 @@ function openDiagramPreview(svg: SVGSVGElement, returnTo?: HTMLElement): void {
|
||||
// The canvas fills the window: the fitted drawing is centred in it, and the
|
||||
// whole window stays a drag surface once zoomed in. Top rows stay free of it
|
||||
// so the Close and Download buttons never cover the drawing.
|
||||
const fitted = fittedCopy(svg, canvas.clientWidth, Math.max(1, canvas.clientHeight - 32));
|
||||
const fit = (next: SVGSVGElement) => fittedCopy(next, canvas.clientWidth, Math.max(1, canvas.clientHeight - 32));
|
||||
let current = svg;
|
||||
let shown = fit(svg);
|
||||
const fitted = shown;
|
||||
canvas.append(fitted);
|
||||
const width = Number(fitted.getAttribute("width"));
|
||||
const height = Number(fitted.getAttribute("height"));
|
||||
@@ -118,6 +126,14 @@ function openDiagramPreview(svg: SVGSVGElement, returnTo?: HTMLElement): void {
|
||||
y: (canvas.clientHeight - height) / 2,
|
||||
},
|
||||
});
|
||||
// In place, inside the pan/zoom layer, so the current pan and zoom stay.
|
||||
const redraw = (next: SVGSVGElement) => {
|
||||
current = next;
|
||||
const copy = fit(next);
|
||||
shown.replaceWith(copy);
|
||||
shown = copy;
|
||||
};
|
||||
preview = { block, redraw };
|
||||
closeActive = close;
|
||||
download.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user