rowsky-chatbot-widget 1.0.5 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chatbot.mjs +161 -80
- package/dist/chatbot.umd.js +1 -1
- package/package.json +1 -1
package/dist/chatbot.mjs
CHANGED
|
@@ -37,69 +37,190 @@ const createWidgetAPI = (baseUrl) => {
|
|
|
37
37
|
captureLead: (token, leadData) => request("POST", "/widget/lead", leadData, token)
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
|
-
const
|
|
40
|
+
const STYLE_ID = "fluxia-widget-styles";
|
|
41
|
+
const CRITICAL_CSS = `
|
|
42
|
+
#fluxia-widget-root{all:initial;font-family:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:14px;line-height:1.5;color:#1f2937;--fw-header:#0f172a;--fw-white:#fff;--fw-green:#22c55e;--fw-red:#ef4444;--fw-red-dark:#dc2626;--fw-text:#1f2937;--fw-gray-100:#f3f4f6;--fw-gray-200:#e5e7eb;--fw-gray-300:#d1d5db;--fw-gray-bg:#fafbfc;--fw-radius:20px;--fw-shadow:0 20px 60px rgba(0,0,0,.25)}
|
|
43
|
+
#fluxia-widget-root *,#fluxia-widget-root *::before,#fluxia-widget-root *::after{box-sizing:border-box;margin:0;padding:0}
|
|
44
|
+
#fluxia-widget-root .fluxia-bubble{position:fixed;bottom:24px;right:24px;z-index:2147483646;width:60px;height:60px;border-radius:50%;border:none;background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 24px rgba(239,68,68,.5),0 0 0 4px rgba(255,255,255,.25);transition:transform .3s cubic-bezier(.34,1.56,.64,1),box-shadow .3s,opacity .25s;opacity:1}
|
|
45
|
+
#fluxia-widget-root .fluxia-bubble.fw-hidden{transform:scale(0);opacity:0;pointer-events:none}
|
|
46
|
+
#fluxia-widget-root .fluxia-bubble svg{width:28px;height:28px;fill:#fff;stroke:none}
|
|
47
|
+
#fluxia-widget-root .fluxia-chatbox{position:fixed;bottom:10px;right:10px;z-index:2147483647;width:400px;height:600px;max-height:calc(100vh - 120px);border-radius:var(--fw-radius);background:var(--fw-white);box-shadow:var(--fw-shadow);display:flex;flex-direction:column;overflow:hidden;transform-origin:bottom right;transform:scale(0) translateY(20px);opacity:0;pointer-events:none;transition:transform .35s cubic-bezier(.34,1.56,.64,1),opacity .25s}
|
|
48
|
+
#fluxia-widget-root .fluxia-chatbox.fw-open{transform:scale(1) translateY(0);opacity:1;pointer-events:auto}
|
|
49
|
+
#fluxia-widget-root .fluxia-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;background:var(--fw-header);color:var(--fw-white);flex-shrink:0;border-radius:var(--fw-radius) var(--fw-radius) 0 0}
|
|
50
|
+
#fluxia-widget-root .fluxia-header-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}
|
|
51
|
+
#fluxia-widget-root .fluxia-avatar{width:42px;height:42px;min-width:42px;border-radius:50%;background:rgba(255,255,255,.12);border:2px solid rgba(34,197,94,.5);display:flex;align-items:center;justify-content:center;font-size:20px;overflow:hidden;color:#fff}
|
|
52
|
+
#fluxia-widget-root .fluxia-avatar img{width:100%;height:100%;object-fit:cover;border-radius:50%}
|
|
53
|
+
#fluxia-widget-root .fluxia-header-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
|
|
54
|
+
#fluxia-widget-root .fluxia-title{font-weight:700;font-size:15px;color:var(--fw-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
55
|
+
#fluxia-widget-root .fluxia-status{font-size:12px;color:var(--fw-green);display:flex;align-items:center;gap:6px;font-weight:600}
|
|
56
|
+
#fluxia-widget-root .fluxia-status-dot{width:7px;height:7px;border-radius:50%;background:var(--fw-green);display:inline-block;animation:fw-pulse 2s ease-in-out infinite}
|
|
57
|
+
@keyframes fw-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(1.3)}}
|
|
58
|
+
#fluxia-widget-root .fluxia-close{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.08);border:none;color:var(--fw-white);cursor:pointer;border-radius:8px;transition:background .2s}
|
|
59
|
+
#fluxia-widget-root .fluxia-close:hover{background:rgba(255,255,255,.18)}
|
|
60
|
+
#fluxia-widget-root .fluxia-close svg{width:16px;height:16px}
|
|
61
|
+
#fluxia-widget-root .fluxia-messages{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;background:var(--fw-white)}
|
|
62
|
+
#fluxia-widget-root .fluxia-msg{max-width:82%;padding:10px 14px;font-size:13.5px;line-height:1.55;word-wrap:break-word;overflow-wrap:break-word;animation:fw-msgIn .3s ease-out}
|
|
63
|
+
@keyframes fw-msgIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
|
|
64
|
+
#fluxia-widget-root .fluxia-msg-assistant{align-self:flex-start;background:var(--fw-gray-100);color:var(--fw-text);border-radius:16px 16px 16px 4px}
|
|
65
|
+
#fluxia-widget-root .fluxia-msg-user{align-self:flex-end;background:var(--fw-header);color:var(--fw-white);border-radius:16px 16px 4px 16px}
|
|
66
|
+
#fluxia-widget-root .fluxia-msg-system{align-self:center;background:#fef3c7;color:#92400e;font-size:12px;padding:8px 14px;border-radius:8px;text-align:center;max-width:90%;border:1px solid #fde68a}
|
|
67
|
+
#fluxia-widget-root .fluxia-typing{display:flex;gap:5px;align-items:center;padding:4px 0}
|
|
68
|
+
#fluxia-widget-root .fluxia-typing-dot{width:7px;height:7px;border-radius:50%;background:#94a3b8;animation:fw-bounce 1.4s infinite ease-in-out}
|
|
69
|
+
#fluxia-widget-root .fluxia-typing-dot:nth-child(2){animation-delay:.16s}
|
|
70
|
+
#fluxia-widget-root .fluxia-typing-dot:nth-child(3){animation-delay:.32s}
|
|
71
|
+
@keyframes fw-bounce{0%,80%,100%{transform:scale(.7);opacity:.4}40%{transform:scale(1.1);opacity:1}}
|
|
72
|
+
#fluxia-widget-root .fluxia-input-area{padding:12px 14px;background:var(--fw-white);border-top:1px solid var(--fw-gray-200);display:flex;align-items:center;gap:10px;flex-shrink:0}
|
|
73
|
+
#fluxia-widget-root .fluxia-input{flex:1;border:1.5px solid var(--fw-gray-300);border-radius:24px;padding:10px 16px;font-size:13px;font-family:inherit;outline:none;color:var(--fw-text);background:var(--fw-gray-bg);transition:border-color .2s,box-shadow .2s}
|
|
74
|
+
#fluxia-widget-root .fluxia-input::placeholder{color:#9ca3af}
|
|
75
|
+
#fluxia-widget-root .fluxia-input:focus{border-color:var(--fw-header);background:var(--fw-white);box-shadow:0 0 0 3px rgba(15,23,42,.06)}
|
|
76
|
+
#fluxia-widget-root .fluxia-input:disabled{opacity:.5;cursor:not-allowed}
|
|
77
|
+
#fluxia-widget-root .fluxia-send{width:40px;height:40px;min-width:40px;border-radius:50%;background:var(--fw-red);color:var(--fw-white);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .2s,transform .2s;flex-shrink:0}
|
|
78
|
+
#fluxia-widget-root .fluxia-send:hover{background:var(--fw-red-dark);transform:scale(1.08)}
|
|
79
|
+
#fluxia-widget-root .fluxia-send:active{transform:scale(.92)}
|
|
80
|
+
#fluxia-widget-root .fluxia-send:disabled{opacity:.4;cursor:not-allowed;transform:none}
|
|
81
|
+
#fluxia-widget-root .fluxia-send svg{width:18px;height:18px}
|
|
82
|
+
#fluxia-widget-root .fluxia-powered{text-align:center;padding:8px 0;font-size:11px;color:#9ca3af;background:var(--fw-white);border-top:1px solid var(--fw-gray-200);flex-shrink:0}
|
|
83
|
+
#fluxia-widget-root .fluxia-powered a{color:#6b7280;text-decoration:none;font-weight:600}
|
|
84
|
+
#fluxia-widget-root[data-position="left"] .fluxia-bubble{left:24px;right:auto}
|
|
85
|
+
#fluxia-widget-root[data-position="left"] .fluxia-chatbox{left:24px;right:auto;transform-origin:bottom left}
|
|
86
|
+
@media(max-width:768px){#fluxia-widget-root .fluxia-chatbox{width:calc(100vw - 32px);max-width:400px;height:calc(100vh - 140px);max-height:600px;bottom:10px;right:10px}#fluxia-widget-root .fluxia-bubble{bottom:20px;right:16px;width:56px;height:56px}}
|
|
87
|
+
@media(max-width:480px){#fluxia-widget-root .fluxia-chatbox{position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;max-width:none;max-height:none;border-radius:0;transform-origin:bottom center}#fluxia-widget-root .fluxia-chatbox.fw-open{border-radius:0}#fluxia-widget-root .fluxia-header{border-radius:0}#fluxia-widget-root .fluxia-bubble{bottom:16px;right:16px;width:52px;height:52px}#fluxia-widget-root .fluxia-bubble svg{width:24px;height:24px}#fluxia-widget-root .fluxia-avatar{width:38px;height:38px;min-width:38px}#fluxia-widget-root .fluxia-title{font-size:14px}#fluxia-widget-root .fluxia-msg{max-width:88%;font-size:13px}#fluxia-widget-root .fluxia-input{font-size:14px}#fluxia-widget-root .fluxia-send{width:38px;height:38px;min-width:38px}}
|
|
88
|
+
`;
|
|
89
|
+
const injectStyles = () => {
|
|
90
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
91
|
+
const el = document.createElement("style");
|
|
92
|
+
el.id = STYLE_ID;
|
|
93
|
+
el.textContent = CRITICAL_CSS;
|
|
94
|
+
document.head.appendChild(el);
|
|
95
|
+
};
|
|
96
|
+
const esc = (str) => {
|
|
97
|
+
const d = document.createElement("div");
|
|
98
|
+
d.textContent = str;
|
|
99
|
+
return d.innerHTML;
|
|
100
|
+
};
|
|
101
|
+
function widgetHTML({ botName, botAvatar }) {
|
|
102
|
+
const avatar = botAvatar ? `<img src="${esc(botAvatar)}" alt="Avatar" />` : "🤖";
|
|
103
|
+
return `
|
|
104
|
+
<button class="fluxia-bubble" aria-label="Abrir chat" title="Abrir chat">
|
|
105
|
+
<svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
|
106
|
+
</button>
|
|
107
|
+
|
|
108
|
+
<div class="fluxia-chatbox" role="dialog" aria-label="Chat">
|
|
109
|
+
<div class="fluxia-header">
|
|
110
|
+
<div class="fluxia-header-info">
|
|
111
|
+
<div class="fluxia-avatar">${avatar}</div>
|
|
112
|
+
<div class="fluxia-header-text">
|
|
113
|
+
<div class="fluxia-title">${botName}</div>
|
|
114
|
+
<div class="fluxia-status">
|
|
115
|
+
<span class="fluxia-status-dot"></span>
|
|
116
|
+
Online agora
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
<button class="fluxia-close" aria-label="Fechar chat" title="Fechar">
|
|
121
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
|
|
122
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
123
|
+
</svg>
|
|
124
|
+
</button>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<div class="fluxia-messages"></div>
|
|
128
|
+
|
|
129
|
+
<div class="fluxia-input-area">
|
|
130
|
+
<input class="fluxia-input" type="text"
|
|
131
|
+
placeholder="Pergunte sobre leads, métricas ou integrações"
|
|
132
|
+
autocomplete="off" />
|
|
133
|
+
<button class="fluxia-send" title="Enviar">
|
|
134
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"
|
|
135
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
136
|
+
<line x1="22" y1="2" x2="11" y2="13"/>
|
|
137
|
+
<polygon points="22 2 15 22 11 13 2 9 22 2"/>
|
|
138
|
+
</svg>
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<div class="fluxia-powered">
|
|
143
|
+
Powered by <a href="https://rowsky.com.br/" target="_blank" rel="noopener">Rowsky</a>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
const renderWidget = async ({ config, token, api, visitorId, botId }) => {
|
|
149
|
+
injectStyles();
|
|
41
150
|
const theme = config.theme || {};
|
|
42
|
-
const primaryColor = theme.primaryColor || "#dc2626";
|
|
43
151
|
const position = theme.position || "right";
|
|
44
152
|
const botName = config.botName || config.name || "Assistente";
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
153
|
+
const botAvatar = config.botAvatar || "";
|
|
154
|
+
const customCss = config.customCss || "";
|
|
155
|
+
const root = document.createElement("div");
|
|
156
|
+
root.id = "fluxia-widget-root";
|
|
157
|
+
root.dataset.position = position;
|
|
158
|
+
root.innerHTML = widgetHTML({ botName: esc(botName), botAvatar });
|
|
159
|
+
document.body.appendChild(root);
|
|
160
|
+
if (customCss && customCss.trim()) {
|
|
161
|
+
const s = document.createElement("style");
|
|
162
|
+
s.id = "fluxia-widget-custom";
|
|
163
|
+
s.textContent = customCss;
|
|
164
|
+
document.head.appendChild(s);
|
|
165
|
+
}
|
|
166
|
+
const bubble = root.querySelector(".fluxia-bubble");
|
|
167
|
+
const chatbox = root.querySelector(".fluxia-chatbox");
|
|
168
|
+
const closeBtn = root.querySelector(".fluxia-close");
|
|
169
|
+
const input = root.querySelector(".fluxia-input");
|
|
170
|
+
const sendBtn = root.querySelector(".fluxia-send");
|
|
171
|
+
const messages = root.querySelector(".fluxia-messages");
|
|
62
172
|
if (config.initialMessage) {
|
|
63
|
-
|
|
173
|
+
addMsg("assistant", config.initialMessage);
|
|
64
174
|
}
|
|
65
|
-
bubble.addEventListener("click", () =>
|
|
66
|
-
closeBtn.addEventListener("click", () =>
|
|
67
|
-
sendBtn.addEventListener("click",
|
|
175
|
+
bubble.addEventListener("click", () => open());
|
|
176
|
+
closeBtn.addEventListener("click", () => close());
|
|
177
|
+
sendBtn.addEventListener("click", send);
|
|
68
178
|
input.addEventListener("keydown", (e) => {
|
|
69
179
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
70
180
|
e.preventDefault();
|
|
71
|
-
|
|
181
|
+
send();
|
|
72
182
|
}
|
|
73
183
|
});
|
|
74
|
-
function
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
184
|
+
function open() {
|
|
185
|
+
bubble.classList.add("fw-hidden");
|
|
186
|
+
chatbox.classList.add("fw-open");
|
|
187
|
+
setTimeout(() => input.focus(), 350);
|
|
188
|
+
}
|
|
189
|
+
function close() {
|
|
190
|
+
chatbox.classList.remove("fw-open");
|
|
191
|
+
setTimeout(() => bubble.classList.remove("fw-hidden"), 300);
|
|
78
192
|
}
|
|
79
|
-
function
|
|
193
|
+
function addMsg(role, content) {
|
|
80
194
|
const div = document.createElement("div");
|
|
81
195
|
div.className = `fluxia-msg fluxia-msg-${role}`;
|
|
82
196
|
div.textContent = content;
|
|
83
|
-
|
|
84
|
-
|
|
197
|
+
messages.appendChild(div);
|
|
198
|
+
messages.scrollTop = messages.scrollHeight;
|
|
85
199
|
}
|
|
86
|
-
async function
|
|
200
|
+
async function send() {
|
|
87
201
|
const text = input.value.trim();
|
|
88
202
|
if (!text) return;
|
|
89
203
|
input.value = "";
|
|
90
204
|
input.disabled = true;
|
|
91
205
|
sendBtn.disabled = true;
|
|
92
|
-
|
|
206
|
+
addMsg("user", text);
|
|
207
|
+
const loader = document.createElement("div");
|
|
208
|
+
loader.className = "fluxia-msg fluxia-msg-assistant";
|
|
209
|
+
loader.innerHTML = '<div class="fluxia-typing"><div class="fluxia-typing-dot"></div><div class="fluxia-typing-dot"></div><div class="fluxia-typing-dot"></div></div>';
|
|
210
|
+
messages.appendChild(loader);
|
|
211
|
+
messages.scrollTop = messages.scrollHeight;
|
|
93
212
|
try {
|
|
94
213
|
const result = await api.sendMessage(token, text);
|
|
214
|
+
loader.remove();
|
|
95
215
|
if (result.reply) {
|
|
96
|
-
|
|
216
|
+
addMsg("assistant", result.reply.content);
|
|
97
217
|
}
|
|
98
218
|
} catch (err) {
|
|
219
|
+
loader.remove();
|
|
99
220
|
if (err.status === 401) {
|
|
100
|
-
|
|
221
|
+
addMsg("system", "Sessão expirada. Recarregue a página.");
|
|
101
222
|
} else {
|
|
102
|
-
|
|
223
|
+
addMsg("system", "Erro ao enviar mensagem. Tente novamente.");
|
|
103
224
|
}
|
|
104
225
|
console.error("[Fluxia]", err);
|
|
105
226
|
} finally {
|
|
@@ -109,47 +230,8 @@ const renderWidget = ({ config, token, api, visitorId, botId }) => {
|
|
|
109
230
|
}
|
|
110
231
|
}
|
|
111
232
|
};
|
|
112
|
-
function getWidgetHTML({ botName }) {
|
|
113
|
-
return `
|
|
114
|
-
<div id="fluxia-bubble" class="fluxia-bubble" aria-label="Abrir chat" role="button">
|
|
115
|
-
💬
|
|
116
|
-
</div>
|
|
117
|
-
|
|
118
|
-
<div id="fluxia-chatbox" class="fluxia-chatbox" role="dialog" aria-live="polite">
|
|
119
|
-
<div class="fluxia-header">
|
|
120
|
-
<div class="fluxia-header-info">
|
|
121
|
-
<div class="fluxia-avatar">🤖</div>
|
|
122
|
-
<div>
|
|
123
|
-
<div class="fluxia-title">${botName}</div>
|
|
124
|
-
<div class="fluxia-status">Online</div>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
<button id="fluxia-close" class="fluxia-close" aria-label="Fechar">✕</button>
|
|
128
|
-
</div>
|
|
129
|
-
|
|
130
|
-
<div id="fluxia-messages" class="fluxia-messages"></div>
|
|
131
|
-
|
|
132
|
-
<div class="fluxia-input-area">
|
|
133
|
-
<input id="fluxia-input" class="fluxia-input" type="text" placeholder="Digite sua mensagem..." />
|
|
134
|
-
<button id="fluxia-send" class="fluxia-send">Enviar</button>
|
|
135
|
-
</div>
|
|
136
|
-
</div>
|
|
137
|
-
`;
|
|
138
|
-
}
|
|
139
|
-
const cssText = '/* Estilos do widget Fluxia — injetados inline no bundle */\r\n\r\n.fluxia-widget {\r\n --fluxia-primary: #dc2626;\r\n --fluxia-radius: 16px;\r\n --fluxia-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);\r\n --fluxia-text: #0f172a;\r\n --fluxia-muted: #64748b;\r\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\r\n}\r\n\r\n.fluxia-widget * {\r\n box-sizing: border-box;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n.fluxia-bubble {\r\n position: fixed;\r\n bottom: 20px;\r\n z-index: 99999;\r\n width: 56px;\r\n height: 56px;\r\n border-radius: 50%;\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);\r\n font-size: 24px;\r\n transition: transform 0.2s;\r\n}\r\n\r\n.fluxia-bubble:hover {\r\n transform: scale(1.1);\r\n}\r\n\r\n.fluxia-chatbox {\r\n display: none;\r\n position: fixed;\r\n bottom: 90px;\r\n z-index: 99999;\r\n width: 370px;\r\n height: 520px;\r\n border-radius: var(--fluxia-radius);\r\n background: #fff;\r\n box-shadow: var(--fluxia-shadow);\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n.fluxia-widget[data-position="left"] .fluxia-bubble,\r\n.fluxia-widget[data-position="left"] .fluxia-chatbox {\r\n left: 20px;\r\n right: auto;\r\n}\r\n\r\n.fluxia-widget[data-position="right"] .fluxia-bubble,\r\n.fluxia-widget[data-position="right"] .fluxia-chatbox {\r\n right: 20px;\r\n left: auto;\r\n}\r\n\r\n.fluxia-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 14px 16px;\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n}\r\n\r\n.fluxia-header-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.fluxia-avatar {\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n background: rgba(255, 255, 255, 0.2);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 16px;\r\n}\r\n\r\n.fluxia-title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n}\r\n\r\n.fluxia-status {\r\n font-size: 11px;\r\n opacity: 0.8;\r\n}\r\n\r\n.fluxia-close {\r\n background: none;\r\n border: none;\r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n padding: 4px;\r\n}\r\n\r\n.fluxia-messages {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.fluxia-input-area {\r\n padding: 12px;\r\n border-top: 1px solid #e5e7eb;\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.fluxia-input {\r\n flex: 1;\r\n border: 1px solid #d1d5db;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n font-size: 13px;\r\n outline: none;\r\n}\r\n\r\n.fluxia-send {\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 14px;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-weight: 600;\r\n}\r\n\r\n.fluxia-msg {\r\n max-width: 80%;\r\n padding: 10px 14px;\r\n border-radius: 12px;\r\n font-size: 13px;\r\n line-height: 1.5;\r\n word-wrap: break-word;\r\n}\r\n\r\n.fluxia-msg-user {\r\n align-self: flex-end;\r\n background: #f1f5f9;\r\n color: #1e293b;\r\n border-bottom-right-radius: 4px;\r\n}\r\n\r\n.fluxia-msg-assistant {\r\n align-self: flex-start;\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n border-bottom-left-radius: 4px;\r\n}\r\n\r\n.fluxia-msg-system {\r\n align-self: center;\r\n background: #fef3c7;\r\n color: #92400e;\r\n font-size: 12px;\r\n border-radius: 8px;\r\n text-align: center;\r\n}\r\n';
|
|
140
233
|
const VISITOR_ID_KEY = "fluxia_visitor_id";
|
|
141
|
-
const
|
|
142
|
-
const injectStyles = () => {
|
|
143
|
-
if (document.getElementById(STYLE_TAG_ID)) return;
|
|
144
|
-
if (!cssText.trim()) {
|
|
145
|
-
console.warn("[Fluxia] CSS nao carregado. Verifique o build.");
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
const style = document.createElement("style");
|
|
149
|
-
style.id = STYLE_TAG_ID;
|
|
150
|
-
style.textContent = cssText;
|
|
151
|
-
document.head.appendChild(style);
|
|
152
|
-
};
|
|
234
|
+
const scriptFromLoad = document.currentScript;
|
|
153
235
|
const getVisitorId = () => {
|
|
154
236
|
let id = null;
|
|
155
237
|
try {
|
|
@@ -166,10 +248,10 @@ const getVisitorId = () => {
|
|
|
166
248
|
return id;
|
|
167
249
|
};
|
|
168
250
|
const getScriptConfig = () => {
|
|
169
|
-
const script = document.currentScript || document.querySelector("script[data-bot-id]");
|
|
251
|
+
const script = scriptFromLoad || document.currentScript || document.querySelector("script[data-client-id], script[data-bot-id]");
|
|
170
252
|
if (!script) {
|
|
171
253
|
console.error(
|
|
172
|
-
"[Fluxia] Script tag não encontrada. Use data-bot-id
|
|
254
|
+
"[Fluxia] Script tag não encontrada. Use data-client-id OU data-bot-id + data-public-key."
|
|
173
255
|
);
|
|
174
256
|
return null;
|
|
175
257
|
}
|
|
@@ -193,7 +275,6 @@ const getScriptConfig = () => {
|
|
|
193
275
|
const init = async () => {
|
|
194
276
|
const config = getScriptConfig();
|
|
195
277
|
if (!config) return;
|
|
196
|
-
injectStyles();
|
|
197
278
|
const visitorId = getVisitorId();
|
|
198
279
|
const api = createWidgetAPI(config.apiBase);
|
|
199
280
|
try {
|
|
@@ -225,7 +306,7 @@ const init = async () => {
|
|
|
225
306
|
if (!botConfig) {
|
|
226
307
|
botConfig = await api.getConfig(token);
|
|
227
308
|
}
|
|
228
|
-
renderWidget({
|
|
309
|
+
await renderWidget({
|
|
229
310
|
config: botConfig,
|
|
230
311
|
token,
|
|
231
312
|
api,
|
package/dist/chatbot.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(n){"function"==typeof define&&define.amd?define(n):n()}(function(){"use strict";const n='/* Estilos do widget Fluxia — injetados inline no bundle */\r\n\r\n.fluxia-widget {\r\n --fluxia-primary: #dc2626;\r\n --fluxia-radius: 16px;\r\n --fluxia-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);\r\n --fluxia-text: #0f172a;\r\n --fluxia-muted: #64748b;\r\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\r\n}\r\n\r\n.fluxia-widget * {\r\n box-sizing: border-box;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n.fluxia-bubble {\r\n position: fixed;\r\n bottom: 20px;\r\n z-index: 99999;\r\n width: 56px;\r\n height: 56px;\r\n border-radius: 50%;\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);\r\n font-size: 24px;\r\n transition: transform 0.2s;\r\n}\r\n\r\n.fluxia-bubble:hover {\r\n transform: scale(1.1);\r\n}\r\n\r\n.fluxia-chatbox {\r\n display: none;\r\n position: fixed;\r\n bottom: 90px;\r\n z-index: 99999;\r\n width: 370px;\r\n height: 520px;\r\n border-radius: var(--fluxia-radius);\r\n background: #fff;\r\n box-shadow: var(--fluxia-shadow);\r\n flex-direction: column;\r\n overflow: hidden;\r\n}\r\n\r\n.fluxia-widget[data-position="left"] .fluxia-bubble,\r\n.fluxia-widget[data-position="left"] .fluxia-chatbox {\r\n left: 20px;\r\n right: auto;\r\n}\r\n\r\n.fluxia-widget[data-position="right"] .fluxia-bubble,\r\n.fluxia-widget[data-position="right"] .fluxia-chatbox {\r\n right: 20px;\r\n left: auto;\r\n}\r\n\r\n.fluxia-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 14px 16px;\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n}\r\n\r\n.fluxia-header-info {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.fluxia-avatar {\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n background: rgba(255, 255, 255, 0.2);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 16px;\r\n}\r\n\r\n.fluxia-title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n}\r\n\r\n.fluxia-status {\r\n font-size: 11px;\r\n opacity: 0.8;\r\n}\r\n\r\n.fluxia-close {\r\n background: none;\r\n border: none;\r\n color: #fff;\r\n font-size: 20px;\r\n cursor: pointer;\r\n padding: 4px;\r\n}\r\n\r\n.fluxia-messages {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 16px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.fluxia-input-area {\r\n padding: 12px;\r\n border-top: 1px solid #e5e7eb;\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.fluxia-input {\r\n flex: 1;\r\n border: 1px solid #d1d5db;\r\n border-radius: 8px;\r\n padding: 8px 12px;\r\n font-size: 13px;\r\n outline: none;\r\n}\r\n\r\n.fluxia-send {\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n border: none;\r\n border-radius: 8px;\r\n padding: 8px 14px;\r\n cursor: pointer;\r\n font-size: 13px;\r\n font-weight: 600;\r\n}\r\n\r\n.fluxia-msg {\r\n max-width: 80%;\r\n padding: 10px 14px;\r\n border-radius: 12px;\r\n font-size: 13px;\r\n line-height: 1.5;\r\n word-wrap: break-word;\r\n}\r\n\r\n.fluxia-msg-user {\r\n align-self: flex-end;\r\n background: #f1f5f9;\r\n color: #1e293b;\r\n border-bottom-right-radius: 4px;\r\n}\r\n\r\n.fluxia-msg-assistant {\r\n align-self: flex-start;\r\n background: var(--fluxia-primary);\r\n color: #fff;\r\n border-bottom-left-radius: 4px;\r\n}\r\n\r\n.fluxia-msg-system {\r\n align-self: center;\r\n background: #fef3c7;\r\n color: #92400e;\r\n font-size: 12px;\r\n border-radius: 8px;\r\n text-align: center;\r\n}\r\n',r="fluxia_visitor_id",e="fluxia-widget-styles",i=async()=>{const i=(()=>{const n=document.currentScript||document.querySelector("script[data-bot-id]");if(!n)return console.error("[Fluxia] Script tag não encontrada. Use data-bot-id e data-public-key."),null;const r=n.getAttribute("data-bot-id"),e=n.getAttribute("data-public-key"),i=n.getAttribute("data-client-id"),t=n.getAttribute("data-api-base")||"";return t&&(i||r&&e)?{botId:r?Number(r):null,publicKey:e||"",clientId:i||"",apiBase:t.replace(/\/$/,"")}:(console.error("[Fluxia] Atributos obrigatorios: data-api-base e (data-client-id OU data-bot-id + data-public-key)"),null)})();if(!i)return;(()=>{if(document.getElementById(e))return;if(!n.trim())return void console.warn("[Fluxia] CSS nao carregado. Verifique o build.");const r=document.createElement("style");r.id=e,r.textContent=n,document.head.appendChild(r)})();const t=(()=>{let n=null;try{n=localStorage.getItem(r)}catch{}if(!n){n="v_"+crypto.randomUUID();try{localStorage.setItem(r,n)}catch{}}return n})(),a=(n=>{const r=async(r,e,i=null,t=null)=>{const a={"Content-Type":"application/json"};t&&(a.Authorization=`Bearer ${t}`);const o={method:r,headers:a};i&&(o.body=JSON.stringify(i));const l=await fetch(`${n}${e}`,o);if(!l.ok){const n=await l.json().catch(()=>({})),r=new Error(n.error||`HTTP ${l.status}`);throw r.status=l.status,r.data=n,r}return l.json()};return{bootstrap:({clientId:n,visitorId:e})=>r("POST","/widget/bootstrap",{clientId:n,visitorId:e}),handshake:({botId:n,publicKey:e,visitorId:i})=>r("POST","/widget/handshake",{botId:n,publicKey:e,visitorId:i}),getConfig:n=>r("GET","/widget/config",null,n),sendMessage:(n,e)=>r("POST","/widget/message",{message:e},n),captureLead:(n,e)=>r("POST","/widget/lead",e,n)}})(i.apiBase);try{let n="",r=null;if(i.clientId){const e=await a.bootstrap({clientId:i.clientId,visitorId:t});if(!e||!e.token)return void console.error("[Fluxia] Bootstrap falhou. Widget nao sera renderizado.");n=e.token,r=e.config||null}else{const r=await a.handshake({botId:i.botId,publicKey:i.publicKey,visitorId:t});if(!r||!r.token)return void console.error("[Fluxia] Handshake falhou. Widget nao sera renderizado.");n=r.token}r||(r=await a.getConfig(n)),(({config:n,token:r,api:e,visitorId:i,botId:t})=>{const a=n.theme||{},o=a.primaryColor||"#dc2626",l=a.position||"right",s=n.botName||n.name||"Assistente",d=document.createElement("div");d.id="fluxia-widget-root",d.className="chatbot-scope fluxia-widget",d.dataset.position=l,d.style.setProperty("--fluxia-primary",o),d.innerHTML=function({botName:n}){return`\n <div id="fluxia-bubble" class="fluxia-bubble" aria-label="Abrir chat" role="button">\n 💬\n </div>\n\n <div id="fluxia-chatbox" class="fluxia-chatbox" role="dialog" aria-live="polite">\n <div class="fluxia-header">\n <div class="fluxia-header-info">\n <div class="fluxia-avatar">🤖</div>\n <div>\n <div class="fluxia-title">${n}</div>\n <div class="fluxia-status">Online</div>\n </div>\n </div>\n <button id="fluxia-close" class="fluxia-close" aria-label="Fechar">✕</button>\n </div>\n\n <div id="fluxia-messages" class="fluxia-messages"></div>\n\n <div class="fluxia-input-area">\n <input id="fluxia-input" class="fluxia-input" type="text" placeholder="Digite sua mensagem..." />\n <button id="fluxia-send" class="fluxia-send">Enviar</button>\n </div>\n </div>\n `}({botName:s,initialMessage:n.initialMessage}),document.body.appendChild(d);let u=!1;const c=d.querySelector("#fluxia-bubble"),f=d.querySelector("#fluxia-chatbox"),x=d.querySelector("#fluxia-close"),p=d.querySelector("#fluxia-input"),b=d.querySelector("#fluxia-send"),g=d.querySelector("#fluxia-messages");function m(n){u=n,f.style.display=u?"flex":"none",c.style.display=u?"none":"flex"}function y(n,r){const e=document.createElement("div");e.className=`fluxia-msg fluxia-msg-${n}`,e.textContent=r,g.appendChild(e),g.scrollTop=g.scrollHeight}async function h(){const n=p.value.trim();if(n){p.value="",p.disabled=!0,b.disabled=!0,y("user",n);try{const i=await e.sendMessage(r,n);i.reply&&y("assistant",i.reply.content)}catch(i){401===i.status?y("system","Sessão expirada. Recarregue a página."):y("system","Erro ao enviar mensagem. Tente novamente."),console.error("[Fluxia]",i)}finally{p.disabled=!1,b.disabled=!1,p.focus()}}}n.initialMessage&&y("assistant",n.initialMessage),c.addEventListener("click",()=>m(!0)),x.addEventListener("click",()=>m(!1)),b.addEventListener("click",h),p.addEventListener("keydown",n=>{"Enter"!==n.key||n.shiftKey||(n.preventDefault(),h())})})({config:r,token:n,api:a,visitorId:t,botId:i.botId||(null==r?void 0:r.botId)}),console.log("[Fluxia] Widget inicializado com sucesso.")}catch(o){console.error("[Fluxia] Erro na inicialização:",o.message||o)}};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",i):i()});
|
|
1
|
+
!function(t){"function"==typeof define&&define.amd?define(t):t()}(function(){"use strict";const t="fluxia-widget-styles",e=t=>{const e=document.createElement("div");return e.textContent=t,e.innerHTML};const i=async({config:i,token:a,api:o,visitorId:n,botId:r})=>{(()=>{if(document.getElementById(t))return;const e=document.createElement("style");e.id=t,e.textContent='\n#fluxia-widget-root{all:initial;font-family:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-size:14px;line-height:1.5;color:#1f2937;--fw-header:#0f172a;--fw-white:#fff;--fw-green:#22c55e;--fw-red:#ef4444;--fw-red-dark:#dc2626;--fw-text:#1f2937;--fw-gray-100:#f3f4f6;--fw-gray-200:#e5e7eb;--fw-gray-300:#d1d5db;--fw-gray-bg:#fafbfc;--fw-radius:20px;--fw-shadow:0 20px 60px rgba(0,0,0,.25)}\n#fluxia-widget-root *,#fluxia-widget-root *::before,#fluxia-widget-root *::after{box-sizing:border-box;margin:0;padding:0}\n#fluxia-widget-root .fluxia-bubble{position:fixed;bottom:24px;right:24px;z-index:2147483646;width:60px;height:60px;border-radius:50%;border:none;background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 8px 24px rgba(239,68,68,.5),0 0 0 4px rgba(255,255,255,.25);transition:transform .3s cubic-bezier(.34,1.56,.64,1),box-shadow .3s,opacity .25s;opacity:1}\n#fluxia-widget-root .fluxia-bubble.fw-hidden{transform:scale(0);opacity:0;pointer-events:none}\n#fluxia-widget-root .fluxia-bubble svg{width:28px;height:28px;fill:#fff;stroke:none}\n#fluxia-widget-root .fluxia-chatbox{position:fixed;bottom:10px;right:10px;z-index:2147483647;width:400px;height:600px;max-height:calc(100vh - 120px);border-radius:var(--fw-radius);background:var(--fw-white);box-shadow:var(--fw-shadow);display:flex;flex-direction:column;overflow:hidden;transform-origin:bottom right;transform:scale(0) translateY(20px);opacity:0;pointer-events:none;transition:transform .35s cubic-bezier(.34,1.56,.64,1),opacity .25s}\n#fluxia-widget-root .fluxia-chatbox.fw-open{transform:scale(1) translateY(0);opacity:1;pointer-events:auto}\n#fluxia-widget-root .fluxia-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;background:var(--fw-header);color:var(--fw-white);flex-shrink:0;border-radius:var(--fw-radius) var(--fw-radius) 0 0}\n#fluxia-widget-root .fluxia-header-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}\n#fluxia-widget-root .fluxia-avatar{width:42px;height:42px;min-width:42px;border-radius:50%;background:rgba(255,255,255,.12);border:2px solid rgba(34,197,94,.5);display:flex;align-items:center;justify-content:center;font-size:20px;overflow:hidden;color:#fff}\n#fluxia-widget-root .fluxia-avatar img{width:100%;height:100%;object-fit:cover;border-radius:50%}\n#fluxia-widget-root .fluxia-header-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}\n#fluxia-widget-root .fluxia-title{font-weight:700;font-size:15px;color:var(--fw-white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n#fluxia-widget-root .fluxia-status{font-size:12px;color:var(--fw-green);display:flex;align-items:center;gap:6px;font-weight:600}\n#fluxia-widget-root .fluxia-status-dot{width:7px;height:7px;border-radius:50%;background:var(--fw-green);display:inline-block;animation:fw-pulse 2s ease-in-out infinite}\n@keyframes fw-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(1.3)}}\n#fluxia-widget-root .fluxia-close{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.08);border:none;color:var(--fw-white);cursor:pointer;border-radius:8px;transition:background .2s}\n#fluxia-widget-root .fluxia-close:hover{background:rgba(255,255,255,.18)}\n#fluxia-widget-root .fluxia-close svg{width:16px;height:16px}\n#fluxia-widget-root .fluxia-messages{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;background:var(--fw-white)}\n#fluxia-widget-root .fluxia-msg{max-width:82%;padding:10px 14px;font-size:13.5px;line-height:1.55;word-wrap:break-word;overflow-wrap:break-word;animation:fw-msgIn .3s ease-out}\n@keyframes fw-msgIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}\n#fluxia-widget-root .fluxia-msg-assistant{align-self:flex-start;background:var(--fw-gray-100);color:var(--fw-text);border-radius:16px 16px 16px 4px}\n#fluxia-widget-root .fluxia-msg-user{align-self:flex-end;background:var(--fw-header);color:var(--fw-white);border-radius:16px 16px 4px 16px}\n#fluxia-widget-root .fluxia-msg-system{align-self:center;background:#fef3c7;color:#92400e;font-size:12px;padding:8px 14px;border-radius:8px;text-align:center;max-width:90%;border:1px solid #fde68a}\n#fluxia-widget-root .fluxia-typing{display:flex;gap:5px;align-items:center;padding:4px 0}\n#fluxia-widget-root .fluxia-typing-dot{width:7px;height:7px;border-radius:50%;background:#94a3b8;animation:fw-bounce 1.4s infinite ease-in-out}\n#fluxia-widget-root .fluxia-typing-dot:nth-child(2){animation-delay:.16s}\n#fluxia-widget-root .fluxia-typing-dot:nth-child(3){animation-delay:.32s}\n@keyframes fw-bounce{0%,80%,100%{transform:scale(.7);opacity:.4}40%{transform:scale(1.1);opacity:1}}\n#fluxia-widget-root .fluxia-input-area{padding:12px 14px;background:var(--fw-white);border-top:1px solid var(--fw-gray-200);display:flex;align-items:center;gap:10px;flex-shrink:0}\n#fluxia-widget-root .fluxia-input{flex:1;border:1.5px solid var(--fw-gray-300);border-radius:24px;padding:10px 16px;font-size:13px;font-family:inherit;outline:none;color:var(--fw-text);background:var(--fw-gray-bg);transition:border-color .2s,box-shadow .2s}\n#fluxia-widget-root .fluxia-input::placeholder{color:#9ca3af}\n#fluxia-widget-root .fluxia-input:focus{border-color:var(--fw-header);background:var(--fw-white);box-shadow:0 0 0 3px rgba(15,23,42,.06)}\n#fluxia-widget-root .fluxia-input:disabled{opacity:.5;cursor:not-allowed}\n#fluxia-widget-root .fluxia-send{width:40px;height:40px;min-width:40px;border-radius:50%;background:var(--fw-red);color:var(--fw-white);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .2s,transform .2s;flex-shrink:0}\n#fluxia-widget-root .fluxia-send:hover{background:var(--fw-red-dark);transform:scale(1.08)}\n#fluxia-widget-root .fluxia-send:active{transform:scale(.92)}\n#fluxia-widget-root .fluxia-send:disabled{opacity:.4;cursor:not-allowed;transform:none}\n#fluxia-widget-root .fluxia-send svg{width:18px;height:18px}\n#fluxia-widget-root .fluxia-powered{text-align:center;padding:8px 0;font-size:11px;color:#9ca3af;background:var(--fw-white);border-top:1px solid var(--fw-gray-200);flex-shrink:0}\n#fluxia-widget-root .fluxia-powered a{color:#6b7280;text-decoration:none;font-weight:600}\n#fluxia-widget-root[data-position="left"] .fluxia-bubble{left:24px;right:auto}\n#fluxia-widget-root[data-position="left"] .fluxia-chatbox{left:24px;right:auto;transform-origin:bottom left}\n@media(max-width:768px){#fluxia-widget-root .fluxia-chatbox{width:calc(100vw - 32px);max-width:400px;height:calc(100vh - 140px);max-height:600px;bottom:10px;right:10px}#fluxia-widget-root .fluxia-bubble{bottom:20px;right:16px;width:56px;height:56px}}\n@media(max-width:480px){#fluxia-widget-root .fluxia-chatbox{position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;max-width:none;max-height:none;border-radius:0;transform-origin:bottom center}#fluxia-widget-root .fluxia-chatbox.fw-open{border-radius:0}#fluxia-widget-root .fluxia-header{border-radius:0}#fluxia-widget-root .fluxia-bubble{bottom:16px;right:16px;width:52px;height:52px}#fluxia-widget-root .fluxia-bubble svg{width:24px;height:24px}#fluxia-widget-root .fluxia-avatar{width:38px;height:38px;min-width:38px}#fluxia-widget-root .fluxia-title{font-size:14px}#fluxia-widget-root .fluxia-msg{max-width:88%;font-size:13px}#fluxia-widget-root .fluxia-input{font-size:14px}#fluxia-widget-root .fluxia-send{width:38px;height:38px;min-width:38px}}\n',document.head.appendChild(e)})();const d=(i.theme||{}).position||"right",l=i.botName||i.name||"Assistente",s=i.botAvatar||"",f=i.customCss||"",u=document.createElement("div");if(u.id="fluxia-widget-root",u.dataset.position=d,u.innerHTML=function({botName:t,botAvatar:i}){return`\n <button class="fluxia-bubble" aria-label="Abrir chat" title="Abrir chat">\n <svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>\n </button>\n\n <div class="fluxia-chatbox" role="dialog" aria-label="Chat">\n <div class="fluxia-header">\n <div class="fluxia-header-info">\n <div class="fluxia-avatar">${i?`<img src="${e(i)}" alt="Avatar" />`:"🤖"}</div>\n <div class="fluxia-header-text">\n <div class="fluxia-title">${t}</div>\n <div class="fluxia-status">\n <span class="fluxia-status-dot"></span>\n Online agora\n </div>\n </div>\n </div>\n <button class="fluxia-close" aria-label="Fechar chat" title="Fechar">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">\n <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>\n </svg>\n </button>\n </div>\n\n <div class="fluxia-messages"></div>\n\n <div class="fluxia-input-area">\n <input class="fluxia-input" type="text"\n placeholder="Pergunte sobre leads, métricas ou integrações"\n autocomplete="off" />\n <button class="fluxia-send" title="Enviar">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"\n stroke-linecap="round" stroke-linejoin="round">\n <line x1="22" y1="2" x2="11" y2="13"/>\n <polygon points="22 2 15 22 11 13 2 9 22 2"/>\n </svg>\n </button>\n </div>\n\n <div class="fluxia-powered">\n Powered by <a href="https://rowsky.com.br/" target="_blank" rel="noopener">Rowsky</a>\n </div>\n </div>\n `}({botName:e(l),botAvatar:s}),document.body.appendChild(u),f&&f.trim()){const t=document.createElement("style");t.id="fluxia-widget-custom",t.textContent=f,document.head.appendChild(t)}const x=u.querySelector(".fluxia-bubble"),c=u.querySelector(".fluxia-chatbox"),p=u.querySelector(".fluxia-close"),g=u.querySelector(".fluxia-input"),w=u.querySelector(".fluxia-send"),h=u.querySelector(".fluxia-messages");function b(t,e){const i=document.createElement("div");i.className=`fluxia-msg fluxia-msg-${t}`,i.textContent=e,h.appendChild(i),h.scrollTop=h.scrollHeight}async function m(){const t=g.value.trim();if(!t)return;g.value="",g.disabled=!0,w.disabled=!0,b("user",t);const e=document.createElement("div");e.className="fluxia-msg fluxia-msg-assistant",e.innerHTML='<div class="fluxia-typing"><div class="fluxia-typing-dot"></div><div class="fluxia-typing-dot"></div><div class="fluxia-typing-dot"></div></div>',h.appendChild(e),h.scrollTop=h.scrollHeight;try{const i=await o.sendMessage(a,t);e.remove(),i.reply&&b("assistant",i.reply.content)}catch(i){e.remove(),401===i.status?b("system","Sessão expirada. Recarregue a página."):b("system","Erro ao enviar mensagem. Tente novamente."),console.error("[Fluxia]",i)}finally{g.disabled=!1,w.disabled=!1,g.focus()}}i.initialMessage&&b("assistant",i.initialMessage),x.addEventListener("click",()=>(x.classList.add("fw-hidden"),c.classList.add("fw-open"),void setTimeout(()=>g.focus(),350))),p.addEventListener("click",()=>(c.classList.remove("fw-open"),void setTimeout(()=>x.classList.remove("fw-hidden"),300))),w.addEventListener("click",m),g.addEventListener("keydown",t=>{"Enter"!==t.key||t.shiftKey||(t.preventDefault(),m())})},a="fluxia_visitor_id",o=document.currentScript,n=async()=>{const t=(()=>{const t=o||document.currentScript||document.querySelector("script[data-client-id], script[data-bot-id]");if(!t)return console.error("[Fluxia] Script tag não encontrada. Use data-client-id OU data-bot-id + data-public-key."),null;const e=t.getAttribute("data-bot-id"),i=t.getAttribute("data-public-key"),a=t.getAttribute("data-client-id"),n=t.getAttribute("data-api-base")||"";return n&&(a||e&&i)?{botId:e?Number(e):null,publicKey:i||"",clientId:a||"",apiBase:n.replace(/\/$/,"")}:(console.error("[Fluxia] Atributos obrigatorios: data-api-base e (data-client-id OU data-bot-id + data-public-key)"),null)})();if(!t)return;const e=(()=>{let t=null;try{t=localStorage.getItem(a)}catch{}if(!t){t="v_"+crypto.randomUUID();try{localStorage.setItem(a,t)}catch{}}return t})(),n=(t=>{const e=async(e,i,a=null,o=null)=>{const n={"Content-Type":"application/json"};o&&(n.Authorization=`Bearer ${o}`);const r={method:e,headers:n};a&&(r.body=JSON.stringify(a));const d=await fetch(`${t}${i}`,r);if(!d.ok){const t=await d.json().catch(()=>({})),e=new Error(t.error||`HTTP ${d.status}`);throw e.status=d.status,e.data=t,e}return d.json()};return{bootstrap:({clientId:t,visitorId:i})=>e("POST","/widget/bootstrap",{clientId:t,visitorId:i}),handshake:({botId:t,publicKey:i,visitorId:a})=>e("POST","/widget/handshake",{botId:t,publicKey:i,visitorId:a}),getConfig:t=>e("GET","/widget/config",null,t),sendMessage:(t,i)=>e("POST","/widget/message",{message:i},t),captureLead:(t,i)=>e("POST","/widget/lead",i,t)}})(t.apiBase);try{let a="",o=null;if(t.clientId){const i=await n.bootstrap({clientId:t.clientId,visitorId:e});if(!i||!i.token)return void console.error("[Fluxia] Bootstrap falhou. Widget nao sera renderizado.");a=i.token,o=i.config||null}else{const i=await n.handshake({botId:t.botId,publicKey:t.publicKey,visitorId:e});if(!i||!i.token)return void console.error("[Fluxia] Handshake falhou. Widget nao sera renderizado.");a=i.token}o||(o=await n.getConfig(a)),await i({config:o,token:a,api:n,visitorId:e,botId:t.botId||(null==o?void 0:o.botId)}),console.log("[Fluxia] Widget inicializado com sucesso.")}catch(r){console.error("[Fluxia] Erro na inicialização:",r.message||r)}};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",n):n()});
|