@nameless26/widget 0.1.0

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.
@@ -0,0 +1,22 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react");function R(t){return`nexus_widget_session_${t}`}function H(t){const r=sessionStorage.getItem(R(t));if(r)return r;const n=crypto.randomUUID();return sessionStorage.setItem(R(t),n),n}async function*W(t,r){const n=new TextDecoder;let u="";try{for(;;){if(r.aborted)return;const{done:a,value:x}=await t.read();if(a)return;u+=n.decode(x,{stream:!0});const c=u.split(`
2
+
3
+ `);u=c.pop()??"";for(const y of c)for(const b of y.split(`
4
+ `)){if(!b.startsWith("data: "))continue;const d=b.slice(6).trim();try{yield JSON.parse(d)}catch{}}}}finally{t.releaseLock()}}function D({agentId:t,baseUrl:r="http://localhost:8000/api",endUserId:n}){const[u,a]=o.useState([]),[x,c]=o.useState(!1),[y,b]=o.useState(!0),[d,h]=o.useState(null),[v,p]=o.useState(null),[m,k]=o.useState(null),s=o.useRef(H(t)),w=o.useRef(null),T=o.useCallback(async()=>{var N;(N=w.current)==null||N.abort(),b(!0),h(null);const i=new AbortController;w.current=i;try{const f=await fetch(`${r}/widget/session`,{method:"POST",signal:i.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:t,sessionId:s.current})});if(!f.ok)throw new Error(`HTTP ${f.status}`);const j=await f.json();k(j.token);const S=await fetch(`${r}/chat/history`,{method:"POST",signal:i.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${j.token}`},body:JSON.stringify({agentId:t,sessionId:s.current})});if(!S.ok)throw new Error(`HTTP ${S.status}`);const l=await S.json();a(l.messages??[]),p(l.conversationId??null)}catch(f){(f==null?void 0:f.name)!=="AbortError"&&h("Unable to initialize widget session.")}finally{b(!1)}},[t]);o.useEffect(()=>(T(),()=>{var i;(i=w.current)==null||i.abort()}),[T]);const O=o.useCallback(()=>{var i;(i=w.current)==null||i.abort(),c(!1)},[]),P=o.useCallback(()=>{var i;(i=w.current)==null||i.abort(),a([]),p(null),h(null),c(!1),s.current=crypto.randomUUID(),k(null),T()},[T]),E=o.useCallback(async i=>{var S;if(!i.trim()||x||!m)return;(S=w.current)==null||S.abort();const N=new AbortController;w.current=N,h(null);const f=`u_${Date.now()}`,j=`a_${Date.now()}`;a(l=>[...l,{id:f,role:"user",content:i.trim()}]),c(!0);try{const l=await fetch(`${r}/chat`,{method:"POST",signal:N.signal,headers:{"Content-Type":"application/json",Authorization:`Bearer ${m}`},body:JSON.stringify({agent_id:t,message:i.trim(),session_id:s.current,end_user_id:n})});if(!l.ok||!l.body)throw new Error(`HTTP ${l.status}`);a(g=>[...g,{id:j,role:"assistant",content:""}]);const $=l.body.getReader();for await(const g of W($,N.signal))switch(g.type){case"start":p(g.conversationId);break;case"token":a(I=>I.map(C=>C.id===j?{...C,content:C.content+g.content}:C));break;case"done":break;case"error":h(g.message),a(I=>I.filter(C=>C.id!==j));break}}catch(l){if((l==null?void 0:l.name)==="AbortError")return;h("Something went wrong. Please try again."),a($=>$.filter(g=>g.id!==f&&g.id!==j))}finally{c(!1)}},[t,n,x,m]);return{messages:u,isLoading:x,historyLoading:y,error:d,conversationId:v,send:E,reset:P,cancel:O}}function _({color:t}){return e.jsx("div",{className:`flex items-end gap-1 px-3 py-2.5 rounded-2xl rounded-bl-sm w-fit\r
5
+ bg-[rgba(255,255,255,0.06)]`,children:[0,1,2].map(r=>e.jsx("span",{style:{width:6,height:6,borderRadius:"50%",background:t,opacity:.6,animation:`nexusBounce 1.2s ease-in-out ${r*.2}s infinite`}},r))})}function z({msg:t,primaryColor:r}){const n=t.role==="user";return e.jsx("div",{className:`flex ${n?"justify-end":"justify-start"}`,children:e.jsx("div",{style:n?{background:r}:void 0,className:`max-w-[82%] px-3 py-2.5 rounded-2xl text-sm leading-relaxed
6
+ ${n?"text-white rounded-br-sm":"bg-[rgba(255,255,255,0.06)] text-[rgba(255,255,255,0.8)] rounded-bl-sm"}`,children:t.content})})}function B({agentName:t,messages:r,isLoading:n,error:u,primaryColor:a,welcomeMessage:x,onSend:c,onReset:y,onClose:b}){const[d,h]=o.useState(""),v=o.useRef(null),p=o.useRef(null);o.useEffect(()=>{var s;(s=v.current)==null||s.scrollIntoView({behavior:"smooth"})},[r,n]),o.useEffect(()=>{var s;(s=p.current)==null||s.focus()},[]);const m=()=>{!d.trim()||n||(c(d),h(""))},k=s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),m())};return e.jsxs(e.Fragment,{children:[e.jsx("style",{children:`
7
+ @keyframes nexusBounce {
8
+ 0%, 80%, 100% { transform: translateY(0); }
9
+ 40% { transform: translateY(-5px); }
10
+ }
11
+ `}),e.jsxs("div",{style:{fontFamily:"system-ui, -apple-system, sans-serif"},className:`flex flex-col overflow-hidden rounded-2xl shadow-2xl\r
12
+ border border-[rgba(255,255,255,0.08)]`,role:"dialog","aria-label":`${t} chat`,children:[e.jsxs("div",{style:{background:a},className:"flex items-center justify-between px-4 py-3 shrink-0",children:[e.jsxs("div",{className:"flex items-center gap-2.5",children:[e.jsx("div",{className:"w-2 h-2 rounded-full bg-white/40"}),e.jsx("span",{className:"text-white text-sm font-medium",children:t})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("button",{onClick:y,"aria-label":"Start new conversation",className:`p-1.5 rounded-full text-white/60 hover:text-white\r
13
+ hover:bg-white/15 transition-colors`,children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:[e.jsx("path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}),e.jsx("path",{d:"M3 3v5h5"})]})}),e.jsx("button",{onClick:b,"aria-label":"Close chat",className:`p-1.5 rounded-full text-white/60 hover:text-white\r
14
+ hover:bg-white/15 transition-colors`,children:e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:e.jsx("path",{d:"M18 6 6 18M6 6l12 12"})})})]})]}),e.jsxs("div",{className:"flex-1 overflow-y-auto px-4 py-4 space-y-3 bg-[#0d0d1a]",style:{minHeight:0},children:[r.length===0&&e.jsx("div",{className:"flex justify-start",children:e.jsx("div",{className:`max-w-[82%] px-3 py-2.5 rounded-2xl rounded-bl-sm\r
15
+ bg-[rgba(255,255,255,0.06)] text-sm\r
16
+ text-[rgba(255,255,255,0.8)] leading-relaxed`,children:x})}),r.map(s=>e.jsx(z,{msg:s,primaryColor:a},s.id)),n&&e.jsx("div",{className:"flex justify-start",children:e.jsx(_,{color:a})}),u&&e.jsx("div",{className:"text-center text-xs text-red-400/70 py-1",children:u}),e.jsx("div",{ref:v})]}),e.jsxs("div",{className:`px-3 py-3 bg-[#0d0d1a] border-t border-[rgba(255,255,255,0.06)]\r
17
+ flex items-end gap-2 shrink-0`,children:[e.jsx("textarea",{ref:p,rows:1,value:d,onChange:s=>h(s.target.value),onKeyDown:k,placeholder:"Type a message…",disabled:n,style:{resize:"none",maxHeight:100,overflowY:"auto"},className:`flex-1 bg-[rgba(255,255,255,0.05)] border border-[rgba(255,255,255,0.08)]\r
18
+ rounded-xl px-3 py-2.5 text-sm text-white/80 placeholder-white/25\r
19
+ focus:outline-none focus:border-[rgba(255,255,255,0.18)]\r
20
+ transition-colors disabled:opacity-40`}),e.jsx("button",{onClick:m,disabled:!d.trim()||n,"aria-label":"Send message",style:{background:d.trim()&&!n?a:void 0},className:`shrink-0 w-9 h-9 rounded-xl flex items-center justify-center\r
21
+ bg-[rgba(255,255,255,0.08)] transition-colors\r
22
+ disabled:opacity-40 disabled:cursor-not-allowed`,children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"2",strokeLinecap:"round",children:[e.jsx("path",{d:"m22 2-7 20-4-9-9-4Z"}),e.jsx("path",{d:"M22 2 11 13"})]})})]})]})]})}const M=o.forwardRef(({agentId:t,baseUrl:r,primaryColor:n="#6366f1",position:u="bottom-right",welcomeMessage:a="Hi! How can I help you today?",agentName:x="Assistant",endUserId:c},y)=>{const{messages:b,isLoading:d,historyLoading:h,error:v,conversationId:p,send:m,reset:k,cancel:s}=D({agentId:t,baseUrl:r,endUserId:c});return e.jsx("div",{ref:y,style:{position:"fixed",[u==="bottom-left"?"left":"right"]:"20px",bottom:"20px",zIndex:9999,fontFamily:"system-ui, -apple-system, sans-serif"},children:e.jsx(B,{agentName:x,messages:b,isLoading:d,error:v,primaryColor:n,welcomeMessage:a,onSend:m,onReset:k,onClose:s})})});M.displayName="NexusWidget";exports.NexusWidget=M;exports.useChat=D;
@@ -0,0 +1,3 @@
1
+ export { NexusWidget } from './Widget';
2
+ export type { NexusWidgetProps, ChatMessage, UseChatOptions, ChatPanelProps, SseEvent, } from './types';
3
+ export { useChat } from './useChat';
@@ -0,0 +1,419 @@
1
+ import { jsxs as p, Fragment as B, jsx as e } from "react/jsx-runtime";
2
+ import { useState as k, useRef as D, useCallback as I, useEffect as H, forwardRef as E } from "react";
3
+ function O(t) {
4
+ return `nexus_widget_session_${t}`;
5
+ }
6
+ function W(t) {
7
+ const s = sessionStorage.getItem(O(t));
8
+ if (s) return s;
9
+ const r = crypto.randomUUID();
10
+ return sessionStorage.setItem(O(t), r), r;
11
+ }
12
+ async function* A(t, s) {
13
+ const r = new TextDecoder();
14
+ let d = "";
15
+ try {
16
+ for (; ; ) {
17
+ if (s.aborted) return;
18
+ const { done: o, value: f } = await t.read();
19
+ if (o) return;
20
+ d += r.decode(f, { stream: !0 });
21
+ const l = d.split(`
22
+
23
+ `);
24
+ d = l.pop() ?? "";
25
+ for (const y of l)
26
+ for (const b of y.split(`
27
+ `)) {
28
+ if (!b.startsWith("data: ")) continue;
29
+ const c = b.slice(6).trim();
30
+ try {
31
+ yield JSON.parse(c);
32
+ } catch {
33
+ }
34
+ }
35
+ }
36
+ } finally {
37
+ t.releaseLock();
38
+ }
39
+ }
40
+ function J({ agentId: t, baseUrl: s = "http://localhost:8000/api", endUserId: r }) {
41
+ const [d, o] = k([]), [f, l] = k(!1), [y, b] = k(!0), [c, u] = k(null), [N, x] = k(null), [g, S] = k(null), n = D(W(t)), w = D(null), j = I(async () => {
42
+ var T;
43
+ (T = w.current) == null || T.abort(), b(!0), u(null);
44
+ const a = new AbortController();
45
+ w.current = a;
46
+ try {
47
+ const h = await fetch(`${s}/widget/session`, {
48
+ method: "POST",
49
+ signal: a.signal,
50
+ headers: { "Content-Type": "application/json" },
51
+ body: JSON.stringify({
52
+ agentId: t,
53
+ sessionId: n.current
54
+ })
55
+ });
56
+ if (!h.ok)
57
+ throw new Error(`HTTP ${h.status}`);
58
+ const v = await h.json();
59
+ S(v.token);
60
+ const C = await fetch(`${s}/chat/history`, {
61
+ method: "POST",
62
+ signal: a.signal,
63
+ headers: {
64
+ "Content-Type": "application/json",
65
+ Authorization: `Bearer ${v.token}`
66
+ },
67
+ body: JSON.stringify({
68
+ agentId: t,
69
+ sessionId: n.current
70
+ })
71
+ });
72
+ if (!C.ok)
73
+ throw new Error(`HTTP ${C.status}`);
74
+ const i = await C.json();
75
+ o(i.messages ?? []), x(i.conversationId ?? null);
76
+ } catch (h) {
77
+ (h == null ? void 0 : h.name) !== "AbortError" && u("Unable to initialize widget session.");
78
+ } finally {
79
+ b(!1);
80
+ }
81
+ }, [t]);
82
+ H(() => (j(), () => {
83
+ var a;
84
+ (a = w.current) == null || a.abort();
85
+ }), [j]);
86
+ const P = I(() => {
87
+ var a;
88
+ (a = w.current) == null || a.abort(), l(!1);
89
+ }, []), _ = I(() => {
90
+ var a;
91
+ (a = w.current) == null || a.abort(), o([]), x(null), u(null), l(!1), n.current = crypto.randomUUID(), S(null), j();
92
+ }, [j]), z = I(
93
+ async (a) => {
94
+ var C;
95
+ if (!a.trim() || f || !g) return;
96
+ (C = w.current) == null || C.abort();
97
+ const T = new AbortController();
98
+ w.current = T, u(null);
99
+ const h = `u_${Date.now()}`, v = `a_${Date.now()}`;
100
+ o((i) => [
101
+ ...i,
102
+ { id: h, role: "user", content: a.trim() }
103
+ ]), l(!0);
104
+ try {
105
+ const i = await fetch(`${s}/chat`, {
106
+ method: "POST",
107
+ signal: T.signal,
108
+ headers: {
109
+ "Content-Type": "application/json",
110
+ Authorization: `Bearer ${g}`
111
+ },
112
+ body: JSON.stringify({
113
+ agent_id: t,
114
+ message: a.trim(),
115
+ session_id: n.current,
116
+ end_user_id: r
117
+ })
118
+ });
119
+ if (!i.ok || !i.body)
120
+ throw new Error(`HTTP ${i.status}`);
121
+ o((m) => [
122
+ ...m,
123
+ { id: v, role: "assistant", content: "" }
124
+ ]);
125
+ const M = i.body.getReader();
126
+ for await (const m of A(M, T.signal))
127
+ switch (m.type) {
128
+ case "start":
129
+ x(m.conversationId);
130
+ break;
131
+ case "token":
132
+ o(
133
+ (R) => R.map(
134
+ ($) => $.id === v ? { ...$, content: $.content + m.content } : $
135
+ )
136
+ );
137
+ break;
138
+ case "done":
139
+ break;
140
+ case "error":
141
+ u(m.message), o(
142
+ (R) => R.filter(($) => $.id !== v)
143
+ );
144
+ break;
145
+ }
146
+ } catch (i) {
147
+ if ((i == null ? void 0 : i.name) === "AbortError") return;
148
+ u("Something went wrong. Please try again."), o(
149
+ (M) => M.filter(
150
+ (m) => m.id !== h && m.id !== v
151
+ )
152
+ );
153
+ } finally {
154
+ l(!1);
155
+ }
156
+ },
157
+ [t, r, f, g]
158
+ );
159
+ return {
160
+ messages: d,
161
+ isLoading: f,
162
+ historyLoading: y,
163
+ error: c,
164
+ conversationId: N,
165
+ send: z,
166
+ reset: _,
167
+ cancel: P
168
+ };
169
+ }
170
+ function K({ color: t }) {
171
+ return /* @__PURE__ */ e("div", { className: `flex items-end gap-1 px-3 py-2.5 rounded-2xl rounded-bl-sm w-fit\r
172
+ bg-[rgba(255,255,255,0.06)]`, children: [0, 1, 2].map((s) => /* @__PURE__ */ e(
173
+ "span",
174
+ {
175
+ style: {
176
+ width: 6,
177
+ height: 6,
178
+ borderRadius: "50%",
179
+ background: t,
180
+ opacity: 0.6,
181
+ animation: `nexusBounce 1.2s ease-in-out ${s * 0.2}s infinite`
182
+ }
183
+ },
184
+ s
185
+ )) });
186
+ }
187
+ function L({
188
+ msg: t,
189
+ primaryColor: s
190
+ }) {
191
+ const r = t.role === "user";
192
+ return /* @__PURE__ */ e("div", { className: `flex ${r ? "justify-end" : "justify-start"}`, children: /* @__PURE__ */ e(
193
+ "div",
194
+ {
195
+ style: r ? { background: s } : void 0,
196
+ className: `max-w-[82%] px-3 py-2.5 rounded-2xl text-sm leading-relaxed
197
+ ${r ? "text-white rounded-br-sm" : "bg-[rgba(255,255,255,0.06)] text-[rgba(255,255,255,0.8)] rounded-bl-sm"}`,
198
+ children: t.content
199
+ }
200
+ ) });
201
+ }
202
+ function U({
203
+ agentName: t,
204
+ messages: s,
205
+ isLoading: r,
206
+ error: d,
207
+ primaryColor: o,
208
+ welcomeMessage: f,
209
+ onSend: l,
210
+ onReset: y,
211
+ onClose: b
212
+ }) {
213
+ const [c, u] = k(""), N = D(null), x = D(null);
214
+ H(() => {
215
+ var n;
216
+ (n = N.current) == null || n.scrollIntoView({ behavior: "smooth" });
217
+ }, [s, r]), H(() => {
218
+ var n;
219
+ (n = x.current) == null || n.focus();
220
+ }, []);
221
+ const g = () => {
222
+ !c.trim() || r || (l(c), u(""));
223
+ }, S = (n) => {
224
+ n.key === "Enter" && !n.shiftKey && (n.preventDefault(), g());
225
+ };
226
+ return /* @__PURE__ */ p(B, { children: [
227
+ /* @__PURE__ */ e("style", { children: `
228
+ @keyframes nexusBounce {
229
+ 0%, 80%, 100% { transform: translateY(0); }
230
+ 40% { transform: translateY(-5px); }
231
+ }
232
+ ` }),
233
+ /* @__PURE__ */ p(
234
+ "div",
235
+ {
236
+ style: { fontFamily: "system-ui, -apple-system, sans-serif" },
237
+ className: `flex flex-col overflow-hidden rounded-2xl shadow-2xl\r
238
+ border border-[rgba(255,255,255,0.08)]`,
239
+ role: "dialog",
240
+ "aria-label": `${t} chat`,
241
+ children: [
242
+ /* @__PURE__ */ p(
243
+ "div",
244
+ {
245
+ style: { background: o },
246
+ className: "flex items-center justify-between px-4 py-3 shrink-0",
247
+ children: [
248
+ /* @__PURE__ */ p("div", { className: "flex items-center gap-2.5", children: [
249
+ /* @__PURE__ */ e("div", { className: "w-2 h-2 rounded-full bg-white/40" }),
250
+ /* @__PURE__ */ e("span", { className: "text-white text-sm font-medium", children: t })
251
+ ] }),
252
+ /* @__PURE__ */ p("div", { className: "flex items-center gap-1", children: [
253
+ /* @__PURE__ */ e(
254
+ "button",
255
+ {
256
+ onClick: y,
257
+ "aria-label": "Start new conversation",
258
+ className: `p-1.5 rounded-full text-white/60 hover:text-white\r
259
+ hover:bg-white/15 transition-colors`,
260
+ children: /* @__PURE__ */ p(
261
+ "svg",
262
+ {
263
+ width: "14",
264
+ height: "14",
265
+ viewBox: "0 0 24 24",
266
+ fill: "none",
267
+ stroke: "currentColor",
268
+ strokeWidth: "2",
269
+ strokeLinecap: "round",
270
+ children: [
271
+ /* @__PURE__ */ e("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
272
+ /* @__PURE__ */ e("path", { d: "M3 3v5h5" })
273
+ ]
274
+ }
275
+ )
276
+ }
277
+ ),
278
+ /* @__PURE__ */ e(
279
+ "button",
280
+ {
281
+ onClick: b,
282
+ "aria-label": "Close chat",
283
+ className: `p-1.5 rounded-full text-white/60 hover:text-white\r
284
+ hover:bg-white/15 transition-colors`,
285
+ children: /* @__PURE__ */ e(
286
+ "svg",
287
+ {
288
+ width: "14",
289
+ height: "14",
290
+ viewBox: "0 0 24 24",
291
+ fill: "none",
292
+ stroke: "currentColor",
293
+ strokeWidth: "2",
294
+ strokeLinecap: "round",
295
+ children: /* @__PURE__ */ e("path", { d: "M18 6 6 18M6 6l12 12" })
296
+ }
297
+ )
298
+ }
299
+ )
300
+ ] })
301
+ ]
302
+ }
303
+ ),
304
+ /* @__PURE__ */ p("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-3 bg-[#0d0d1a]", style: { minHeight: 0 }, children: [
305
+ s.length === 0 && /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ e("div", { className: `max-w-[82%] px-3 py-2.5 rounded-2xl rounded-bl-sm\r
306
+ bg-[rgba(255,255,255,0.06)] text-sm\r
307
+ text-[rgba(255,255,255,0.8)] leading-relaxed`, children: f }) }),
308
+ s.map((n) => /* @__PURE__ */ e(L, { msg: n, primaryColor: o }, n.id)),
309
+ r && /* @__PURE__ */ e("div", { className: "flex justify-start", children: /* @__PURE__ */ e(K, { color: o }) }),
310
+ d && /* @__PURE__ */ e("div", { className: "text-center text-xs text-red-400/70 py-1", children: d }),
311
+ /* @__PURE__ */ e("div", { ref: N })
312
+ ] }),
313
+ /* @__PURE__ */ p("div", { className: `px-3 py-3 bg-[#0d0d1a] border-t border-[rgba(255,255,255,0.06)]\r
314
+ flex items-end gap-2 shrink-0`, children: [
315
+ /* @__PURE__ */ e(
316
+ "textarea",
317
+ {
318
+ ref: x,
319
+ rows: 1,
320
+ value: c,
321
+ onChange: (n) => u(n.target.value),
322
+ onKeyDown: S,
323
+ placeholder: "Type a message…",
324
+ disabled: r,
325
+ style: { resize: "none", maxHeight: 100, overflowY: "auto" },
326
+ className: `flex-1 bg-[rgba(255,255,255,0.05)] border border-[rgba(255,255,255,0.08)]\r
327
+ rounded-xl px-3 py-2.5 text-sm text-white/80 placeholder-white/25\r
328
+ focus:outline-none focus:border-[rgba(255,255,255,0.18)]\r
329
+ transition-colors disabled:opacity-40`
330
+ }
331
+ ),
332
+ /* @__PURE__ */ e(
333
+ "button",
334
+ {
335
+ onClick: g,
336
+ disabled: !c.trim() || r,
337
+ "aria-label": "Send message",
338
+ style: { background: c.trim() && !r ? o : void 0 },
339
+ className: `shrink-0 w-9 h-9 rounded-xl flex items-center justify-center\r
340
+ bg-[rgba(255,255,255,0.08)] transition-colors\r
341
+ disabled:opacity-40 disabled:cursor-not-allowed`,
342
+ children: /* @__PURE__ */ p(
343
+ "svg",
344
+ {
345
+ width: "14",
346
+ height: "14",
347
+ viewBox: "0 0 24 24",
348
+ fill: "none",
349
+ stroke: "white",
350
+ strokeWidth: "2",
351
+ strokeLinecap: "round",
352
+ children: [
353
+ /* @__PURE__ */ e("path", { d: "m22 2-7 20-4-9-9-4Z" }),
354
+ /* @__PURE__ */ e("path", { d: "M22 2 11 13" })
355
+ ]
356
+ }
357
+ )
358
+ }
359
+ )
360
+ ] })
361
+ ]
362
+ }
363
+ )
364
+ ] });
365
+ }
366
+ const F = E(
367
+ ({
368
+ agentId: t,
369
+ baseUrl: s,
370
+ primaryColor: r = "#6366f1",
371
+ position: d = "bottom-right",
372
+ welcomeMessage: o = "Hi! How can I help you today?",
373
+ agentName: f = "Assistant",
374
+ endUserId: l
375
+ }, y) => {
376
+ const {
377
+ messages: b,
378
+ isLoading: c,
379
+ historyLoading: u,
380
+ error: N,
381
+ conversationId: x,
382
+ send: g,
383
+ reset: S,
384
+ cancel: n
385
+ } = J({ agentId: t, baseUrl: s, endUserId: l });
386
+ return /* @__PURE__ */ e(
387
+ "div",
388
+ {
389
+ ref: y,
390
+ style: {
391
+ position: "fixed",
392
+ [d === "bottom-left" ? "left" : "right"]: "20px",
393
+ bottom: "20px",
394
+ zIndex: 9999,
395
+ fontFamily: "system-ui, -apple-system, sans-serif"
396
+ },
397
+ children: /* @__PURE__ */ e(
398
+ U,
399
+ {
400
+ agentName: f,
401
+ messages: b,
402
+ isLoading: c,
403
+ error: N,
404
+ primaryColor: r,
405
+ welcomeMessage: o,
406
+ onSend: g,
407
+ onReset: S,
408
+ onClose: n
409
+ }
410
+ )
411
+ }
412
+ );
413
+ }
414
+ );
415
+ F.displayName = "NexusWidget";
416
+ export {
417
+ F as NexusWidget,
418
+ J as useChat
419
+ };
@@ -0,0 +1,42 @@
1
+ export interface ChatMessage {
2
+ id: string;
3
+ role: "user" | "assistant";
4
+ content: string;
5
+ }
6
+ export interface UseChatOptions {
7
+ agentId: string;
8
+ baseUrl?: string;
9
+ endUserId?: string;
10
+ }
11
+ export type SseEvent = {
12
+ type: "start";
13
+ conversationId: string;
14
+ } | {
15
+ type: "token";
16
+ content: string;
17
+ } | {
18
+ type: "done";
19
+ } | {
20
+ type: "error";
21
+ message: string;
22
+ };
23
+ export interface NexusWidgetProps {
24
+ agentId: string;
25
+ baseUrl?: string;
26
+ primaryColor?: string;
27
+ position?: "bottom-right" | "bottom-left";
28
+ welcomeMessage?: string;
29
+ agentName?: string;
30
+ endUserId?: string;
31
+ }
32
+ export interface ChatPanelProps {
33
+ agentName: string;
34
+ messages: ChatMessage[];
35
+ isLoading: boolean;
36
+ error: string | null;
37
+ primaryColor: string;
38
+ welcomeMessage: string;
39
+ onSend: (text: string) => void;
40
+ onReset: () => void;
41
+ onClose: () => void;
42
+ }
@@ -0,0 +1,11 @@
1
+ import { ChatMessage, UseChatOptions } from './types';
2
+ export declare function useChat({ agentId, baseUrl: BASE_URL, endUserId }: UseChatOptions): {
3
+ messages: ChatMessage[];
4
+ isLoading: boolean;
5
+ historyLoading: boolean;
6
+ error: string | null;
7
+ conversationId: string | null;
8
+ send: (text: string) => Promise<void>;
9
+ reset: () => void;
10
+ cancel: () => void;
11
+ };
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@nameless26/widget",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.es.js",
11
+ "require": "./dist/index.cjs.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "dev": "vite build --watch",
20
+ "build": "vite build && vite build --config vite.embed.config.ts",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "peerDependencies": {
24
+ "react": "^18.0.0",
25
+ "react-dom": "^18.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "@vitejs/plugin-react": "^4.0.0",
29
+ "react": "^18.2.0",
30
+ "react-dom": "^18.2.0",
31
+ "typescript": "^5.0.0",
32
+ "vite": "^5.0.0",
33
+ "vite-plugin-dts": "^5.0.2"
34
+ }
35
+ }