const downloads = new WeakMap 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("[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. */ } }