/** * ReplyFlow embeddable widget. * Usage: */ (function () { if (window.__ReplyFlowWidgetLoaded) return; window.__ReplyFlowWidgetLoaded = true; const script = document.currentScript || document.querySelector('script[src*="widget.js"]'); const base = (script && script.src ? script.src.replace(/\/widget\.js(?:\?.*)?$/, "") : window.location.origin) || ""; const style = document.createElement("style"); style.textContent = ` #rf-launcher{position:fixed;right:20px;bottom:20px;z-index:99999; width:58px;height:58px;border-radius:50%;border:0;cursor:pointer; background:linear-gradient(135deg,#d4a24c,#e8c078);color:#1a1408; font:700 14px/1 Manrope,system-ui,sans-serif;box-shadow:0 12px 30px rgba(0,0,0,.35)} #rf-panel{position:fixed;right:20px;bottom:90px;z-index:99999;width:min(360px,calc(100vw - 24px)); height:min(520px,70vh);display:none;flex-direction:column;overflow:hidden; border-radius:18px;background:#16302b;color:#f3f0e8;border:1px solid rgba(243,240,232,.12); box-shadow:0 24px 60px rgba(0,0,0,.4);font:14px/1.4 Manrope,system-ui,sans-serif} #rf-panel.open{display:flex} #rf-head{padding:12px 14px;border-bottom:1px solid rgba(243,240,232,.12)} #rf-head strong{font-family:Syne,Manrope,sans-serif;letter-spacing:-.02em} #rf-msgs{flex:1;overflow:auto;padding:12px;display:flex;flex-direction:column;gap:8px} .rf-b{max-width:88%;padding:8px 10px;border-radius:12px;white-space:pre-wrap} .rf-u{align-self:flex-end;background:rgba(212,162,76,.22)} .rf-a{align-self:flex-start;background:rgba(255,255,255,.06);border:1px solid rgba(243,240,232,.1)} #rf-form{display:flex;gap:6px;padding:10px;border-top:1px solid rgba(243,240,232,.12)} #rf-form input{flex:1;border-radius:999px;border:1px solid rgba(243,240,232,.15); background:rgba(0,0,0,.25);color:#f3f0e8;padding:10px 12px;font:inherit} #rf-form button{border:0;border-radius:999px;padding:10px 12px;cursor:pointer; background:linear-gradient(135deg,#d4a24c,#e8c078);color:#1a1408;font-weight:700} `; document.head.appendChild(style); const launcher = document.createElement("button"); launcher.id = "rf-launcher"; launcher.type = "button"; launcher.setAttribute("aria-label", "Open ReplyFlow chat"); launcher.textContent = "RF"; const panel = document.createElement("div"); panel.id = "rf-panel"; panel.innerHTML = `
ReplyFlow
`; document.body.appendChild(panel); document.body.appendChild(launcher); const msgs = panel.querySelector("#rf-msgs"); const form = panel.querySelector("#rf-form"); const input = panel.querySelector("#rf-input"); let conversationId = null; let started = false; function bubble(role, text) { const el = document.createElement("div"); el.className = `rf-b ${role === "user" ? "rf-u" : "rf-a"}`; el.textContent = text; msgs.appendChild(el); msgs.scrollTop = msgs.scrollHeight; } async function start() { msgs.innerHTML = ""; const res = await fetch( `${base}/api/chat/start?ui_language=en`, { method: "POST" } ); const data = await res.json(); conversationId = data.conversation_id; bubble("assistant", data.greeting); started = true; } launcher.addEventListener("click", async () => { panel.classList.toggle("open"); if (panel.classList.contains("open") && !started) { await start(); } }); form.addEventListener("submit", async (e) => { e.preventDefault(); const text = input.value.trim(); if (!text || !conversationId) return; input.value = ""; bubble("user", text); const res = await fetch(`${base}/api/chat/message`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ conversation_id: conversationId, message: text, ui_language: "en", }), }); const data = await res.json(); bubble("assistant", data.reply || "…"); }); })();