Expose reusable builder kit surfaces and email preset pack
This commit is contained in:
1 parent
e019ac34c8
commit
eb1875f0bc
20 files changed
+635
-4
No files matched your search
@@ -0,0 +1,33 @@
|
||||
const downloads = new WeakMap<HTMLElement, () => void>();
|
||||
|
||||
/** Keep a direct user-gesture fallback until replaced or the editor is removed. */
|
||||
export function offerBuilderDownload(host: HTMLElement, content: string, type: string, filename: string): void {
|
||||
const outlet = host.querySelector<HTMLElement>("[data-builder-download]");
|
||||
if (!outlet) throw new Error("Download outlet is unavailable");
|
||||
const url = URL.createObjectURL(new Blob([content], { type }));
|
||||
const link = host.ownerDocument.createElement("a");
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
link.textContent = `Download prepared file: ${filename}`;
|
||||
let disposed = false;
|
||||
const observer = new MutationObserver(() => { if (!host.isConnected) dispose(); });
|
||||
const dispose = () => {
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
observer.disconnect();
|
||||
URL.revokeObjectURL(url);
|
||||
link.remove();
|
||||
if (downloads.get(host) === dispose) downloads.delete(host);
|
||||
};
|
||||
try {
|
||||
downloads.get(host)?.();
|
||||
outlet.replaceChildren(link);
|
||||
observer.observe(host.ownerDocument.documentElement, { childList: true, subtree: true });
|
||||
downloads.set(host, dispose);
|
||||
} catch (error) {
|
||||
dispose();
|
||||
throw error;
|
||||
}
|
||||
// A blocked automatic click must not destroy the direct-click fallback.
|
||||
try { link.click(); } catch { /* The visible link remains available. */ }
|
||||
}
|
||||
Reference in new issue
Block a user