Add native task metadata, working-day calendar settings, dependency scheduling and rich note editing. Support complete-sheet PNG export with resolution and transparency controls, preserve XMind extensions and update browser regressions.
95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
"use client";
|
|
|
|
import { Download, Loader2, X } from "lucide-react";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import type { ImageExportOptions } from "@/lib/flow-board/image-export";
|
|
|
|
export function XmindImageExport({
|
|
busy,
|
|
onExport,
|
|
onClose,
|
|
}: {
|
|
busy: boolean;
|
|
onExport: (
|
|
options: Pick<ImageExportOptions, "scale" | "transparent">
|
|
) => void;
|
|
onClose: () => void;
|
|
}) {
|
|
const dialog = useRef<HTMLDialogElement>(null);
|
|
const [scale, setScale] = useState<1 | 2 | 3>(2);
|
|
const [transparent, setTransparent] = useState(false);
|
|
useEffect(() => {
|
|
const node = dialog.current;
|
|
node?.showModal();
|
|
return () => node?.close();
|
|
}, []);
|
|
return (
|
|
<dialog
|
|
ref={dialog}
|
|
className="xmind-image-export"
|
|
aria-labelledby="image-export-title"
|
|
data-flow-board-shell-control="true"
|
|
onKeyDown={(event) => event.stopPropagation()}
|
|
onCancel={(event) => {
|
|
event.preventDefault();
|
|
if (!busy) onClose();
|
|
}}
|
|
>
|
|
<header>
|
|
<h2 id="image-export-title">导出图片</h2>
|
|
<button
|
|
type="button"
|
|
aria-label="关闭图片导出"
|
|
disabled={busy}
|
|
onClick={onClose}
|
|
>
|
|
<X size={18} />
|
|
</button>
|
|
</header>
|
|
<p>导出当前工作表的完整内容为 PNG 图片。</p>
|
|
<label className="xmind-image-export-field">
|
|
清晰度
|
|
<select
|
|
aria-label="图片清晰度"
|
|
value={scale}
|
|
disabled={busy}
|
|
onChange={(event) =>
|
|
setScale(Number(event.target.value) as 1 | 2 | 3)
|
|
}
|
|
>
|
|
<option value={1}>标准 · 1 倍</option>
|
|
<option value={2}>高清 · 2 倍</option>
|
|
<option value={3}>超清 · 3 倍</option>
|
|
</select>
|
|
</label>
|
|
<label className="xmind-image-export-check">
|
|
<input
|
|
type="checkbox"
|
|
checked={transparent}
|
|
disabled={busy}
|
|
onChange={(event) => setTransparent(event.target.checked)}
|
|
/>
|
|
透明背景
|
|
</label>
|
|
<footer>
|
|
<button type="button" disabled={busy} onClick={onClose}>
|
|
取消
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="xmind-primary-button"
|
|
disabled={busy}
|
|
onClick={() => onExport({ scale, transparent })}
|
|
>
|
|
{busy ? (
|
|
<Loader2 size={16} className="animate-spin" />
|
|
) : (
|
|
<Download size={16} />
|
|
)}
|
|
{busy ? "正在导出…" : "导出 PNG"}
|
|
</button>
|
|
</footer>
|
|
</dialog>
|
|
);
|
|
}
|