@docgenlab.com/chat-widget 0.2.4 → 0.4.2

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/index.js CHANGED
@@ -1,134 +1,200 @@
1
- import { createRoot as ke } from "react-dom/client";
1
+ import { createRoot as $e } from "react-dom/client";
2
2
  import * as e from "react";
3
- import { useRef as _, useState as p, useEffect as C, useCallback as me, createElement as ge } from "react";
4
- const F = "/api/v1/public/kb", ue = "dgl-visitor-id";
5
- function he() {
3
+ import { useRef as j, useState as f, useEffect as T, useCallback as be, createElement as Ee } from "react";
4
+ const S = "/api/v1/public/kb", ye = "dgl-visitor-id";
5
+ function ve() {
6
6
  const t = globalThis.crypto;
7
- return t && typeof t.randomUUID == "function" ? t.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (s) => {
8
- const l = Math.random() * 16 | 0;
9
- return (s === "x" ? l : l & 3 | 8).toString(16);
7
+ return t && typeof t.randomUUID == "function" ? t.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (n) => {
8
+ const i = Math.random() * 16 | 0;
9
+ return (n === "x" ? i : i & 3 | 8).toString(16);
10
10
  });
11
11
  }
12
- function we() {
12
+ function Se() {
13
13
  try {
14
- let t = localStorage.getItem(ue);
15
- return t || (t = he(), localStorage.setItem(ue, t)), t;
14
+ let t = localStorage.getItem(ye);
15
+ return t || (t = ve(), localStorage.setItem(ye, t)), t;
16
16
  } catch (t) {
17
- return he();
17
+ return ve();
18
18
  }
19
19
  }
20
- class xe {
21
- constructor(s) {
22
- this.agentKey = s.agentKey, this.baseUrl = s.apiBaseUrl.replace(/\/+$/, ""), this.visitorId = s.endUserId ? `user:${s.endUserId}` : we(), this.endUserHash = s.endUserHash;
20
+ class Te {
21
+ constructor(n) {
22
+ this.agentKey = n.agentKey, this.baseUrl = n.apiBaseUrl.replace(/\/+$/, ""), this.visitorId = n.endUserId ? `user:${n.endUserId}` : Se(), this.endUserHash = n.endUserHash;
23
23
  }
24
- headers(s) {
25
- const l = {
24
+ headers(n) {
25
+ const i = {
26
26
  "X-DocGenLab-Key": this.agentKey,
27
27
  "X-DocGenLab-Visitor-Id": this.visitorId,
28
- ...s || {}
28
+ ...n || {}
29
29
  };
30
- return this.endUserHash && (l["X-DocGenLab-User-Hash"] = this.endUserHash), l;
30
+ return this.endUserHash && (i["X-DocGenLab-User-Hash"] = this.endUserHash), i;
31
31
  }
32
32
  async getAgent() {
33
- const s = await fetch(`${this.baseUrl}${F}/agent`, {
33
+ const n = await fetch(`${this.baseUrl}${S}/agent`, {
34
34
  method: "GET",
35
35
  headers: this.headers()
36
36
  });
37
- if (!s.ok) throw new Error(`getAgent failed: ${s.status}`);
38
- return s.json();
37
+ if (!n.ok) throw new Error(`getAgent failed: ${n.status}`);
38
+ return n.json();
39
+ }
40
+ /** Load a previous conversation's messages so the widget can show
41
+ * history after a refresh / re-open. The visitor-id header is the
42
+ * authorization — the backend only returns conversations owned by
43
+ * the requesting visitor on this agent. */
44
+ async getConversation(n) {
45
+ const i = `${this.baseUrl}${S}/conversations/${encodeURIComponent(n)}`, l = await fetch(i, { headers: this.headers() });
46
+ if (!l.ok) throw new Error(`getConversation failed: ${l.status}`);
47
+ return l.json();
39
48
  }
40
- async uploadImage(s) {
41
- const l = new FormData();
42
- l.append("file", s);
43
- const r = await fetch(`${this.baseUrl}${F}/chat-image`, {
49
+ /** Reconstruct the ticket card that SHOULD currently be on the
50
+ * conversation, based on persisted state. Lets the widget restore
51
+ * raise-ticket / "already on it" / created cards after refresh.
52
+ * Returns kind=null when nothing should show. */
53
+ async getTicketCardState(n) {
54
+ const i = `${this.baseUrl}${S}/conversations/${encodeURIComponent(n)}/ticket-card`, l = await fetch(i, { headers: this.headers() });
55
+ if (!l.ok) throw new Error(`getTicketCardState failed: ${l.status}`);
56
+ return l.json();
57
+ }
58
+ async uploadImage(n) {
59
+ const i = new FormData();
60
+ i.append("file", n);
61
+ const l = await fetch(`${this.baseUrl}${S}/chat-image`, {
44
62
  method: "POST",
45
63
  headers: this.headers(),
46
64
  // browser sets Content-Type for FormData
47
- body: l
65
+ body: i
48
66
  });
49
- if (!r.ok) {
50
- let o = `${r.status} ${r.statusText}`;
67
+ if (!l.ok) {
68
+ let o = `${l.status} ${l.statusText}`;
51
69
  try {
52
- const i = await r.json();
53
- o = (i == null ? void 0 : i.detail) || o;
54
- } catch (i) {
70
+ const s = await l.json();
71
+ o = (s == null ? void 0 : s.detail) || o;
72
+ } catch (s) {
55
73
  }
56
74
  throw new Error(o);
57
75
  }
58
- return (await r.json()).image_path;
76
+ return (await l.json()).image_path;
59
77
  }
60
78
  /** Fetch a previously-uploaded image as a blob URL. Caller must
61
79
  * URL.revokeObjectURL() when done to avoid memory leaks. */
62
- async fetchImage(s) {
63
- const l = `${this.baseUrl}${F}/chat-image?path=${encodeURIComponent(s)}&key=${encodeURIComponent(this.agentKey)}`, r = await fetch(l, {
80
+ async fetchImage(n) {
81
+ const i = `${this.baseUrl}${S}/chat-image?path=${encodeURIComponent(n)}&key=${encodeURIComponent(this.agentKey)}`, l = await fetch(i, {
64
82
  method: "GET",
65
83
  headers: { "X-DocGenLab-Visitor-Id": this.visitorId }
66
84
  });
67
- if (!r.ok) throw new Error(`fetchImage failed: ${r.status}`);
68
- const n = await r.blob();
69
- return URL.createObjectURL(n);
85
+ if (!l.ok) throw new Error(`fetchImage failed: ${l.status}`);
86
+ const a = await l.blob();
87
+ return URL.createObjectURL(a);
88
+ }
89
+ /** Raise a support ticket from a conversation. Requires explicit user
90
+ * consent — the widget only calls this after the user clicks the
91
+ * in-chat "Raise a ticket" chip. */
92
+ async raiseTicket(n, i) {
93
+ const l = `${this.baseUrl}${S}/conversations/${encodeURIComponent(n)}/raise-ticket`, a = await fetch(l, {
94
+ method: "POST",
95
+ headers: {
96
+ "Content-Type": "application/json",
97
+ "X-DocGenLab-Key": this.agentKey,
98
+ "X-DocGenLab-Visitor-Id": this.visitorId,
99
+ ...this.endUserHash ? { "X-DocGenLab-User-Hash": this.endUserHash } : {}
100
+ },
101
+ body: JSON.stringify(i)
102
+ });
103
+ if (!a.ok) {
104
+ let o = `raiseTicket failed: ${a.status}`;
105
+ try {
106
+ o = (await a.json()).detail || o;
107
+ } catch (s) {
108
+ }
109
+ throw new Error(o);
110
+ }
111
+ return a.json();
112
+ }
113
+ /** List all tickets for THIS visitor on THIS agent. Used by the widget
114
+ * to hydrate ticket cards on conversation reload and to power the
115
+ * "Manage tickets" modal. Optionally filtered by conversation. */
116
+ async listTickets(n) {
117
+ const i = n ? `?conversation_id=${encodeURIComponent(n)}` : "", l = `${this.baseUrl}${S}/tickets${i}`, a = await fetch(l, {
118
+ headers: {
119
+ "X-DocGenLab-Key": this.agentKey,
120
+ "X-DocGenLab-Visitor-Id": this.visitorId
121
+ }
122
+ });
123
+ if (!a.ok) throw new Error(`listTickets failed: ${a.status}`);
124
+ return a.json();
125
+ }
126
+ /** Fetch the latest status of a ticket the user raised. */
127
+ async getTicket(n, i = !1) {
128
+ const l = `${this.baseUrl}${S}/tickets/${encodeURIComponent(n)}${i ? "?refresh=1" : ""}`, a = await fetch(l, {
129
+ headers: {
130
+ "X-DocGenLab-Key": this.agentKey,
131
+ "X-DocGenLab-Visitor-Id": this.visitorId
132
+ }
133
+ });
134
+ if (!a.ok) throw new Error(`getTicket failed: ${a.status}`);
135
+ return a.json();
70
136
  }
71
137
  /** Fetch a video-source frame attached to a citation chunk.
72
138
  * Same auth pattern as fetchImage. */
73
- async fetchSourceFrame(s, l) {
74
- const r = `${this.baseUrl}${F}/sources/${encodeURIComponent(s)}/frame?path=${encodeURIComponent(l)}&key=${encodeURIComponent(this.agentKey)}`, n = await fetch(r, {
139
+ async fetchSourceFrame(n, i) {
140
+ const l = `${this.baseUrl}${S}/sources/${encodeURIComponent(n)}/frame?path=${encodeURIComponent(i)}&key=${encodeURIComponent(this.agentKey)}`, a = await fetch(l, {
75
141
  method: "GET",
76
142
  headers: { "X-DocGenLab-Visitor-Id": this.visitorId }
77
143
  });
78
- if (!n.ok) throw new Error(`fetchSourceFrame failed: ${n.status}`);
79
- const o = await n.blob();
144
+ if (!a.ok) throw new Error(`fetchSourceFrame failed: ${a.status}`);
145
+ const o = await a.blob();
80
146
  return URL.createObjectURL(o);
81
147
  }
82
148
  /** Stream a chat response via SSE. Returns an abort fn the caller invokes
83
149
  * to cancel the stream. */
84
- streamChat(s, l) {
85
- const r = new AbortController();
150
+ streamChat(n, i) {
151
+ const l = new AbortController();
86
152
  return (async () => {
87
153
  try {
88
- const n = await fetch(`${this.baseUrl}${F}/chat`, {
154
+ const a = await fetch(`${this.baseUrl}${S}/chat`, {
89
155
  method: "POST",
90
- signal: r.signal,
156
+ signal: l.signal,
91
157
  headers: this.headers({ "Content-Type": "application/json", Accept: "text/event-stream" }),
92
- body: JSON.stringify(s)
158
+ body: JSON.stringify(n)
93
159
  });
94
- if (!n.ok || !n.body) {
95
- let m = `${n.status} ${n.statusText}`;
160
+ if (!a.ok || !a.body) {
161
+ let d = `${a.status} ${a.statusText}`;
96
162
  try {
97
- const f = await n.json();
98
- m = (f == null ? void 0 : f.detail) || m;
99
- } catch (f) {
163
+ const h = await a.json();
164
+ d = (h == null ? void 0 : h.detail) || d;
165
+ } catch (h) {
100
166
  }
101
- l({ type: "error", error: m });
167
+ i({ type: "error", error: d });
102
168
  return;
103
169
  }
104
- const o = n.body.getReader(), i = new TextDecoder();
105
- let a = "";
170
+ const o = a.body.getReader(), s = new TextDecoder();
171
+ let r = "";
106
172
  for (; ; ) {
107
- const { value: m, done: f } = await o.read();
108
- if (f) break;
109
- a += i.decode(m, { stream: !0 });
110
- let N;
111
- for (; (N = a.indexOf(`
173
+ const { value: d, done: h } = await o.read();
174
+ if (h) break;
175
+ r += s.decode(d, { stream: !0 });
176
+ let w;
177
+ for (; (w = r.indexOf(`
112
178
 
113
179
  `)) !== -1; ) {
114
- const E = a.slice(0, N);
115
- a = a.slice(N + 2);
116
- const u = E.trim();
117
- if (u.startsWith("data:"))
180
+ const y = r.slice(0, w);
181
+ r = r.slice(w + 2);
182
+ const k = y.trim();
183
+ if (k.startsWith("data:"))
118
184
  try {
119
- const S = JSON.parse(u.slice(5).trim());
120
- l(S);
121
- } catch (S) {
185
+ const L = JSON.parse(k.slice(5).trim());
186
+ i(L);
187
+ } catch (L) {
122
188
  }
123
189
  }
124
190
  }
125
- } catch (n) {
126
- (n == null ? void 0 : n.name) !== "AbortError" && l({ type: "error", error: (n == null ? void 0 : n.message) || String(n) });
191
+ } catch (a) {
192
+ (a == null ? void 0 : a.name) !== "AbortError" && i({ type: "error", error: (a == null ? void 0 : a.message) || String(a) });
127
193
  }
128
- })(), () => r.abort();
194
+ })(), () => l.abort();
129
195
  }
130
196
  }
131
- const x = {
197
+ const F = {
132
198
  apiBaseUrl: "https://api.docgenlab.com",
133
199
  position: "bottom-right",
134
200
  primary: "#4F46E5",
@@ -138,194 +204,343 @@ const x = {
138
204
  greeting: "How can I help you today?",
139
205
  greetingSub: "Ask anything about your uploaded documents. I'll only answer from what's in the knowledge base."
140
206
  };
141
- function z(t) {
142
- var te, ne, ae, re, le, se, ie, oe;
143
- const s = t.apiBaseUrl || x.apiBaseUrl, l = t.enableImageUpload !== !1, r = _(null), n = `${t.agentKey}::${t.endUserId || ""}::${t.endUserHash || ""}`, o = _("");
144
- (!r.current || o.current !== n) && (r.current = new xe({
207
+ function le(t) {
208
+ var de, me, ge, ue, he, fe, pe, ke;
209
+ const n = t.apiBaseUrl || F.apiBaseUrl, i = t.enableImageUpload !== !1, l = j(null), a = `${t.agentKey}::${t.endUserId || ""}::${t.endUserHash || ""}`, o = j("");
210
+ (!l.current || o.current !== a) && (l.current = new Te({
145
211
  agentKey: t.agentKey,
146
- apiBaseUrl: s,
212
+ apiBaseUrl: n,
147
213
  endUserId: t.endUserId,
148
214
  endUserHash: t.endUserHash
149
- }), o.current = n);
150
- const i = r.current, [a, m] = p(null), [f, N] = p(null), E = (a == null ? void 0 : a.widget_config) || {}, u = {
151
- position: t.position || E.position || x.position,
152
- primary: ((te = t.theme) == null ? void 0 : te.primary) || E.primary_color || x.primary,
153
- primaryText: ((ne = t.theme) == null ? void 0 : ne.primaryText) || E.primary_text_color || x.primaryText,
154
- radius: ((ae = t.theme) == null ? void 0 : ae.radius) || E.radius || x.radius,
155
- fontFamily: ((re = t.theme) == null ? void 0 : re.fontFamily) || x.fontFamily,
156
- greeting: t.greeting || E.greeting || x.greeting,
157
- agentName: t.agentName || E.agent_name || (a == null ? void 0 : a.name) || "Assistant",
158
- agentAvatarUrl: t.agentAvatarUrl || E.agent_avatar_url || void 0,
159
- launcherAvatarUrl: E.launcher_avatar_url || void 0,
160
- hideBranding: (se = (le = t.hideBranding) != null ? le : E.hide_branding) != null ? se : !1,
161
- openOnLoad: (oe = (ie = t.openOnLoad) != null ? ie : E.open_on_load) != null ? oe : !1
162
- }, S = {
163
- "--dgl-primary": u.primary,
164
- "--dgl-primary-text": u.primaryText,
165
- "--dgl-radius": u.radius,
166
- "--dgl-font": u.fontFamily
167
- }, [R, J] = p(u.openOnLoad), [A, ye] = p(!1), [T, U] = p([]), [O, W] = p(""), [$, B] = p(!1), [D, M] = p(null), [Y, G] = p(null), [k, H] = p(null), [j, V] = p(!1), Q = _(null), X = _(null), K = _(""), P = _(null);
168
- C(() => {
169
- !R || a || i.getAgent().then((c) => {
170
- var d;
171
- m(c), (d = t.onReady) == null || d.call(t, c);
172
- }).catch((c) => {
173
- var d;
174
- N(c.message), (d = t.onError) == null || d.call(t, c.message);
215
+ }), o.current = a);
216
+ const s = l.current, [r, d] = f(null), [h, w] = f(null), y = (r == null ? void 0 : r.widget_config) || {}, k = {
217
+ position: t.position || y.position || F.position,
218
+ primary: ((de = t.theme) == null ? void 0 : de.primary) || y.primary_color || F.primary,
219
+ primaryText: ((me = t.theme) == null ? void 0 : me.primaryText) || y.primary_text_color || F.primaryText,
220
+ radius: ((ge = t.theme) == null ? void 0 : ge.radius) || y.radius || F.radius,
221
+ fontFamily: ((ue = t.theme) == null ? void 0 : ue.fontFamily) || F.fontFamily,
222
+ greeting: t.greeting || y.greeting || F.greeting,
223
+ agentName: t.agentName || y.agent_name || (r == null ? void 0 : r.name) || "Assistant",
224
+ agentAvatarUrl: t.agentAvatarUrl || y.agent_avatar_url || void 0,
225
+ launcherAvatarUrl: y.launcher_avatar_url || void 0,
226
+ hideBranding: (fe = (he = t.hideBranding) != null ? he : y.hide_branding) != null ? fe : !1,
227
+ openOnLoad: (ke = (pe = t.openOnLoad) != null ? pe : y.open_on_load) != null ? ke : !1
228
+ }, L = {
229
+ "--dgl-primary": k.primary,
230
+ "--dgl-primary-text": k.primaryText,
231
+ "--dgl-radius": k.radius,
232
+ "--dgl-font": k.fontFamily
233
+ }, [_, R] = f(k.openOnLoad), [C, P] = f(!1), [E, I] = f([]), [W, q] = f(""), [D, G] = f(!1), [K, J] = f(null), [re, Q] = f(null), [$, Z] = f(null), [H, ee] = f(!1), ie = j(null), te = j(null), X = j(""), V = j(null), [ae, ne] = f([]), [Ue, se] = f(!1);
234
+ T(() => {
235
+ !_ || r || s.getAgent().then((m) => {
236
+ var b;
237
+ d(m), (b = t.onReady) == null || b.call(t, m);
238
+ }).catch((m) => {
239
+ var b;
240
+ w(m.message), (b = t.onError) == null || b.call(t, m.message);
175
241
  });
176
- }, [R, a, i, t]), C(() => {
177
- const c = `dgl-chat:${t.agentKey}`, d = localStorage.getItem(c);
178
- d && M(d);
179
- }, [t.agentKey]), C(() => {
180
- D && localStorage.setItem(`dgl-chat:${t.agentKey}`, D);
181
- }, [D, t.agentKey]), C(() => {
182
- P.current && (P.current.scrollTop = P.current.scrollHeight);
183
- }, [T]);
184
- const Z = me(() => {
185
- k && URL.revokeObjectURL(k), G(null), H(null);
186
- }, [k]), ee = me((c) => {
187
- if (!c.type.startsWith("image/")) return;
188
- const d = 10 * 1024 * 1024;
189
- c.size > d || (k && URL.revokeObjectURL(k), G(c), H(URL.createObjectURL(c)));
190
- }, [k]), Ee = async (c) => {
191
- var ce;
192
- if (c.preventDefault(), !O.trim() || $ || j) return;
193
- const d = O.trim();
194
- let b, w;
195
- if (Y) {
242
+ }, [_, r, s, t]), T(() => {
243
+ if (!_ || t.disableTicketing) return;
244
+ let m = !1;
245
+ return s.listTickets().then((b) => {
246
+ m || ne(b);
247
+ }).catch(() => {
248
+ }), () => {
249
+ m = !0;
250
+ };
251
+ }, [_, s, t.disableTicketing]), T(() => {
252
+ if (!_) return;
253
+ const m = `dgl-chat:${t.agentKey}`, b = localStorage.getItem(m);
254
+ if (!b) return;
255
+ let x = !1;
256
+ return (async () => {
257
+ try {
258
+ const [v, p] = await Promise.all([
259
+ s.getConversation(b),
260
+ s.getTicketCardState(b).catch(() => null)
261
+ ]);
262
+ if (x) return;
263
+ const c = [];
264
+ for (const U of v.messages || [])
265
+ U.role === "user" ? c.push({
266
+ id: U.id,
267
+ role: "user",
268
+ content: U.content || "",
269
+ imagePath: U.image_path || void 0
270
+ }) : U.role === "assistant" && c.push({
271
+ id: U.id,
272
+ role: "assistant",
273
+ content: U.content || "",
274
+ citations: U.retrieved_chunks || void 0
275
+ });
276
+ if (p && p.kind && c.length) {
277
+ let U = -1;
278
+ for (let g = c.length - 1; g >= 0; g--)
279
+ if (c[g].role === "assistant") {
280
+ U = g;
281
+ break;
282
+ }
283
+ if (U >= 0) {
284
+ const g = c[U];
285
+ p.kind === "offer" && p.conversation_id && p.connector_type && p.connector_name ? g.ticketOffer = {
286
+ conversationId: p.conversation_id,
287
+ connectorType: p.connector_type,
288
+ connectorName: p.connector_name
289
+ } : p.kind === "existing" && p.ticket_id && p.status ? g.ticketExisting = {
290
+ ticketId: p.ticket_id,
291
+ externalNumber: p.external_ticket_number || null,
292
+ externalUrl: p.external_url || null,
293
+ status: p.status
294
+ } : p.kind === "created" && p.ticket_id && (g.ticketCreated = {
295
+ id: p.ticket_id,
296
+ externalNumber: p.external_ticket_number || null,
297
+ externalUrl: p.external_url || null
298
+ });
299
+ }
300
+ }
301
+ J(b), I(c);
302
+ } catch (v) {
303
+ localStorage.removeItem(m);
304
+ }
305
+ })(), () => {
306
+ x = !0;
307
+ };
308
+ }, [t.agentKey, s, _]), T(() => {
309
+ K && localStorage.setItem(`dgl-chat:${t.agentKey}`, K);
310
+ }, [K, t.agentKey]), T(() => {
311
+ V.current && (V.current.scrollTop = V.current.scrollHeight);
312
+ }, [E]);
313
+ const ce = be(() => {
314
+ $ && URL.revokeObjectURL($), Q(null), Z(null);
315
+ }, [$]), oe = be((m) => {
316
+ if (!m.type.startsWith("image/")) return;
317
+ const b = 10 * 1024 * 1024;
318
+ m.size > b || ($ && URL.revokeObjectURL($), Q(m), Z(URL.createObjectURL(m)));
319
+ }, [$]), Ce = async (m) => {
320
+ var p;
321
+ if (m.preventDefault(), !W.trim() || D || H) return;
322
+ const b = W.trim();
323
+ let x, v;
324
+ if (re) {
196
325
  try {
197
- V(!0), b = await i.uploadImage(Y);
198
- } catch (g) {
199
- (ce = t.onError) == null || ce.call(t, (g == null ? void 0 : g.message) || "Image upload failed"), V(!1);
326
+ ee(!0), x = await s.uploadImage(re);
327
+ } catch (c) {
328
+ (p = t.onError) == null || p.call(t, (c == null ? void 0 : c.message) || "Image upload failed"), ee(!1);
200
329
  return;
201
330
  }
202
- V(!1), w = k || void 0;
331
+ ee(!1), v = $ || void 0;
203
332
  }
204
- W(""), K.current = "", U((g) => [
205
- ...g,
206
- { role: "user", content: d, imagePath: b, imagePreviewUrl: w },
333
+ q(""), X.current = "", I((c) => [
334
+ ...c,
335
+ { role: "user", content: b, imagePath: x, imagePreviewUrl: v },
207
336
  { role: "assistant", content: "", streaming: !0 }
208
- ]), B(!0), G(null), H(null), X.current = i.streamChat(
209
- { message: d, conversation_id: D || void 0, image_path: b },
210
- (g) => {
211
- var de;
212
- if (g.type === "conversation")
213
- M(g.conversation_id);
214
- else if (g.type === "token") {
215
- K.current += g.content;
216
- const y = K.current;
217
- U((h) => h.map(
218
- (v, ve) => ve === h.length - 1 && v.role === "assistant" ? { ...v, content: y } : v
337
+ ]), G(!0), Q(null), Z(null), te.current = s.streamChat(
338
+ { message: b, conversation_id: K || void 0, image_path: x },
339
+ (c) => {
340
+ var U;
341
+ if (c.type === "conversation")
342
+ J(c.conversation_id);
343
+ else if (c.type === "token") {
344
+ X.current += c.content;
345
+ const g = X.current;
346
+ I((u) => u.map(
347
+ (N, Ie) => Ie === u.length - 1 && N.role === "assistant" ? { ...N, content: g } : N
219
348
  ));
220
- } else g.type === "citations" ? U((y) => y.map(
221
- (h, v) => v === y.length - 1 && h.role === "assistant" ? { ...h, citations: g.citations } : h
222
- )) : g.type === "refused" ? (K.current = g.content, U((y) => y.map(
223
- (h, v) => v === y.length - 1 && h.role === "assistant" ? { ...h, content: g.content, refused: !0 } : h
224
- ))) : g.type === "done" ? (U((y) => y.map(
225
- (h, v) => v === y.length - 1 && h.role === "assistant" ? { ...h, streaming: !1, id: g.message_id, cacheHit: g.cache_hit } : h
226
- )), B(!1)) : g.type === "error" && (U((y) => y.map(
227
- (h, v) => v === y.length - 1 && h.role === "assistant" ? { ...h, content: `Error: ${g.error}`, streaming: !1, refused: !0 } : h
228
- )), B(!1), (de = t.onError) == null || de.call(t, g.error));
349
+ } else if (c.type === "citations")
350
+ I((g) => g.map(
351
+ (u, N) => N === g.length - 1 && u.role === "assistant" ? { ...u, citations: c.citations } : u
352
+ ));
353
+ else if (c.type === "refused")
354
+ X.current = c.content, I((g) => g.map(
355
+ (u, N) => N === g.length - 1 && u.role === "assistant" ? { ...u, content: c.content, refused: !0 } : u
356
+ ));
357
+ else if (c.type === "ticket_offer") {
358
+ if (t.disableTicketing) return;
359
+ I((g) => g.map(
360
+ (u, N) => N === g.length - 1 && u.role === "assistant" ? {
361
+ ...u,
362
+ ticketOffer: {
363
+ conversationId: c.conversation_id,
364
+ connectorType: c.connector_type,
365
+ connectorName: c.connector_name
366
+ }
367
+ } : u
368
+ ));
369
+ } else if (c.type === "ticket_existing") {
370
+ if (t.disableTicketing) return;
371
+ I((g) => g.map(
372
+ (u, N) => N === g.length - 1 && u.role === "assistant" ? {
373
+ ...u,
374
+ ticketExisting: {
375
+ ticketId: c.ticket_id,
376
+ externalNumber: c.external_ticket_number,
377
+ externalUrl: c.external_url,
378
+ status: c.status
379
+ }
380
+ } : u
381
+ ));
382
+ } else c.type === "ticket_status_card" ? I((g) => g.map(
383
+ (u, N) => N === g.length - 1 && u.role === "assistant" ? {
384
+ ...u,
385
+ ticketStatus: {
386
+ ticketId: c.ticket_id,
387
+ externalNumber: c.external_number,
388
+ externalUrl: c.external_url,
389
+ status: c.status,
390
+ title: c.title,
391
+ priority: c.priority,
392
+ lastUpdate: c.last_update,
393
+ assignedTo: c.assigned_to,
394
+ createdAt: c.created_at
395
+ }
396
+ } : u
397
+ )) : c.type === "done" ? (I((g) => g.map(
398
+ (u, N) => N === g.length - 1 && u.role === "assistant" ? { ...u, streaming: !1, id: c.message_id, cacheHit: c.cache_hit } : u
399
+ )), G(!1)) : c.type === "error" && (I((g) => g.map(
400
+ (u, N) => N === g.length - 1 && u.role === "assistant" ? { ...u, content: `Error: ${c.error}`, streaming: !1, refused: !0 } : u
401
+ )), G(!1), (U = t.onError) == null || U.call(t, c.error));
229
402
  }
230
403
  );
231
- }, be = () => {
232
- X.current && X.current(), U([]), M(null), B(!1), localStorage.removeItem(`dgl-chat:${t.agentKey}`), Z();
404
+ }, Le = () => {
405
+ te.current && te.current(), I([]), J(null), G(!1), localStorage.removeItem(`dgl-chat:${t.agentKey}`), ce();
233
406
  };
234
- return /* @__PURE__ */ e.createElement("div", { className: `dgl-root dgl-pos-${u.position}`, style: S }, R && /* @__PURE__ */ e.createElement("div", { className: `dgl-panel ${A ? "dgl-panel-expanded" : ""}` }, /* @__PURE__ */ e.createElement("div", { className: "dgl-header" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-header-info" }, u.agentAvatarUrl ? /* @__PURE__ */ e.createElement("img", { src: u.agentAvatarUrl, alt: "", className: "dgl-avatar" }) : /* @__PURE__ */ e.createElement("div", { className: "dgl-avatar dgl-avatar-fallback dgl-avatar-fallback-light" }, u.agentName.slice(0, 1).toUpperCase()), /* @__PURE__ */ e.createElement("div", { className: "dgl-header-text" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-title" }, u.agentName), (a == null ? void 0 : a.org_name) && /* @__PURE__ */ e.createElement("div", { className: "dgl-subtitle" }, a.org_name))), /* @__PURE__ */ e.createElement("div", { className: "dgl-header-actions" }, /* @__PURE__ */ e.createElement(
407
+ return /* @__PURE__ */ e.createElement("div", { className: `dgl-root dgl-pos-${k.position}`, style: L }, _ && /* @__PURE__ */ e.createElement("div", { className: `dgl-panel ${C ? "dgl-panel-expanded" : ""}` }, /* @__PURE__ */ e.createElement("div", { className: "dgl-header" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-header-info" }, k.agentAvatarUrl ? /* @__PURE__ */ e.createElement("img", { src: k.agentAvatarUrl, alt: "", className: "dgl-avatar" }) : /* @__PURE__ */ e.createElement("div", { className: "dgl-avatar dgl-avatar-fallback dgl-avatar-fallback-light" }, k.agentName.slice(0, 1).toUpperCase()), /* @__PURE__ */ e.createElement("div", { className: "dgl-header-text" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-title" }, k.agentName), (r == null ? void 0 : r.org_name) && /* @__PURE__ */ e.createElement("div", { className: "dgl-subtitle" }, r.org_name))), /* @__PURE__ */ e.createElement("div", { className: "dgl-header-actions" }, !t.disableTicketing && ae.length > 0 && /* @__PURE__ */ e.createElement(
408
+ "button",
409
+ {
410
+ type: "button",
411
+ onClick: () => se(!0),
412
+ className: "dgl-tix-btn",
413
+ title: "Your tickets",
414
+ "aria-label": "Your tickets"
415
+ },
416
+ M(),
417
+ /* @__PURE__ */ e.createElement("span", null, "Tickets"),
418
+ /* @__PURE__ */ e.createElement("span", { className: "dgl-tix-btn-badge" }, ae.length)
419
+ ), /* @__PURE__ */ e.createElement(
235
420
  "button",
236
421
  {
237
422
  type: "button",
238
- onClick: be,
423
+ onClick: Le,
239
424
  className: "dgl-icon-btn",
240
425
  title: "New chat",
241
426
  "aria-label": "New chat"
242
427
  },
243
- Oe()
428
+ Je()
244
429
  ), /* @__PURE__ */ e.createElement(
245
430
  "button",
246
431
  {
247
432
  type: "button",
248
- onClick: () => ye((c) => !c),
433
+ onClick: () => P((m) => !m),
249
434
  className: "dgl-icon-btn dgl-hide-on-mobile",
250
- title: A ? "Restore size" : "Expand view",
251
- "aria-label": A ? "Restore size" : "Expand view"
435
+ title: C ? "Restore size" : "Expand view",
436
+ "aria-label": C ? "Restore size" : "Expand view"
252
437
  },
253
- A ? Pe() : Ke()
438
+ C ? tt() : et()
254
439
  ), /* @__PURE__ */ e.createElement(
255
440
  "button",
256
441
  {
257
442
  type: "button",
258
- onClick: () => J(!1),
443
+ onClick: () => R(!1),
259
444
  className: "dgl-icon-btn",
260
445
  title: "Close",
261
446
  "aria-label": "Close"
262
447
  },
263
- q()
264
- ))), /* @__PURE__ */ e.createElement("div", { className: "dgl-messages", ref: P }, T.length === 0 && !f && /* @__PURE__ */ e.createElement("div", { className: "dgl-empty" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-empty-icon" }, pe()), /* @__PURE__ */ e.createElement("div", { className: "dgl-empty-text" }, u.greeting), /* @__PURE__ */ e.createElement("div", { className: "dgl-empty-sub" }, (a == null ? void 0 : a.description) || x.greetingSub)), f && /* @__PURE__ */ e.createElement("div", { className: "dgl-error" }, "Couldn't load the assistant: ", f), T.map((c, d) => /* @__PURE__ */ e.createElement(
265
- Ne,
448
+ Y()
449
+ ))), Ue && /* @__PURE__ */ e.createElement(
450
+ Ve,
451
+ {
452
+ tickets: ae,
453
+ onClose: () => se(!1),
454
+ onRefresh: async () => {
455
+ try {
456
+ const m = await s.listTickets();
457
+ ne(m);
458
+ } catch (m) {
459
+ }
460
+ }
461
+ }
462
+ ), /* @__PURE__ */ e.createElement("div", { className: "dgl-messages", ref: V }, E.length === 0 && !h && /* @__PURE__ */ e.createElement("div", { className: "dgl-empty" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-empty-icon" }, _e()), /* @__PURE__ */ e.createElement("div", { className: "dgl-empty-text" }, k.greeting), /* @__PURE__ */ e.createElement("div", { className: "dgl-empty-sub" }, (r == null ? void 0 : r.description) || F.greetingSub)), h && /* @__PURE__ */ e.createElement("div", { className: "dgl-error" }, "Couldn't load the assistant: ", h), E.map((m, b) => /* @__PURE__ */ e.createElement(
463
+ Re,
266
464
  {
267
- key: d,
268
- message: c,
269
- client: i,
270
- isLast: d === T.length - 1,
271
- agentAvatarUrl: u.agentAvatarUrl,
272
- onPickFollowup: (b) => {
273
- W(b);
465
+ key: b,
466
+ message: m,
467
+ client: s,
468
+ isLast: b === E.length - 1,
469
+ agentAvatarUrl: k.agentAvatarUrl,
470
+ onPickFollowup: (x) => {
471
+ q(x);
472
+ },
473
+ defaultEmail: t.endUserEmail,
474
+ defaultPhone: t.endUserPhone,
475
+ conversationId: K || void 0,
476
+ onTicketCreated: (x, v) => {
477
+ I((p) => p.map((c) => c === x ? {
478
+ ...c,
479
+ // Either an existing-issue card OR a fresh offer
480
+ // can land here — clear both, render created.
481
+ ticketOffer: void 0,
482
+ ticketExisting: void 0,
483
+ ticketCreated: {
484
+ id: v.id,
485
+ externalNumber: v.external_ticket_number,
486
+ externalUrl: v.external_url
487
+ }
488
+ } : c)), ne((p) => [v, ...p.filter((c) => c.id !== v.id)]);
274
489
  }
275
490
  }
276
- ))), /* @__PURE__ */ e.createElement("form", { className: "dgl-composer", onSubmit: Ee }, k && /* @__PURE__ */ e.createElement("div", { className: "dgl-staged-image" }, /* @__PURE__ */ e.createElement("img", { src: k, alt: "attachment" }), /* @__PURE__ */ e.createElement(
491
+ ))), /* @__PURE__ */ e.createElement("form", { className: "dgl-composer", onSubmit: Ce }, $ && /* @__PURE__ */ e.createElement("div", { className: "dgl-staged-image" }, /* @__PURE__ */ e.createElement("img", { src: $, alt: "attachment" }), /* @__PURE__ */ e.createElement(
277
492
  "button",
278
493
  {
279
494
  type: "button",
280
- onClick: Z,
495
+ onClick: ce,
281
496
  className: "dgl-staged-remove",
282
497
  "aria-label": "Remove image"
283
498
  },
284
- q()
285
- )), /* @__PURE__ */ e.createElement("div", { className: "dgl-composer-row" }, l && /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(
499
+ Y()
500
+ )), /* @__PURE__ */ e.createElement("div", { className: "dgl-composer-row" }, i && /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(
286
501
  "button",
287
502
  {
288
503
  type: "button",
289
504
  className: "dgl-icon-btn",
290
505
  onClick: () => {
291
- var c;
292
- return (c = Q.current) == null ? void 0 : c.click();
506
+ var m;
507
+ return (m = ie.current) == null ? void 0 : m.click();
293
508
  },
294
- disabled: $ || j,
509
+ disabled: D || H,
295
510
  title: "Attach image",
296
511
  "aria-label": "Attach image"
297
512
  },
298
- De()
513
+ Ze()
299
514
  ), /* @__PURE__ */ e.createElement(
300
515
  "input",
301
516
  {
302
- ref: Q,
517
+ ref: ie,
303
518
  type: "file",
304
519
  accept: "image/png,image/jpeg,image/webp,image/gif",
305
520
  style: { display: "none" },
306
- onChange: (c) => {
307
- var b;
308
- const d = (b = c.target.files) == null ? void 0 : b[0];
309
- d && ee(d), c.target && (c.target.value = "");
521
+ onChange: (m) => {
522
+ var x;
523
+ const b = (x = m.target.files) == null ? void 0 : x[0];
524
+ b && oe(b), m.target && (m.target.value = "");
310
525
  }
311
526
  }
312
527
  )), /* @__PURE__ */ e.createElement(
313
528
  "input",
314
529
  {
315
530
  className: "dgl-input",
316
- value: O,
317
- onChange: (c) => W(c.target.value),
318
- placeholder: $ ? "Thinking…" : k ? "Describe what to know about this image…" : "Type your question…",
319
- disabled: $,
320
- onPaste: (c) => {
321
- var b;
322
- if (!l) return;
323
- const d = Array.from(((b = c.clipboardData) == null ? void 0 : b.items) || []).find(
324
- (w) => w.kind === "file" && w.type.startsWith("image/")
531
+ value: W,
532
+ onChange: (m) => q(m.target.value),
533
+ placeholder: D ? "Thinking…" : $ ? "Describe what to know about this image…" : "Type your question…",
534
+ disabled: D,
535
+ onPaste: (m) => {
536
+ var x;
537
+ if (!i) return;
538
+ const b = Array.from(((x = m.clipboardData) == null ? void 0 : x.items) || []).find(
539
+ (v) => v.kind === "file" && v.type.startsWith("image/")
325
540
  );
326
- if (d) {
327
- const w = d.getAsFile();
328
- w && (c.preventDefault(), ee(w));
541
+ if (b) {
542
+ const v = b.getAsFile();
543
+ v && (m.preventDefault(), oe(v));
329
544
  }
330
545
  }
331
546
  }
@@ -334,262 +549,556 @@ function z(t) {
334
549
  {
335
550
  type: "submit",
336
551
  className: "dgl-send-btn",
337
- disabled: !O.trim() || $ || j,
552
+ disabled: !W.trim() || D || H,
338
553
  "aria-label": "Send"
339
554
  },
340
- $ || j ? je() : Be()
341
- )), !u.hideBranding && /* @__PURE__ */ e.createElement("div", { className: "dgl-branding" }, "Powered by ", /* @__PURE__ */ e.createElement("a", { href: "https://docgenlab.com", target: "_blank", rel: "noopener noreferrer" }, "DocGenLab")))), /* @__PURE__ */ e.createElement(
555
+ D || H ? z() : Qe()
556
+ )), !k.hideBranding && /* @__PURE__ */ e.createElement("div", { className: "dgl-branding" }, "Powered by ", /* @__PURE__ */ e.createElement("a", { href: "https://docgenlab.com", target: "_blank", rel: "noopener noreferrer" }, "DocGenLab")))), /* @__PURE__ */ e.createElement(
342
557
  "button",
343
558
  {
344
559
  type: "button",
345
560
  className: "dgl-launcher",
346
- onClick: () => J((c) => !c),
347
- "aria-label": R ? "Close chat" : "Open chat"
561
+ onClick: () => R((m) => !m),
562
+ "aria-label": _ ? "Close chat" : "Open chat"
348
563
  },
349
- R ? Te() : u.launcherAvatarUrl ? /* @__PURE__ */ e.createElement("img", { src: u.launcherAvatarUrl, alt: "", className: "dgl-launcher-avatar" }) : Ae()
564
+ _ ? qe() : k.launcherAvatarUrl ? /* @__PURE__ */ e.createElement("img", { src: k.launcherAvatarUrl, alt: "", className: "dgl-launcher-avatar" }) : ze()
350
565
  ));
351
566
  }
352
- function Ne({
567
+ function Re({
353
568
  message: t,
354
- client: s,
355
- isLast: l,
356
- agentAvatarUrl: r,
357
- onPickFollowup: n
569
+ client: n,
570
+ isLast: i,
571
+ agentAvatarUrl: l,
572
+ onPickFollowup: a,
573
+ defaultEmail: o,
574
+ defaultPhone: s,
575
+ conversationId: r,
576
+ onTicketCreated: d
358
577
  }) {
359
- var a;
578
+ var y;
360
579
  if (t.role === "user")
361
- return /* @__PURE__ */ e.createElement("div", { className: "dgl-msg dgl-msg-user" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-bubble dgl-bubble-user" }, (t.imagePath || t.imagePreviewUrl) && /* @__PURE__ */ e.createElement(Ce, { client: s, imagePath: t.imagePath, previewUrl: t.imagePreviewUrl }), t.content));
362
- const o = Re(t.content), i = t.streaming ? [] : _e(t.content);
363
- return /* @__PURE__ */ e.createElement("div", { className: "dgl-msg dgl-msg-assistant" }, r ? /* @__PURE__ */ e.createElement("img", { src: r, className: "dgl-avatar", alt: "" }) : /* @__PURE__ */ e.createElement("div", { className: "dgl-avatar dgl-avatar-fallback" }, pe()), /* @__PURE__ */ e.createElement("div", { className: "dgl-msg-body" }, t.refused ? /* @__PURE__ */ e.createElement("div", { className: "dgl-refused" }, o) : /* @__PURE__ */ e.createElement("div", { className: "dgl-assistant-text" }, t.streaming && !o ? /* @__PURE__ */ e.createElement(Se, null) : /* @__PURE__ */ e.createElement(e.Fragment, null, Fe(o), t.streaming && /* @__PURE__ */ e.createElement("span", { className: "dgl-typing-cursor" }, "▍"))), !t.streaming && !!((a = t.citations) != null && a.length) && /* @__PURE__ */ e.createElement(Ie, { citations: t.citations, client: s }), i.length > 0 && /* @__PURE__ */ e.createElement(Ue, { suggestions: i, onPick: n })));
580
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-msg dgl-msg-user" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-bubble dgl-bubble-user" }, (t.imagePath || t.imagePreviewUrl) && /* @__PURE__ */ e.createElement(Be, { client: n, imagePath: t.imagePath, previewUrl: t.imagePreviewUrl }), t.content));
581
+ const h = Me(t.content), w = t.streaming ? [] : je(t.content);
582
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-msg dgl-msg-assistant" }, l ? /* @__PURE__ */ e.createElement("img", { src: l, className: "dgl-avatar", alt: "" }) : /* @__PURE__ */ e.createElement("div", { className: "dgl-avatar dgl-avatar-fallback" }, _e()), /* @__PURE__ */ e.createElement("div", { className: "dgl-msg-body" }, t.refused ? /* @__PURE__ */ e.createElement("div", { className: "dgl-refused" }, h) : t.ticketStatus ? (
583
+ /* Status query — suppress the markdown body and render
584
+ the rich Jira-style card on its own. */
585
+ /* @__PURE__ */ e.createElement(Xe, { ticket: t.ticketStatus })
586
+ ) : /* @__PURE__ */ e.createElement("div", { className: "dgl-assistant-text" }, t.streaming && !h ? /* @__PURE__ */ e.createElement(Ke, null) : /* @__PURE__ */ e.createElement(e.Fragment, null, Pe(h), t.streaming && /* @__PURE__ */ e.createElement("span", { className: "dgl-typing-cursor" }, "▍"))), !t.streaming && !t.refused && !!((y = t.citations) != null && y.length) && !t.ticketStatus && /* @__PURE__ */ e.createElement(Oe, { citations: t.citations, client: n }), !t.streaming && !t.ticketStatus && t.ticketCreated ? /* @__PURE__ */ e.createElement(Ge, { created: t.ticketCreated }) : !t.streaming && !t.ticketStatus && t.ticketExisting ? /* @__PURE__ */ e.createElement(
587
+ He,
588
+ {
589
+ existing: t.ticketExisting,
590
+ client: n,
591
+ conversationId: r,
592
+ defaultEmail: o,
593
+ defaultPhone: s,
594
+ onNewTicketRaised: (k) => d == null ? void 0 : d(t, k)
595
+ }
596
+ ) : !t.streaming && !t.ticketStatus && t.ticketOffer ? /* @__PURE__ */ e.createElement(
597
+ We,
598
+ {
599
+ client: n,
600
+ offer: t.ticketOffer,
601
+ defaultEmail: o,
602
+ defaultPhone: s,
603
+ onCreated: (k) => d == null ? void 0 : d(t, k)
604
+ }
605
+ ) : null, w.length > 0 && /* @__PURE__ */ e.createElement(Fe, { suggestions: w, onPick: a })));
364
606
  }
365
- function Ue({
607
+ function Fe({
366
608
  suggestions: t,
367
- onPick: s
609
+ onPick: n
368
610
  }) {
369
- return /* @__PURE__ */ e.createElement("div", { className: "dgl-followups" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-followups-label" }, "Continue exploring"), /* @__PURE__ */ e.createElement("div", { className: "dgl-followups-list" }, t.map((l, r) => /* @__PURE__ */ e.createElement(
611
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-followups" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-followups-label" }, "Continue exploring"), /* @__PURE__ */ e.createElement("div", { className: "dgl-followups-list" }, t.map((i, l) => /* @__PURE__ */ e.createElement(
370
612
  "button",
371
613
  {
372
- key: r,
614
+ key: l,
373
615
  type: "button",
374
616
  className: "dgl-followup-chip",
375
- onClick: () => s(l)
617
+ onClick: () => n(i)
376
618
  },
377
- l
619
+ i
378
620
  ))));
379
621
  }
380
- function Ce({
622
+ function Be({
381
623
  client: t,
382
- imagePath: s,
383
- previewUrl: l
624
+ imagePath: n,
625
+ previewUrl: i
384
626
  }) {
385
- const [r, n] = p(l || null), [o, i] = p(!1);
386
- return C(() => {
387
- if (l || !s) return;
388
- let a = null;
389
- return t.fetchImage(s).then((m) => {
390
- a = m, n(m);
391
- }).catch(() => n(null)), () => {
392
- a && URL.revokeObjectURL(a);
627
+ const [l, a] = f(i || null), [o, s] = f(!1);
628
+ return T(() => {
629
+ if (i || !n) return;
630
+ let r = null;
631
+ return t.fetchImage(n).then((d) => {
632
+ r = d, a(d);
633
+ }).catch(() => a(null)), () => {
634
+ r && URL.revokeObjectURL(r);
393
635
  };
394
- }, [t, s, l]), C(() => {
636
+ }, [t, n, i]), T(() => {
395
637
  if (!o) return;
396
- const a = (f) => {
397
- f.key === "Escape" && i(!1);
638
+ const r = (h) => {
639
+ h.key === "Escape" && s(!1);
398
640
  };
399
- window.addEventListener("keydown", a);
400
- const m = document.body.style.overflow;
641
+ window.addEventListener("keydown", r);
642
+ const d = document.body.style.overflow;
401
643
  return document.body.style.overflow = "hidden", () => {
402
- window.removeEventListener("keydown", a), document.body.style.overflow = m;
644
+ window.removeEventListener("keydown", r), document.body.style.overflow = d;
403
645
  };
404
- }, [o]), r ? /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(
646
+ }, [o]), l ? /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(
405
647
  "button",
406
648
  {
407
649
  type: "button",
408
- onClick: () => i(!0),
650
+ onClick: () => s(!0),
409
651
  className: "dgl-user-image-btn",
410
652
  "aria-label": "View image"
411
653
  },
412
- /* @__PURE__ */ e.createElement("img", { src: r, className: "dgl-user-image", alt: "attached" })
654
+ /* @__PURE__ */ e.createElement("img", { src: l, className: "dgl-user-image", alt: "attached" })
413
655
  ), o && /* @__PURE__ */ e.createElement(
414
656
  "div",
415
657
  {
416
658
  className: "dgl-lightbox",
417
659
  role: "dialog",
418
660
  "aria-modal": "true",
419
- onClick: () => i(!1)
661
+ onClick: () => s(!1)
420
662
  },
421
663
  /* @__PURE__ */ e.createElement(
422
664
  "button",
423
665
  {
424
666
  type: "button",
425
667
  className: "dgl-lightbox-close",
426
- onClick: (a) => {
427
- a.stopPropagation(), i(!1);
668
+ onClick: (r) => {
669
+ r.stopPropagation(), s(!1);
428
670
  },
429
671
  "aria-label": "Close image"
430
672
  },
431
- q()
673
+ Y()
432
674
  ),
433
675
  /* @__PURE__ */ e.createElement(
434
676
  "img",
435
677
  {
436
- src: r,
678
+ src: l,
437
679
  className: "dgl-lightbox-img",
438
680
  alt: "attached",
439
- onClick: (a) => a.stopPropagation()
681
+ onClick: (r) => r.stopPropagation()
440
682
  }
441
683
  )
442
684
  )) : null;
443
685
  }
444
- function Ie({ citations: t, client: s }) {
445
- const l = {};
446
- for (const a of t) {
447
- const m = l[a.source_id];
448
- (!m || a.score > m.score) && (l[a.source_id] = a);
686
+ function Oe({ citations: t, client: n }) {
687
+ const i = {};
688
+ for (const r of t) {
689
+ const d = i[r.source_id];
690
+ (!d || r.score > d.score) && (i[r.source_id] = r);
449
691
  }
450
- const r = Object.values(l).sort((a, m) => m.score - a.score).slice(0, 3), n = Object.keys(l).length - r.length;
451
- if (!r.length) return null;
452
- const [o, i] = p(null);
453
- return /* @__PURE__ */ e.createElement("div", { className: "dgl-citations" }, r.map((a) => /* @__PURE__ */ e.createElement(
454
- Le,
692
+ const l = Object.values(i).sort((r, d) => d.score - r.score).slice(0, 3), a = Object.keys(i).length - l.length;
693
+ if (!l.length) return null;
694
+ const [o, s] = f(null);
695
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-citations" }, l.map((r) => /* @__PURE__ */ e.createElement(
696
+ Ae,
455
697
  {
456
- key: a.chunk_id,
457
- citation: a,
458
- client: s,
459
- isOpen: o === a.chunk_id,
460
- onToggle: () => i(o === a.chunk_id ? null : a.chunk_id)
698
+ key: r.chunk_id,
699
+ citation: r,
700
+ client: n,
701
+ isOpen: o === r.chunk_id,
702
+ onToggle: () => s(o === r.chunk_id ? null : r.chunk_id)
461
703
  }
462
- )), n > 0 && /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-more" }, "+", n, " more"));
704
+ )), a > 0 && /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-more" }, "+", a, " more"));
463
705
  }
464
- function Le({
706
+ function Ae({
465
707
  citation: t,
466
- client: s,
467
- isOpen: l,
468
- onToggle: r
708
+ client: n,
709
+ isOpen: i,
710
+ onToggle: l
469
711
  }) {
470
- const n = t, o = !!n.frame_path, i = n.heading ? `${n.heading}${n.subheading ? " › " + n.subheading : ""}` : null, a = n.start_seconds != null ? `${Math.floor(n.start_seconds / 60)}:${String(n.start_seconds % 60).padStart(2, "0")}` : null;
712
+ const a = t, o = !!a.frame_path, s = a.heading ? `${a.heading}${a.subheading ? " › " + a.subheading : ""}` : null, r = a.start_seconds != null ? `${Math.floor(a.start_seconds / 60)}:${String(a.start_seconds % 60).padStart(2, "0")}` : null;
471
713
  return /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-wrap" }, /* @__PURE__ */ e.createElement(
472
714
  "button",
473
715
  {
474
716
  type: "button",
475
- className: `dgl-citation ${l ? "dgl-citation-open" : ""}`,
476
- onClick: r,
477
- title: n.snippet || ""
717
+ className: `dgl-citation ${i ? "dgl-citation-open" : ""}`,
718
+ onClick: l,
719
+ title: a.snippet || ""
478
720
  },
479
721
  o && /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-icon" }, "▶"),
480
- n.source_name,
481
- a && /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-stamp" }, " · ", a),
482
- n.page && /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-stamp" }, " · p", n.page)
483
- ), l && /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-popover" }, n.frame_path && /* @__PURE__ */ e.createElement(
484
- $e,
722
+ a.source_name,
723
+ r && /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-stamp" }, " · ", r),
724
+ a.page && /* @__PURE__ */ e.createElement("span", { className: "dgl-citation-stamp" }, " · p", a.page)
725
+ ), i && /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-popover" }, a.frame_path && /* @__PURE__ */ e.createElement(
726
+ De,
485
727
  {
486
- client: s,
487
- sourceId: n.source_id,
488
- framePath: n.frame_path
728
+ client: n,
729
+ sourceId: a.source_id,
730
+ framePath: a.frame_path
489
731
  }
490
- ), i && /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-breadcrumb" }, i), n.snippet && /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-snippet" }, n.snippet)));
732
+ ), s && /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-breadcrumb" }, s), a.snippet && /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-snippet" }, a.snippet)));
491
733
  }
492
- function $e({
734
+ function De({
493
735
  client: t,
494
- sourceId: s,
495
- framePath: l
736
+ sourceId: n,
737
+ framePath: i
496
738
  }) {
497
- const [r, n] = p(null);
498
- return C(() => {
739
+ const [l, a] = f(null);
740
+ return T(() => {
499
741
  let o = null;
500
- return t.fetchSourceFrame(s, l).then((i) => {
501
- o = i, n(i);
502
- }).catch(() => n(null)), () => {
742
+ return t.fetchSourceFrame(n, i).then((s) => {
743
+ o = s, a(s);
744
+ }).catch(() => a(null)), () => {
503
745
  o && URL.revokeObjectURL(o);
504
746
  };
505
- }, [t, s, l]), r ? /* @__PURE__ */ e.createElement("a", { href: r, target: "_blank", rel: "noopener noreferrer", className: "dgl-citation-frame-link" }, /* @__PURE__ */ e.createElement("img", { src: r, alt: "", className: "dgl-citation-frame" })) : /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-frame-loading" });
747
+ }, [t, n, i]), l ? /* @__PURE__ */ e.createElement("a", { href: l, target: "_blank", rel: "noopener noreferrer", className: "dgl-citation-frame-link" }, /* @__PURE__ */ e.createElement("img", { src: l, alt: "", className: "dgl-citation-frame" })) : /* @__PURE__ */ e.createElement("div", { className: "dgl-citation-frame-loading" });
506
748
  }
507
- function _e(t) {
508
- const s = t.match(/<followups>([\s\S]*?)<\/followups>/i);
509
- return s ? s[1].split(`
510
- `).map((l) => l.trim()).map((l) => l.replace(/^[-*•\d.)\s"']+|["']$/g, "").trim()).filter((l) => l.length >= 4 && l.length <= 120).slice(0, 3) : [];
749
+ function je(t) {
750
+ const n = t.match(/<followups>([\s\S]*?)<\/followups>/i);
751
+ return n ? n[1].split(`
752
+ `).map((i) => i.trim()).map((i) => i.replace(/^[-*•\d.)\s"']+|["']$/g, "").trim()).filter((i) => i.length >= 4 && i.length <= 120).slice(0, 3) : [];
511
753
  }
512
- function Re(t) {
513
- return t.replace(/\n*<followups>[\s\S]*?(<\/followups>|$)/gi, "").replace(/\s*\[\s*Section:[^\]]*\]?/gi, "").replace(/\s*\[\s*doc:[^\]]*\]?/gi, "").replace(/\s*\[\s*(?:document|doc|source|ref|reference)[^\]]*\]?/gi, "").replace(/\s*\[\s*(?:p\.?\s*)?\d+(?:\s*[,–-]\s*\d+)*\s*\]/gi, "").replace(/[,;]?\s*doc:\s*[0-9a-fA-F][0-9a-fA-F-]{6,}\]?/gi, "").replace(/[,;]\s*(?:\d+|doc:?\s*[0-9a-fA-F-]+)\s*\]?/gi, "").replace(/([\w%])\s*\]/g, "$1").replace(/\s+([,.;:!?])/g, "$1").replace(/[ \t]+/g, " ").replace(/\n{3,}/g, `
754
+ function Me(t) {
755
+ const n = /\s*I\s+(don'?t|do not)\s+have\s+(?:specific|enough|that|the|any)?\s*information\s+on\s+(?:this|that)[^.]*?\.(?:\s*Please\s+(?:contact|reach\s*out\s+to)\s+(?:your\s+)?(?:support|admin)[^.]*?\.)?/gi, i = /\n*<followups>[\s\S]*?(<\/followups>|$)/gi, l = t.replace(i, ""), a = l.replace(n, "").trim();
756
+ return (l.trim().length > 0 && a.length < 20 ? t : t.replace(n, "")).replace(/\n*<followups>[\s\S]*?(<\/followups>|$)/gi, "").replace(/\s*\[\s*Section:[^\]]*\]?/gi, "").replace(/\s*\[\s*doc:[^\]]*\]?/gi, "").replace(/\s*\[\s*(?:document|doc|source|ref|reference)[^\]]*\]?/gi, "").replace(/\s*\[\s*(?:p\.?\s*)?\d+(?:\s*[,–-]\s*\d+)*\s*\]/gi, "").replace(/[,;]?\s*doc:\s*[0-9a-fA-F][0-9a-fA-F-]{6,}\]?/gi, "").replace(/[,;]\s*(?:\d+|doc:?\s*[0-9a-fA-F-]+)\s*\]?/gi, "").replace(/([\w%])\s*\]/g, "$1").replace(/\s+([,.;:!?])/g, "$1").replace(/[ \t]+/g, " ").replace(/\n{3,}/g, `
514
757
 
515
758
  `).trim();
516
759
  }
517
- function Fe(t) {
518
- return t.split(/\n{2,}/).map((l, r) => {
519
- const n = l.split(`
760
+ function Pe(t) {
761
+ return t.split(/\n{2,}/).map((i, l) => {
762
+ const a = i.split(`
520
763
  `);
521
- if (n.every((i) => /^(\s*)([-*]|\d+\.)\s/.test(i)) && n.length > 0) {
522
- const i = /^\d+\./.test(n[0].trim()), a = n.map((f) => f.replace(/^\s*(?:[-*]|\d+\.)\s+/, "")), m = i ? "ol" : "ul";
523
- return /* @__PURE__ */ e.createElement(m, { key: r, className: `dgl-md-list ${i ? "dgl-md-ol" : "dgl-md-ul"}` }, a.map((f, N) => /* @__PURE__ */ e.createElement("li", { key: N }, fe(f))));
764
+ if (a.every((s) => /^(\s*)([-*]|\d+\.)\s/.test(s)) && a.length > 0) {
765
+ const s = /^\d+\./.test(a[0].trim()), r = a.map((h) => h.replace(/^\s*(?:[-*]|\d+\.)\s+/, "")), d = s ? "ol" : "ul";
766
+ return /* @__PURE__ */ e.createElement(d, { key: l, className: `dgl-md-list ${s ? "dgl-md-ol" : "dgl-md-ul"}` }, r.map((h, w) => /* @__PURE__ */ e.createElement("li", { key: w }, Ne(h))));
524
767
  }
525
- return /* @__PURE__ */ e.createElement("p", { key: r, className: "dgl-md-p" }, l.split(`
526
- `).map((i, a, m) => /* @__PURE__ */ e.createElement(e.Fragment, { key: a }, fe(i), a < m.length - 1 && /* @__PURE__ */ e.createElement("br", null))));
768
+ return /* @__PURE__ */ e.createElement("p", { key: l, className: "dgl-md-p" }, i.split(`
769
+ `).map((s, r, d) => /* @__PURE__ */ e.createElement(e.Fragment, { key: r }, Ne(s), r < d.length - 1 && /* @__PURE__ */ e.createElement("br", null))));
527
770
  });
528
771
  }
529
- function fe(t) {
530
- const s = /(`[^`]+`|\*\*[^*\n]+\*\*|\*[^*\n]+\*|\[[^\]]+\]\([^)]+\))/g;
531
- return t.split(s).map((r, n) => {
532
- if (!r) return null;
533
- if (r.startsWith("`") && r.endsWith("`"))
534
- return /* @__PURE__ */ e.createElement("code", { key: n, className: "dgl-md-code" }, r.slice(1, -1));
535
- if (r.startsWith("**") && r.endsWith("**"))
536
- return /* @__PURE__ */ e.createElement("strong", { key: n }, r.slice(2, -2));
537
- if (r.startsWith("*") && r.endsWith("*") && r.length > 2)
538
- return /* @__PURE__ */ e.createElement("em", { key: n }, r.slice(1, -1));
539
- const o = r.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
540
- return o ? /* @__PURE__ */ e.createElement("a", { key: n, href: o[2], target: "_blank", rel: "noopener noreferrer", className: "dgl-md-link" }, o[1]) : /* @__PURE__ */ e.createElement(e.Fragment, { key: n }, r);
772
+ function Ne(t) {
773
+ const n = /(`[^`]+`|\*\*[^*\n]+\*\*|\*[^*\n]+\*|\[[^\]]+\]\([^)]+\))/g;
774
+ return t.split(n).map((l, a) => {
775
+ if (!l) return null;
776
+ if (l.startsWith("`") && l.endsWith("`"))
777
+ return /* @__PURE__ */ e.createElement("code", { key: a, className: "dgl-md-code" }, l.slice(1, -1));
778
+ if (l.startsWith("**") && l.endsWith("**"))
779
+ return /* @__PURE__ */ e.createElement("strong", { key: a }, l.slice(2, -2));
780
+ if (l.startsWith("*") && l.endsWith("*") && l.length > 2)
781
+ return /* @__PURE__ */ e.createElement("em", { key: a }, l.slice(1, -1));
782
+ const o = l.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
783
+ return o ? /* @__PURE__ */ e.createElement("a", { key: a, href: o[2], target: "_blank", rel: "noopener noreferrer", className: "dgl-md-link" }, o[1]) : /* @__PURE__ */ e.createElement(e.Fragment, { key: a }, l);
541
784
  });
542
785
  }
543
- function Se() {
786
+ function Ke() {
544
787
  return /* @__PURE__ */ e.createElement("span", { className: "dgl-thinking" }, /* @__PURE__ */ e.createElement("span", { className: "dgl-thinking-dot" }), /* @__PURE__ */ e.createElement("span", { className: "dgl-thinking-dot" }), /* @__PURE__ */ e.createElement("span", { className: "dgl-thinking-dot" }));
545
788
  }
546
- function Ae() {
789
+ const A = {
790
+ open: { label: "Open", stripe: "linear-gradient(90deg,#3b82f6,#6366f1)", iconBg: "#3b82f6", pillBg: "#dbeafe", pillFg: "#1e40af" },
791
+ in_progress: { label: "In progress", stripe: "linear-gradient(90deg,#8b5cf6,#d946ef)", iconBg: "#8b5cf6", pillBg: "#ede9fe", pillFg: "#5b21b6" },
792
+ on_hold: { label: "On hold", stripe: "linear-gradient(90deg,#f59e0b,#f97316)", iconBg: "#f59e0b", pillBg: "#fef3c7", pillFg: "#92400e" },
793
+ resolved: { label: "Resolved", stripe: "linear-gradient(90deg,#10b981,#14b8a6)", iconBg: "#10b981", pillBg: "#d1fae5", pillFg: "#065f46" },
794
+ closed: { label: "Closed", stripe: "linear-gradient(90deg,#94a3b8,#64748b)", iconBg: "#64748b", pillBg: "#f1f5f9", pillFg: "#334155" },
795
+ cancelled: { label: "Cancelled", stripe: "linear-gradient(90deg,#ef4444,#f43f5e)", iconBg: "#ef4444", pillBg: "#fee2e2", pillFg: "#991b1b" }
796
+ }, we = {
797
+ low: { bg: "#f1f5f9", fg: "#475569" },
798
+ medium: { bg: "#dbeafe", fg: "#1e40af" },
799
+ high: { bg: "#fef3c7", fg: "#92400e" },
800
+ urgent: { bg: "#fee2e2", fg: "#991b1b" }
801
+ };
802
+ function xe(t) {
803
+ if (!t) return "—";
804
+ const n = new Date(t), i = Date.now() - n.getTime();
805
+ if (Number.isNaN(i)) return t;
806
+ const l = Math.floor(i / 6e4);
807
+ if (l < 1) return "just now";
808
+ if (l < 60) return `${l}m ago`;
809
+ const a = Math.floor(l / 60);
810
+ if (a < 24) return `${a}h ago`;
811
+ const o = Math.floor(a / 24);
812
+ return o < 7 ? `${o}d ago` : n.toLocaleDateString();
813
+ }
814
+ function We({
815
+ client: t,
816
+ offer: n,
817
+ defaultEmail: i,
818
+ defaultPhone: l,
819
+ onCreated: a
820
+ }) {
821
+ const [o, s] = f(i || ""), [r, d] = f(l || ""), [h, w] = f(!i), [y, k] = f("medium"), [L, _] = f(!1), [R, C] = f(null), P = async () => {
822
+ if (!o.trim()) {
823
+ C("Email is required so the team can follow up.");
824
+ return;
825
+ }
826
+ _(!0), C(null);
827
+ try {
828
+ const E = await t.raiseTicket(n.conversationId, {
829
+ consent: !0,
830
+ end_user_email: o.trim(),
831
+ end_user_phone: r.trim() || void 0,
832
+ priority: y
833
+ });
834
+ a(E);
835
+ } catch (E) {
836
+ C((E == null ? void 0 : E.message) || "Could not create ticket. Try again.");
837
+ } finally {
838
+ _(!1);
839
+ }
840
+ };
841
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-stripe", style: { background: "linear-gradient(90deg,#6366f1,#8b5cf6)" } }), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-body" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-head" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-icon", style: { background: "linear-gradient(135deg,#6366f1,#8b5cf6,#ec4899)" } }, M()), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-titles" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-eyebrow" }, "Support escalation"), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-title" }, "Need a human to look at this?"))), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-desc" }, "We'll summarise this chat and raise a ticket. Our team will follow up on the email below."), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-form-grid" }, /* @__PURE__ */ e.createElement("div", null, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-field-label" }, "Reply to"), h ? /* @__PURE__ */ e.createElement(
842
+ "input",
843
+ {
844
+ type: "email",
845
+ className: "dgl-ticket-input",
846
+ value: o,
847
+ onChange: (E) => s(E.target.value),
848
+ onBlur: () => o && w(!1),
849
+ placeholder: "you@example.com",
850
+ autoFocus: !0
851
+ }
852
+ ) : /* @__PURE__ */ e.createElement(
853
+ "button",
854
+ {
855
+ type: "button",
856
+ className: "dgl-ticket-email-link",
857
+ onClick: () => w(!0),
858
+ title: "Click to change"
859
+ },
860
+ o || "Set email",
861
+ " ",
862
+ /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-email-change" }, "(change)")
863
+ )), /* @__PURE__ */ e.createElement("div", null, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-field-label" }, "Priority"), /* @__PURE__ */ e.createElement(
864
+ "select",
865
+ {
866
+ className: "dgl-ticket-input",
867
+ value: y,
868
+ onChange: (E) => k(E.target.value)
869
+ },
870
+ /* @__PURE__ */ e.createElement("option", { value: "low" }, "Low"),
871
+ /* @__PURE__ */ e.createElement("option", { value: "medium" }, "Medium"),
872
+ /* @__PURE__ */ e.createElement("option", { value: "high" }, "High"),
873
+ /* @__PURE__ */ e.createElement("option", { value: "urgent" }, "Urgent")
874
+ ))), R && /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-error" }, R), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-footer" }, /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-hint" }, "The bot writes the title + description from this chat."), /* @__PURE__ */ e.createElement(
875
+ "button",
876
+ {
877
+ type: "button",
878
+ className: "dgl-ticket-submit",
879
+ onClick: P,
880
+ disabled: L || !o.trim()
881
+ },
882
+ L ? z() : M(),
883
+ /* @__PURE__ */ e.createElement("span", null, L ? "Submitting…" : "Submit ticket")
884
+ ))));
885
+ }
886
+ function Ge({ created: t }) {
887
+ const n = A.open;
888
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-stripe", style: { background: "linear-gradient(90deg,#10b981,#14b8a6)" } }), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-body" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-head" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-icon", style: { background: "linear-gradient(135deg,#10b981,#14b8a6)" } }, Ye()), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-titles" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-eyebrow", style: { color: "#059669" } }, "Ticket created"), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-title" }, "#", t.externalNumber || t.id.slice(0, 8))), t.externalUrl && /* @__PURE__ */ e.createElement("a", { className: "dgl-ticket-open-btn", href: t.externalUrl, target: "_blank", rel: "noopener noreferrer" }, "Open")), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-pills" }, /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill", style: { background: n.pillBg, color: n.pillFg } }, /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill-dot", style: { background: n.iconBg } }), " Open")), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-desc" }, "Support team has been notified — they'll follow up directly on your email.")));
889
+ }
890
+ function He({
891
+ existing: t,
892
+ client: n,
893
+ conversationId: i,
894
+ defaultEmail: l,
895
+ defaultPhone: a,
896
+ onNewTicketRaised: o
897
+ }) {
898
+ const s = A[t.status] || A.open, [r, d] = f(!1), [h, w] = f(l || ""), [y, k] = f("medium"), [L, _] = f(!1), [R, C] = f(null), P = async () => {
899
+ if (!h.trim()) {
900
+ C("Email is required so the team can follow up.");
901
+ return;
902
+ }
903
+ if (!i) {
904
+ C("Conversation not available yet.");
905
+ return;
906
+ }
907
+ _(!0), C(null);
908
+ try {
909
+ const E = await n.raiseTicket(i, {
910
+ consent: !0,
911
+ end_user_email: h.trim(),
912
+ end_user_phone: a || void 0,
913
+ priority: y,
914
+ force_new: !0
915
+ });
916
+ o == null || o(E);
917
+ } catch (E) {
918
+ C((E == null ? void 0 : E.message) || "Could not create ticket. Try again.");
919
+ } finally {
920
+ _(!1);
921
+ }
922
+ };
923
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-stripe", style: { background: s.stripe } }), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-body" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-head" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-icon", style: { background: s.iconBg } }, M()), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-titles" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-eyebrow" }, "We're already on it"), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-title" }, "#", t.externalNumber || t.ticketId.slice(0, 8))), t.externalUrl && /* @__PURE__ */ e.createElement("a", { className: "dgl-ticket-open-btn", href: t.externalUrl, target: "_blank", rel: "noopener noreferrer" }, "Open")), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-pills" }, /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill", style: { background: s.pillBg, color: s.pillFg } }, /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill-dot", style: { background: s.iconBg } }), " ", s.label)), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-desc" }, "A ticket has already been raised for this conversation. Our team will follow up — no need to file another."), r ? /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-diff-form" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-field-label", style: { marginTop: 4 } }, "File a separate ticket for a new issue"), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-form-grid" }, /* @__PURE__ */ e.createElement("div", null, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-field-label" }, "Reply to"), /* @__PURE__ */ e.createElement(
924
+ "input",
925
+ {
926
+ type: "email",
927
+ className: "dgl-ticket-input",
928
+ value: h,
929
+ onChange: (E) => w(E.target.value),
930
+ placeholder: "you@example.com"
931
+ }
932
+ )), /* @__PURE__ */ e.createElement("div", null, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-field-label" }, "Priority"), /* @__PURE__ */ e.createElement(
933
+ "select",
934
+ {
935
+ className: "dgl-ticket-input",
936
+ value: y,
937
+ onChange: (E) => k(E.target.value)
938
+ },
939
+ /* @__PURE__ */ e.createElement("option", { value: "low" }, "Low"),
940
+ /* @__PURE__ */ e.createElement("option", { value: "medium" }, "Medium"),
941
+ /* @__PURE__ */ e.createElement("option", { value: "high" }, "High"),
942
+ /* @__PURE__ */ e.createElement("option", { value: "urgent" }, "Urgent")
943
+ ))), R && /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-error" }, R), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-footer" }, /* @__PURE__ */ e.createElement(
944
+ "button",
945
+ {
946
+ type: "button",
947
+ className: "dgl-ticket-diff-cancel",
948
+ onClick: () => d(!1)
949
+ },
950
+ "Cancel"
951
+ ), /* @__PURE__ */ e.createElement(
952
+ "button",
953
+ {
954
+ type: "button",
955
+ className: "dgl-ticket-submit",
956
+ onClick: P,
957
+ disabled: L || !h.trim()
958
+ },
959
+ L ? z() : M(),
960
+ /* @__PURE__ */ e.createElement("span", null, L ? "Submitting…" : "Submit new ticket")
961
+ ))) : /* @__PURE__ */ e.createElement(
962
+ "button",
963
+ {
964
+ type: "button",
965
+ className: "dgl-ticket-diff-link",
966
+ onClick: () => d(!0)
967
+ },
968
+ "Different issue? Raise new ticket →"
969
+ )));
970
+ }
971
+ function Xe({
972
+ ticket: t
973
+ }) {
974
+ const n = A[t.status] || A.open, i = we[(t.priority || "medium").toLowerCase()] || we.medium;
975
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-stripe", style: { background: n.stripe } }), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-body" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-head" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-icon", style: { background: n.iconBg } }, M()), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-titles" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-eyebrow" }, "Support ticket"), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-title" }, "#", t.externalNumber || t.ticketId.slice(0, 8))), t.externalUrl && /* @__PURE__ */ e.createElement("a", { className: "dgl-ticket-open-btn", href: t.externalUrl, target: "_blank", rel: "noopener noreferrer" }, "Open")), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-pills" }, /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill", style: { background: n.pillBg, color: n.pillFg } }, /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill-dot", style: { background: n.iconBg } }), " ", n.label), /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill", style: { background: i.bg, color: i.fg } }, t.priority || "medium", " priority")), t.title && /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-card-body-title" }, t.title), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-meta-grid" }, /* @__PURE__ */ e.createElement("div", null, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-meta-label" }, "Last update"), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-meta-value" }, xe(t.lastUpdate))), /* @__PURE__ */ e.createElement("div", null, /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-meta-label" }, "Assigned to"), /* @__PURE__ */ e.createElement("div", { className: "dgl-ticket-meta-value" }, t.assignedTo || "Unassigned")))));
976
+ }
977
+ function Ve({
978
+ tickets: t,
979
+ onClose: n,
980
+ onRefresh: i
981
+ }) {
982
+ const [l, a] = f(!1);
983
+ T(() => {
984
+ const r = (d) => {
985
+ d.key === "Escape" && n();
986
+ };
987
+ return window.addEventListener("keydown", r), () => window.removeEventListener("keydown", r);
988
+ }, [n]);
989
+ const o = async () => {
990
+ a(!0);
991
+ try {
992
+ await i();
993
+ } finally {
994
+ a(!1);
995
+ }
996
+ }, s = [...t].sort((r, d) => {
997
+ const h = r.created_at ? new Date(r.created_at).getTime() : 0;
998
+ return (d.created_at ? new Date(d.created_at).getTime() : 0) - h;
999
+ });
1000
+ return /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-modal-backdrop", onClick: n }, /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-modal", onClick: (r) => r.stopPropagation() }, /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-modal-header" }, /* @__PURE__ */ e.createElement("div", null, /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-modal-title" }, "Your tickets"), /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-modal-sub" }, t.length === 0 ? "No tickets yet" : `${t.length} ticket${t.length === 1 ? "" : "s"} on this assistant`)), /* @__PURE__ */ e.createElement("div", { style: { display: "flex", gap: 4 } }, /* @__PURE__ */ e.createElement(
1001
+ "button",
1002
+ {
1003
+ type: "button",
1004
+ onClick: o,
1005
+ className: "dgl-icon-btn",
1006
+ title: "Refresh",
1007
+ "aria-label": "Refresh tickets",
1008
+ disabled: l,
1009
+ style: { color: "#475569" }
1010
+ },
1011
+ l ? z() : at()
1012
+ ), /* @__PURE__ */ e.createElement(
1013
+ "button",
1014
+ {
1015
+ type: "button",
1016
+ onClick: n,
1017
+ className: "dgl-icon-btn",
1018
+ title: "Close",
1019
+ "aria-label": "Close",
1020
+ style: { color: "#475569" }
1021
+ },
1022
+ Y()
1023
+ ))), /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-modal-list" }, s.length === 0 ? /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-empty" }, "You haven't raised any support tickets here yet. They'll show up here once you do.") : s.map((r) => {
1024
+ const d = A[r.status] || A.open;
1025
+ return /* @__PURE__ */ e.createElement("div", { key: r.id, className: "dgl-tix-row" }, /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-row-head" }, /* @__PURE__ */ e.createElement("span", { className: "dgl-tix-row-num" }, "#", r.external_ticket_number || r.id.slice(0, 8)), /* @__PURE__ */ e.createElement(
1026
+ "span",
1027
+ {
1028
+ className: "dgl-ticket-pill",
1029
+ style: { background: d.pillBg, color: d.pillFg }
1030
+ },
1031
+ /* @__PURE__ */ e.createElement("span", { className: "dgl-ticket-pill-dot", style: { background: d.iconBg } }),
1032
+ d.label
1033
+ ), r.external_url && /* @__PURE__ */ e.createElement(
1034
+ "a",
1035
+ {
1036
+ href: r.external_url,
1037
+ target: "_blank",
1038
+ rel: "noopener noreferrer",
1039
+ className: "dgl-ticket-open-btn",
1040
+ style: { marginLeft: "auto" }
1041
+ },
1042
+ "Open"
1043
+ )), r.title && /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-row-title" }, r.title), /* @__PURE__ */ e.createElement("div", { className: "dgl-tix-row-meta" }, r.priority || "medium", " priority · raised ", xe(r.created_at)));
1044
+ }))));
1045
+ }
1046
+ function M() {
1047
+ return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ e.createElement("circle", { cx: "12", cy: "12", r: "4" }), /* @__PURE__ */ e.createElement("path", { d: "M4.93 4.93l4.24 4.24M14.83 14.83l4.24 4.24M14.83 9.17l4.24-4.24M14.83 9.17l3.53-3.53M4.93 19.07l4.24-4.24" }));
1048
+ }
1049
+ function Ye() {
1050
+ return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", stroke: "white", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("path", { d: "M20 6L9 17l-5-5" }));
1051
+ }
1052
+ function ze() {
547
1053
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "currentColor" }, /* @__PURE__ */ e.createElement("path", { d: "M4 4h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H8l-4 4V6a2 2 0 0 1 2-2z" }));
548
1054
  }
549
- function Te() {
1055
+ function qe() {
550
1056
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("polyline", { points: "6 9 12 15 18 9" }));
551
1057
  }
552
- function q() {
1058
+ function Y() {
553
1059
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), /* @__PURE__ */ e.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" }));
554
1060
  }
555
- function Oe() {
1061
+ function Je() {
556
1062
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), /* @__PURE__ */ e.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" }));
557
1063
  }
558
- function Be() {
1064
+ function Qe() {
559
1065
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "currentColor" }, /* @__PURE__ */ e.createElement("path", { d: "M2 21l21-9L2 3v7l15 2-15 2z" }));
560
1066
  }
561
- function De() {
1067
+ function Ze() {
562
1068
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), /* @__PURE__ */ e.createElement("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), /* @__PURE__ */ e.createElement("polyline", { points: "21 15 16 10 5 21" }));
563
1069
  }
564
- function je() {
1070
+ function z() {
565
1071
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "16", height: "16", className: "dgl-spin", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round" }, /* @__PURE__ */ e.createElement("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }));
566
1072
  }
567
- function Ke() {
1073
+ function et() {
568
1074
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("polyline", { points: "15 3 21 3 21 9" }), /* @__PURE__ */ e.createElement("polyline", { points: "9 21 3 21 3 15" }), /* @__PURE__ */ e.createElement("line", { x1: "21", y1: "3", x2: "14", y2: "10" }), /* @__PURE__ */ e.createElement("line", { x1: "3", y1: "21", x2: "10", y2: "14" }));
569
1075
  }
570
- function Pe() {
1076
+ function tt() {
571
1077
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("polyline", { points: "4 14 10 14 10 20" }), /* @__PURE__ */ e.createElement("polyline", { points: "20 10 14 10 14 4" }), /* @__PURE__ */ e.createElement("line", { x1: "14", y1: "10", x2: "21", y2: "3" }), /* @__PURE__ */ e.createElement("line", { x1: "3", y1: "21", x2: "10", y2: "14" }));
572
1078
  }
573
- function pe() {
1079
+ function at() {
1080
+ return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ e.createElement("polyline", { points: "23 4 23 10 17 10" }), /* @__PURE__ */ e.createElement("polyline", { points: "1 20 1 14 7 14" }), /* @__PURE__ */ e.createElement("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" }));
1081
+ }
1082
+ function _e() {
574
1083
  return /* @__PURE__ */ e.createElement("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "currentColor" }, /* @__PURE__ */ e.createElement("path", { d: "M12 2l2.39 6.95L21 11l-6.61 2.05L12 20l-2.39-6.95L3 11l6.61-2.05L12 2z" }));
575
1084
  }
576
- let I = null, L = null;
577
- function We(t) {
1085
+ let B = null, O = null;
1086
+ function nt(t) {
578
1087
  if (typeof document == "undefined")
579
1088
  throw new Error("DocGenLab.init() requires a browser environment.");
580
- if (I) {
581
- I.render(ge(z, t));
1089
+ if (B) {
1090
+ B.render(Ee(le, t));
582
1091
  return;
583
1092
  }
584
- L = document.createElement("div"), L.id = "docgenlab-chat-widget-root", document.body.appendChild(L), I = ke(L), I.render(ge(z, t));
1093
+ O = document.createElement("div"), O.id = "docgenlab-chat-widget-root", document.body.appendChild(O), B = $e(O), B.render(Ee(le, t));
585
1094
  }
586
- function Me() {
587
- I && (I.unmount(), I = null), L && (L.remove(), L = null);
1095
+ function lt() {
1096
+ B && (B.unmount(), B = null), O && (O.remove(), O = null);
588
1097
  }
589
- typeof window != "undefined" && (window.DocGenLab = { init: We, destroy: Me, DocGenLabChat: z });
1098
+ typeof window != "undefined" && (window.DocGenLab = { init: nt, destroy: lt, DocGenLabChat: le });
590
1099
  export {
591
- z as DocGenLabChat,
592
- Me as destroy,
593
- We as init
1100
+ le as DocGenLabChat,
1101
+ lt as destroy,
1102
+ nt as init
594
1103
  };
595
1104
  //# sourceMappingURL=index.js.map