@channlize/react 0.1.0 → 0.1.1

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
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  ContactForm: () => ContactForm,
26
26
  SupportChat: () => SupportChat,
27
27
  useChannlize: () => useChannlize,
28
+ useChannlizeAnalytics: () => useChannlizeAnalytics,
28
29
  useChatSession: () => useChatSession,
29
30
  useContactForm: () => useContactForm
30
31
  });
@@ -35,7 +36,10 @@ var import_react = require("react");
35
36
  var import_core = require("@channlize/core");
36
37
  var import_jsx_runtime = require("react/jsx-runtime");
37
38
  var ChannlizeContext = (0, import_react.createContext)(null);
38
- function ChannlizeProvider({ config, children }) {
39
+ function ChannlizeProvider({
40
+ config,
41
+ children
42
+ }) {
39
43
  const client = new import_core.ChannlizeClient(config);
40
44
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChannlizeContext.Provider, { value: { client, config }, children });
41
45
  }
@@ -105,15 +109,18 @@ function useChatSession(options = {}) {
105
109
  (0, import_react3.useEffect)(() => {
106
110
  sessionRef.current = session;
107
111
  }, [session]);
108
- const saveSessionToStorage = (0, import_react3.useCallback)((sessionId) => {
109
- if (persistSession && typeof window !== "undefined") {
110
- try {
111
- localStorage.setItem(storageKey, sessionId);
112
- } catch (err) {
113
- console.warn("Failed to save session to localStorage:", err);
112
+ const saveSessionToStorage = (0, import_react3.useCallback)(
113
+ (sessionId) => {
114
+ if (persistSession && typeof window !== "undefined") {
115
+ try {
116
+ localStorage.setItem(storageKey, sessionId);
117
+ } catch (err) {
118
+ console.warn("Failed to save session to localStorage:", err);
119
+ }
114
120
  }
115
- }
116
- }, [persistSession, storageKey]);
121
+ },
122
+ [persistSession, storageKey]
123
+ );
117
124
  const getSessionFromStorage = (0, import_react3.useCallback)(() => {
118
125
  if (persistSession && typeof window !== "undefined") {
119
126
  try {
@@ -133,64 +140,80 @@ function useChatSession(options = {}) {
133
140
  }
134
141
  }
135
142
  }, [persistSession, storageKey]);
136
- const connectToSSE = (0, import_react3.useCallback)((sseEndpoint) => {
137
- if (eventSourceRef.current) {
138
- eventSourceRef.current.close();
139
- }
140
- const fullUrl = sseEndpoint.startsWith("http") ? sseEndpoint : `${baseUrl}${sseEndpoint}`;
141
- const eventSource = new EventSource(fullUrl);
142
- eventSourceRef.current = eventSource;
143
- eventSource.onopen = () => {
144
- setIsConnected(true);
145
- setError(null);
146
- };
147
- eventSource.addEventListener("connected", (event) => {
148
- console.log("SSE connected:", event.data);
149
- });
150
- eventSource.addEventListener("message", (event) => {
151
- try {
152
- console.log("SSE message:", event.data);
153
- const message = JSON.parse(event.data);
154
- const chatMessage = {
155
- ...message,
156
- timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
157
- };
158
- setMessages((prev) => {
159
- const exists = prev.some((m) => m.id === chatMessage.id);
160
- return exists ? prev : [...prev, chatMessage];
161
- });
162
- options.onMessage?.(chatMessage);
163
- } catch (err) {
164
- console.warn("Failed to parse SSE message:", err, event.data);
143
+ const connectToSSE = (0, import_react3.useCallback)(
144
+ (sseEndpoint) => {
145
+ if (eventSourceRef.current) {
146
+ eventSourceRef.current.close();
165
147
  }
166
- });
167
- eventSource.onmessage = (event) => {
168
- try {
169
- const data = JSON.parse(event.data);
170
- if (data.type === "message" && data.message) {
171
- const message = {
172
- ...data.message,
173
- timestamp: data.message.timestamp ? new Date(data.message.timestamp) : /* @__PURE__ */ new Date()
148
+ const fullUrl = sseEndpoint.startsWith("http") ? sseEndpoint : `${baseUrl}${sseEndpoint}`;
149
+ console.log("[Channlize SSE] Connecting to:", fullUrl);
150
+ const eventSource = new EventSource(fullUrl);
151
+ eventSourceRef.current = eventSource;
152
+ eventSource.onopen = () => {
153
+ console.log("[Channlize SSE] Connection opened");
154
+ setIsConnected(true);
155
+ setError(null);
156
+ };
157
+ eventSource.addEventListener("connected", (event) => {
158
+ console.log("SSE connected:", event.data);
159
+ });
160
+ eventSource.addEventListener("message", (event) => {
161
+ try {
162
+ console.log("SSE message:", event.data);
163
+ const message = JSON.parse(event.data);
164
+ const chatMessage = {
165
+ ...message,
166
+ timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
174
167
  };
175
168
  setMessages((prev) => {
176
- const exists = prev.some((m) => m.id === message.id);
177
- return exists ? prev : [...prev, message];
169
+ const exists = prev.some((m) => m.id === chatMessage.id);
170
+ return exists ? prev : [...prev, chatMessage];
178
171
  });
179
- options.onMessage?.(message);
172
+ options.onMessage?.(chatMessage);
173
+ } catch (err) {
174
+ console.warn("Failed to parse SSE message:", err, event.data);
180
175
  }
181
- } catch (err) {
182
- console.warn("Failed to parse default SSE message:", err);
183
- }
184
- };
185
- eventSource.onerror = () => {
186
- setIsConnected(false);
187
- eventSource.close();
188
- eventSourceRef.current = null;
189
- const error2 = new Error("Connection lost");
190
- setError(error2);
191
- options.onError?.(error2);
192
- };
193
- }, [baseUrl, options.onError, options.onMessage]);
176
+ });
177
+ eventSource.onmessage = (event) => {
178
+ try {
179
+ const data = JSON.parse(event.data);
180
+ if (data.type === "message" && data.message) {
181
+ const message = {
182
+ ...data.message,
183
+ timestamp: data.message.timestamp ? new Date(data.message.timestamp) : /* @__PURE__ */ new Date()
184
+ };
185
+ setMessages((prev) => {
186
+ const exists = prev.some((m) => m.id === message.id);
187
+ return exists ? prev : [...prev, message];
188
+ });
189
+ options.onMessage?.(message);
190
+ }
191
+ } catch (err) {
192
+ console.warn("Failed to parse default SSE message:", err);
193
+ }
194
+ };
195
+ eventSource.onerror = (event) => {
196
+ if (eventSource.readyState === EventSource.CONNECTING) {
197
+ setIsConnected(false);
198
+ return;
199
+ }
200
+ console.error("[Channlize SSE] Connection error", {
201
+ readyState: eventSource.readyState,
202
+ url: fullUrl,
203
+ event
204
+ });
205
+ const stateMessage = eventSource.readyState === 0 ? "Failed to connect (CONNECTING)" : eventSource.readyState === 1 ? "Connection error while OPEN" : "Connection closed";
206
+ setIsConnected(false);
207
+ eventSource.close();
208
+ eventSourceRef.current = null;
209
+ const error2 = new Error(`SSE ${stateMessage}`);
210
+ error2.code = "SSE_ERROR";
211
+ setError(error2);
212
+ options.onError?.(error2);
213
+ };
214
+ },
215
+ [baseUrl, options.onError, options.onMessage]
216
+ );
194
217
  const startSession = (0, import_react3.useCallback)(async () => {
195
218
  if (isConnecting || session) return;
196
219
  setIsConnecting(true);
@@ -203,10 +226,12 @@ function useChatSession(options = {}) {
203
226
  const existingSession = await client.getChatSession(existingSessionId);
204
227
  const existingMessages = await client.getChatMessages(existingSessionId);
205
228
  setSession(existingSession);
206
- const normalizedMessages2 = existingMessages.map((msg) => ({
207
- ...msg,
208
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
209
- }));
229
+ const normalizedMessages2 = existingMessages.map(
230
+ (msg) => ({
231
+ ...msg,
232
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
233
+ })
234
+ );
210
235
  setMessages(normalizedMessages2);
211
236
  const sseEndpoint = `/v1/chat/sessions/${existingSessionId}/events`;
212
237
  connectToSSE(sseEndpoint);
@@ -221,10 +246,12 @@ function useChatSession(options = {}) {
221
246
  const response = await client.createChatSession(options.metadata);
222
247
  setSession(response.session);
223
248
  saveSessionToStorage(response.session.id);
224
- const normalizedMessages = (response.session.messages || []).map((msg) => ({
225
- ...msg,
226
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
227
- }));
249
+ const normalizedMessages = (response.session.messages || []).map(
250
+ (msg) => ({
251
+ ...msg,
252
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
253
+ })
254
+ );
228
255
  setMessages(normalizedMessages);
229
256
  if (response.sseEndpoint) {
230
257
  connectToSSE(response.sseEndpoint);
@@ -237,7 +264,18 @@ function useChatSession(options = {}) {
237
264
  } finally {
238
265
  setIsConnecting(false);
239
266
  }
240
- }, [client, connectToSSE, options.metadata, options.onError, options.sessionId, getSessionFromStorage, saveSessionToStorage, clearSessionFromStorage, isConnecting, session]);
267
+ }, [
268
+ client,
269
+ connectToSSE,
270
+ options.metadata,
271
+ options.onError,
272
+ options.sessionId,
273
+ getSessionFromStorage,
274
+ saveSessionToStorage,
275
+ clearSessionFromStorage,
276
+ isConnecting,
277
+ session
278
+ ]);
241
279
  const sendMessage = (0, import_react3.useCallback)(
242
280
  async (content, attachments) => {
243
281
  if (!sessionRef.current) {
@@ -291,12 +329,15 @@ function useChatSession(options = {}) {
291
329
  isInitializedRef.current = true;
292
330
  startSession();
293
331
  }
332
+ }, [options.autoConnect, session, isConnecting, startSession]);
333
+ (0, import_react3.useEffect)(() => {
294
334
  return () => {
295
335
  if (eventSourceRef.current) {
296
336
  eventSourceRef.current.close();
337
+ eventSourceRef.current = null;
297
338
  }
298
339
  };
299
- }, [options.autoConnect, session, isConnecting, startSession]);
340
+ }, []);
300
341
  return {
301
342
  session,
302
343
  messages,
@@ -309,8 +350,19 @@ function useChatSession(options = {}) {
309
350
  };
310
351
  }
311
352
 
312
- // src/components/Form.tsx
353
+ // src/hooks/useChannlizeAnalytics.ts
313
354
  var import_react4 = require("react");
355
+ function useChannlizeAnalytics() {
356
+ const { client } = useChannlize();
357
+ const track = (0, import_react4.useCallback)(
358
+ (name, options) => client.trackEvent(name, options),
359
+ [client]
360
+ );
361
+ return { track };
362
+ }
363
+
364
+ // src/components/Form.tsx
365
+ var import_react5 = require("react");
314
366
  var import_jsx_runtime2 = require("react/jsx-runtime");
315
367
  function Form({
316
368
  customFields = [],
@@ -321,7 +373,7 @@ function Form({
321
373
  submitText = "Send Message",
322
374
  successMessage = "Thank you! Your message has been sent."
323
375
  }) {
324
- const [formData, setFormData] = (0, import_react4.useState)({
376
+ const [formData, setFormData] = (0, import_react5.useState)({
325
377
  name: "",
326
378
  email: "",
327
379
  subject: "",
@@ -349,7 +401,10 @@ function Form({
349
401
  await submit(formData);
350
402
  };
351
403
  const handleInputChange = (field, value) => {
352
- setFormData((prev) => ({ ...prev, [field]: value }));
404
+ setFormData((prev) => ({
405
+ ...prev,
406
+ [field]: value
407
+ }));
353
408
  };
354
409
  const handleCustomFieldChange = (fieldName, value) => {
355
410
  setFormData((prev) => ({
@@ -361,18 +416,17 @@ function Form({
361
416
  }));
362
417
  };
363
418
  if (isSuccess) {
364
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `channlize-form-success ${className}`, style: styles.success, children: [
365
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: successMessage }),
366
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
367
- "button",
368
- {
369
- type: "button",
370
- onClick: reset,
371
- style: styles.button,
372
- children: "Send Another Message"
373
- }
374
- )
375
- ] });
419
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
420
+ "div",
421
+ {
422
+ className: `channlize-form-success ${className}`,
423
+ style: styles.success,
424
+ children: [
425
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: successMessage }),
426
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: reset, style: styles.button, children: "Send Another Message" })
427
+ ]
428
+ }
429
+ );
376
430
  }
377
431
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
378
432
  "form",
@@ -477,15 +531,7 @@ function Form({
477
531
  )
478
532
  ] }),
479
533
  error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message }),
480
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
481
- "button",
482
- {
483
- type: "submit",
484
- disabled: isSubmitting,
485
- style: styles.button,
486
- children: isSubmitting ? "Sending..." : submitText
487
- }
488
- )
534
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "submit", disabled: isSubmitting, style: styles.button, children: isSubmitting ? "Sending..." : submitText })
489
535
  ]
490
536
  }
491
537
  );
@@ -498,7 +544,7 @@ function ContactForm(props) {
498
544
  }
499
545
 
500
546
  // src/components/SupportChat.tsx
501
- var import_react5 = require("react");
547
+ var import_react6 = require("react");
502
548
  var import_jsx_runtime4 = require("react/jsx-runtime");
503
549
  function SupportChat({
504
550
  autoConnect = true,
@@ -516,9 +562,9 @@ function SupportChat({
516
562
  showTimestamps = true,
517
563
  allowAttachments = false
518
564
  }) {
519
- const [messageInput, setMessageInput] = (0, import_react5.useState)("");
520
- const [attachments, setAttachments] = (0, import_react5.useState)([]);
521
- const messagesEndRef = (0, import_react5.useRef)(null);
565
+ const [messageInput, setMessageInput] = (0, import_react6.useState)("");
566
+ const [attachments, setAttachments] = (0, import_react6.useState)([]);
567
+ const messagesEndRef = (0, import_react6.useRef)(null);
522
568
  const {
523
569
  session,
524
570
  messages,
@@ -537,14 +583,17 @@ function SupportChat({
537
583
  persistSession,
538
584
  storageKey
539
585
  });
540
- (0, import_react5.useEffect)(() => {
586
+ (0, import_react6.useEffect)(() => {
541
587
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
542
588
  }, [messages]);
543
589
  const handleSubmit = async (e) => {
544
590
  e.preventDefault();
545
591
  if (!messageInput.trim() && attachments.length === 0) return;
546
592
  try {
547
- await sendMessage(messageInput, attachments.length > 0 ? attachments : void 0);
593
+ await sendMessage(
594
+ messageInput,
595
+ attachments.length > 0 ? attachments : void 0
596
+ );
548
597
  setMessageInput("");
549
598
  setAttachments([]);
550
599
  } catch (err) {
@@ -572,130 +621,183 @@ function SupportChat({
572
621
  }
573
622
  };
574
623
  if (!session && !isConnecting) {
575
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
576
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-chat-header", style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: title }) }),
577
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-chat-start", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { onClick: startSession, style: styles.button, children: "Start Chat" }) }),
578
- error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message })
579
- ] });
580
- }
581
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
582
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-chat-header", style: styles.header, children: [
583
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: title }),
584
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-chat-status", style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
585
- isConnecting && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
586
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
587
- display: "inline-block",
588
- width: "8px",
589
- height: "8px",
590
- borderRadius: "50%",
591
- backgroundColor: "#f59e0b"
592
- } }),
593
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Connecting..." })
594
- ] }),
595
- isConnected && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
596
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
597
- display: "inline-block",
598
- width: "8px",
599
- height: "8px",
600
- borderRadius: "50%",
601
- backgroundColor: "#10b981"
602
- } }),
603
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Connected" })
604
- ] }),
605
- !isConnected && !isConnecting && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
606
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
607
- display: "inline-block",
608
- width: "8px",
609
- height: "8px",
610
- borderRadius: "50%",
611
- backgroundColor: "#ef4444"
612
- } }),
613
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Disconnected" })
614
- ] })
615
- ] }),
616
- session && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
617
- "button",
618
- {
619
- onClick: endSession,
620
- style: { ...styles.button, fontSize: "0.875rem" },
621
- type: "button",
622
- children: "End Chat"
623
- }
624
- )
625
- ] }),
626
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-messages", style: styles.messagesContainer, children: [
627
- messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { textAlign: "center", padding: "2rem", color: "#666" }, children: "No messages yet. Start the conversation!" }),
628
- messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
629
- "div",
630
- {
631
- className: `channlize-message ${message.author === "user" ? "channlize-message-user" : "channlize-message-agent"}`,
632
- style: {
633
- ...styles.message,
634
- ...message.author === "user" ? styles.userMessage : styles.agentMessage
635
- },
636
- children: [
637
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-message-content", children: message.content }),
638
- showTimestamps && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-message-timestamp", style: styles.timestamp, children: formatTimestamp(message.timestamp) })
639
- ]
640
- },
641
- message.id || index
642
- )),
643
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: messagesEndRef })
644
- ] }),
645
- error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message }),
646
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
647
- "form",
624
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
625
+ "div",
648
626
  {
649
- className: "channlize-chat-input-container",
650
- style: styles.inputContainer,
651
- onSubmit: handleSubmit,
627
+ className: `channlize-chat-container ${className}`,
628
+ style: styles.container,
652
629
  children: [
653
- allowAttachments && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
654
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
655
- "input",
656
- {
657
- type: "file",
658
- multiple: true,
659
- onChange: handleFileChange,
660
- style: { fontSize: "0.875rem" }
661
- }
662
- ),
663
- attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: "0.75rem", marginTop: "0.25rem" }, children: [
664
- attachments.length,
665
- " file(s) selected"
666
- ] })
667
- ] }),
668
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "0.5rem" }, children: [
669
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
670
- "input",
671
- {
672
- type: "text",
673
- value: messageInput,
674
- onChange: (e) => setMessageInput(e.target.value),
675
- placeholder,
676
- disabled: !session || isConnecting,
677
- style: { ...styles.input, flex: 1 }
678
- }
679
- ),
680
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
681
- "button",
682
- {
683
- type: "submit",
684
- disabled: !session || isConnecting || !messageInput.trim() && attachments.length === 0,
685
- style: styles.button,
686
- children: sendButtonText
687
- }
688
- )
689
- ] })
630
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-chat-header", style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: title }) }),
631
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-chat-start", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { onClick: startSession, style: styles.button, children: "Start Chat" }) }),
632
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message })
690
633
  ]
691
634
  }
692
- )
693
- ] });
635
+ );
636
+ }
637
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
638
+ "div",
639
+ {
640
+ className: `channlize-chat-container ${className}`,
641
+ style: styles.container,
642
+ children: [
643
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-chat-header", style: styles.header, children: [
644
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: title }),
645
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
646
+ "div",
647
+ {
648
+ className: "channlize-chat-status",
649
+ style: { display: "flex", alignItems: "center", gap: "0.5rem" },
650
+ children: [
651
+ isConnecting && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
652
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
653
+ "span",
654
+ {
655
+ style: {
656
+ display: "inline-block",
657
+ width: "8px",
658
+ height: "8px",
659
+ borderRadius: "50%",
660
+ backgroundColor: "#f59e0b"
661
+ }
662
+ }
663
+ ),
664
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Connecting..." })
665
+ ] }),
666
+ isConnected && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
667
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
668
+ "span",
669
+ {
670
+ style: {
671
+ display: "inline-block",
672
+ width: "8px",
673
+ height: "8px",
674
+ borderRadius: "50%",
675
+ backgroundColor: "#10b981"
676
+ }
677
+ }
678
+ ),
679
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Connected" })
680
+ ] }),
681
+ !isConnected && !isConnecting && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
682
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
683
+ "span",
684
+ {
685
+ style: {
686
+ display: "inline-block",
687
+ width: "8px",
688
+ height: "8px",
689
+ borderRadius: "50%",
690
+ backgroundColor: "#ef4444"
691
+ }
692
+ }
693
+ ),
694
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Disconnected" })
695
+ ] })
696
+ ]
697
+ }
698
+ ),
699
+ session && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
700
+ "button",
701
+ {
702
+ onClick: endSession,
703
+ style: { ...styles.button, fontSize: "0.875rem" },
704
+ type: "button",
705
+ children: "End Chat"
706
+ }
707
+ )
708
+ ] }),
709
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-messages", style: styles.messagesContainer, children: [
710
+ messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { textAlign: "center", padding: "2rem", color: "#666" }, children: "No messages yet. Start the conversation!" }),
711
+ messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
712
+ "div",
713
+ {
714
+ className: `channlize-message ${message.author === "user" ? "channlize-message-user" : "channlize-message-agent"}`,
715
+ style: {
716
+ ...styles.message,
717
+ ...message.author === "user" ? styles.userMessage : styles.agentMessage
718
+ },
719
+ children: [
720
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-message-content", children: message.content }),
721
+ showTimestamps && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
722
+ "div",
723
+ {
724
+ className: "channlize-message-timestamp",
725
+ style: styles.timestamp,
726
+ children: formatTimestamp(message.timestamp)
727
+ }
728
+ )
729
+ ]
730
+ },
731
+ message.id || index
732
+ )),
733
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: messagesEndRef })
734
+ ] }),
735
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message }),
736
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
737
+ "form",
738
+ {
739
+ className: "channlize-chat-input-container",
740
+ style: styles.inputContainer,
741
+ onSubmit: handleSubmit,
742
+ children: [
743
+ allowAttachments && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
744
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
745
+ "input",
746
+ {
747
+ type: "file",
748
+ multiple: true,
749
+ onChange: handleFileChange,
750
+ style: { fontSize: "0.875rem" }
751
+ }
752
+ ),
753
+ attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: "0.75rem", marginTop: "0.25rem" }, children: [
754
+ attachments.length,
755
+ " file(s) selected"
756
+ ] })
757
+ ] }),
758
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "0.5rem" }, children: [
759
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
760
+ "input",
761
+ {
762
+ type: "text",
763
+ value: messageInput,
764
+ onChange: (e) => setMessageInput(e.target.value),
765
+ placeholder,
766
+ disabled: !session || isConnecting,
767
+ style: { ...styles.input, flex: 1 }
768
+ }
769
+ ),
770
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
771
+ "button",
772
+ {
773
+ type: "submit",
774
+ disabled: !session || isConnecting || !messageInput.trim() && attachments.length === 0,
775
+ style: styles.button,
776
+ children: sendButtonText
777
+ }
778
+ )
779
+ ] })
780
+ ]
781
+ }
782
+ )
783
+ ]
784
+ }
785
+ );
694
786
  }
695
787
 
696
788
  // src/components/ChannlizeChat.tsx
697
- var import_react6 = require("react");
789
+ var import_react7 = require("react");
698
790
  var import_jsx_runtime5 = require("react/jsx-runtime");
791
+ var emptySubscribe = () => () => {
792
+ };
793
+ function subscribeDarkMode(onStoreChange) {
794
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
795
+ mediaQuery.addEventListener("change", onStoreChange);
796
+ return () => mediaQuery.removeEventListener("change", onStoreChange);
797
+ }
798
+ function getDarkModeSnapshot() {
799
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
800
+ }
699
801
  function ChannlizeChat({
700
802
  config,
701
803
  position = "bottom-right",
@@ -720,20 +822,17 @@ function ChannlizeChat({
720
822
  buttonClassName = "",
721
823
  chatClassName = ""
722
824
  }) {
723
- const [isOpen, setIsOpen] = (0, import_react6.useState)(defaultOpen);
724
- const [isMounted, setIsMounted] = (0, import_react6.useState)(false);
725
- const [isDarkMode, setIsDarkMode] = (0, import_react6.useState)(false);
726
- (0, import_react6.useEffect)(() => {
727
- setIsMounted(true);
728
- }, []);
729
- (0, import_react6.useEffect)(() => {
730
- if (typeof window === "undefined") return;
731
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
732
- setIsDarkMode(mediaQuery.matches);
733
- const handler = (e) => setIsDarkMode(e.matches);
734
- mediaQuery.addEventListener("change", handler);
735
- return () => mediaQuery.removeEventListener("change", handler);
736
- }, []);
825
+ const [isOpen, setIsOpen] = (0, import_react7.useState)(defaultOpen);
826
+ const isMounted = (0, import_react7.useSyncExternalStore)(
827
+ emptySubscribe,
828
+ () => true,
829
+ () => false
830
+ );
831
+ const isDarkMode = (0, import_react7.useSyncExternalStore)(
832
+ subscribeDarkMode,
833
+ getDarkModeSnapshot,
834
+ () => false
835
+ );
737
836
  if (!isMounted) {
738
837
  return null;
739
838
  }
@@ -850,173 +949,166 @@ function ChannlizeChat({
850
949
  )
851
950
  }
852
951
  ),
853
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
854
- "div",
855
- {
856
- style: chatContainerStyle,
857
- className: chatClassName,
858
- children: [
859
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
860
- SupportChat,
861
- {
862
- autoConnect: isOpen,
863
- persistSession: true,
864
- title: "Support Chat",
865
- placeholder: "Type your message...",
866
- showTimestamps: true,
867
- ...chatProps,
868
- styles: {
869
- container: {
870
- width: "384px",
871
- height: "600px",
872
- maxHeight: "calc(100vh - 120px)",
873
- borderRadius: "16px",
874
- overflow: "hidden",
875
- boxShadow: isDarkMode ? "0 20px 25px -5px rgb(0 0 0 / 0.4), 0 8px 10px -6px rgb(0 0 0 / 0.5)" : "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
876
- backgroundColor: isDarkMode ? "#1f2937" : "#ffffff",
877
- display: "flex",
878
- flexDirection: "column",
879
- position: "relative",
880
- ...chatProps.styles?.container
881
- },
882
- header: {
883
- background: "linear-gradient(135deg, #3b82f6 0%, #9333ea 100%)",
884
- padding: "20px",
885
- borderRadius: "16px 16px 0 0",
886
- color: "white",
887
- display: "flex",
888
- alignItems: "center",
889
- justifyContent: "space-between",
890
- ...chatProps.styles?.header
891
- },
892
- messagesContainer: {
893
- flex: 1,
894
- overflowY: "auto",
895
- padding: "20px",
896
- backgroundColor: isDarkMode ? "#111827" : "#f9fafb",
897
- ...chatProps.styles?.messagesContainer
898
- },
899
- inputContainer: {
900
- padding: "16px",
901
- backgroundColor: isDarkMode ? "#1f2937" : "white",
902
- borderTop: `1px solid ${isDarkMode ? "#374151" : "#e5e7eb"}`,
903
- ...chatProps.styles?.inputContainer
904
- },
905
- input: {
906
- ...chatProps.styles?.input,
907
- borderRadius: "12px",
908
- padding: "12px 16px",
909
- fontSize: "14px",
910
- border: `1px solid ${isDarkMode ? "#374151" : "#d1d5db"}`,
911
- outline: "none",
912
- backgroundColor: isDarkMode ? "#374151" : "#ffffff",
913
- color: isDarkMode ? "#f9fafb" : "#111827",
914
- fontWeight: "400"
915
- },
916
- button: {
917
- backgroundColor: "#3b82f6",
918
- color: "white",
919
- borderRadius: "12px",
920
- padding: "12px 24px",
921
- fontSize: "14px",
922
- fontWeight: "500",
923
- border: "none",
924
- cursor: "pointer",
925
- transition: "background-color 0.2s",
926
- ...chatProps.styles?.button
927
- },
928
- userMessage: {
929
- backgroundColor: "#3b82f6",
930
- color: "white",
931
- padding: "10px 14px",
932
- borderRadius: "12px 12px 4px 12px",
933
- marginBottom: "8px",
934
- marginLeft: "auto",
935
- maxWidth: "80%",
936
- width: "fit-content",
937
- ...chatProps.styles?.userMessage
938
- },
939
- agentMessage: {
940
- backgroundColor: isDarkMode ? "#374151" : "white",
941
- color: isDarkMode ? "#f9fafb" : "#1f2937",
942
- padding: "10px 14px",
943
- borderRadius: "12px 12px 12px 4px",
944
- marginBottom: "8px",
945
- marginRight: "auto",
946
- maxWidth: "80%",
947
- width: "fit-content",
948
- boxShadow: isDarkMode ? "0 1px 2px 0 rgb(0 0 0 / 0.3)" : "0 1px 2px 0 rgb(0 0 0 / 0.05)",
949
- ...chatProps.styles?.agentMessage
950
- },
951
- timestamp: {
952
- fontSize: "11px",
953
- opacity: 0.7,
954
- marginTop: "4px",
955
- color: isDarkMode ? "#d1d5db" : "inherit",
956
- ...chatProps.styles?.timestamp
957
- },
958
- error: {
959
- backgroundColor: isDarkMode ? "#7f1d1d" : "#fee2e2",
960
- color: isDarkMode ? "#fca5a5" : "#991b1b",
961
- padding: "12px",
962
- margin: "8px 16px",
963
- borderRadius: "8px",
964
- fontSize: "14px",
965
- ...chatProps.styles?.error
966
- }
967
- }
952
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: chatContainerStyle, className: chatClassName, children: [
953
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
954
+ SupportChat,
955
+ {
956
+ autoConnect: isOpen,
957
+ persistSession: true,
958
+ title: "Support Chat",
959
+ placeholder: "Type your message...",
960
+ showTimestamps: true,
961
+ ...chatProps,
962
+ styles: {
963
+ container: {
964
+ width: "384px",
965
+ height: "600px",
966
+ maxHeight: "calc(100vh - 120px)",
967
+ borderRadius: "16px",
968
+ overflow: "hidden",
969
+ boxShadow: isDarkMode ? "0 20px 25px -5px rgb(0 0 0 / 0.4), 0 8px 10px -6px rgb(0 0 0 / 0.5)" : "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
970
+ backgroundColor: isDarkMode ? "#1f2937" : "#ffffff",
971
+ display: "flex",
972
+ flexDirection: "column",
973
+ position: "relative",
974
+ ...chatProps.styles?.container
975
+ },
976
+ header: {
977
+ background: "linear-gradient(135deg, #3b82f6 0%, #9333ea 100%)",
978
+ padding: "20px",
979
+ borderRadius: "16px 16px 0 0",
980
+ color: "white",
981
+ display: "flex",
982
+ alignItems: "center",
983
+ justifyContent: "space-between",
984
+ ...chatProps.styles?.header
985
+ },
986
+ messagesContainer: {
987
+ flex: 1,
988
+ overflowY: "auto",
989
+ padding: "20px",
990
+ backgroundColor: isDarkMode ? "#111827" : "#f9fafb",
991
+ ...chatProps.styles?.messagesContainer
992
+ },
993
+ inputContainer: {
994
+ padding: "16px",
995
+ backgroundColor: isDarkMode ? "#1f2937" : "white",
996
+ borderTop: `1px solid ${isDarkMode ? "#374151" : "#e5e7eb"}`,
997
+ ...chatProps.styles?.inputContainer
998
+ },
999
+ input: {
1000
+ ...chatProps.styles?.input,
1001
+ borderRadius: "12px",
1002
+ padding: "12px 16px",
1003
+ fontSize: "14px",
1004
+ border: `1px solid ${isDarkMode ? "#374151" : "#d1d5db"}`,
1005
+ outline: "none",
1006
+ backgroundColor: isDarkMode ? "#374151" : "#ffffff",
1007
+ color: isDarkMode ? "#f9fafb" : "#111827",
1008
+ fontWeight: "400"
1009
+ },
1010
+ button: {
1011
+ backgroundColor: "#3b82f6",
1012
+ color: "white",
1013
+ borderRadius: "12px",
1014
+ padding: "12px 24px",
1015
+ fontSize: "14px",
1016
+ fontWeight: "500",
1017
+ border: "none",
1018
+ cursor: "pointer",
1019
+ transition: "background-color 0.2s",
1020
+ ...chatProps.styles?.button
1021
+ },
1022
+ userMessage: {
1023
+ backgroundColor: "#3b82f6",
1024
+ color: "white",
1025
+ padding: "10px 14px",
1026
+ borderRadius: "12px 12px 4px 12px",
1027
+ marginBottom: "8px",
1028
+ marginLeft: "auto",
1029
+ maxWidth: "80%",
1030
+ width: "fit-content",
1031
+ ...chatProps.styles?.userMessage
1032
+ },
1033
+ agentMessage: {
1034
+ backgroundColor: isDarkMode ? "#374151" : "white",
1035
+ color: isDarkMode ? "#f9fafb" : "#1f2937",
1036
+ padding: "10px 14px",
1037
+ borderRadius: "12px 12px 12px 4px",
1038
+ marginBottom: "8px",
1039
+ marginRight: "auto",
1040
+ maxWidth: "80%",
1041
+ width: "fit-content",
1042
+ boxShadow: isDarkMode ? "0 1px 2px 0 rgb(0 0 0 / 0.3)" : "0 1px 2px 0 rgb(0 0 0 / 0.05)",
1043
+ ...chatProps.styles?.agentMessage
1044
+ },
1045
+ timestamp: {
1046
+ fontSize: "11px",
1047
+ opacity: 0.7,
1048
+ marginTop: "4px",
1049
+ color: isDarkMode ? "#d1d5db" : "inherit",
1050
+ ...chatProps.styles?.timestamp
1051
+ },
1052
+ error: {
1053
+ backgroundColor: isDarkMode ? "#7f1d1d" : "#fee2e2",
1054
+ color: isDarkMode ? "#fca5a5" : "#991b1b",
1055
+ padding: "12px",
1056
+ margin: "8px 16px",
1057
+ borderRadius: "8px",
1058
+ fontSize: "14px",
1059
+ ...chatProps.styles?.error
968
1060
  }
969
- ),
970
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
971
- "button",
1061
+ }
1062
+ }
1063
+ ),
1064
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1065
+ "button",
1066
+ {
1067
+ onClick: handleToggle,
1068
+ style: {
1069
+ position: "absolute",
1070
+ top: "16px",
1071
+ right: "16px",
1072
+ width: "32px",
1073
+ height: "32px",
1074
+ borderRadius: "50%",
1075
+ backgroundColor: "rgba(255, 255, 255, 0.2)",
1076
+ border: "none",
1077
+ cursor: "pointer",
1078
+ display: "flex",
1079
+ alignItems: "center",
1080
+ justifyContent: "center",
1081
+ color: "white",
1082
+ transition: "background-color 0.2s",
1083
+ zIndex: 10
1084
+ },
1085
+ onMouseEnter: (e) => {
1086
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
1087
+ },
1088
+ onMouseLeave: (e) => {
1089
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
1090
+ },
1091
+ "aria-label": "Close chat",
1092
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1093
+ "svg",
972
1094
  {
973
- onClick: handleToggle,
974
- style: {
975
- position: "absolute",
976
- top: "16px",
977
- right: "16px",
978
- width: "32px",
979
- height: "32px",
980
- borderRadius: "50%",
981
- backgroundColor: "rgba(255, 255, 255, 0.2)",
982
- border: "none",
983
- cursor: "pointer",
984
- display: "flex",
985
- alignItems: "center",
986
- justifyContent: "center",
987
- color: "white",
988
- transition: "background-color 0.2s",
989
- zIndex: 10
990
- },
991
- onMouseEnter: (e) => {
992
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
993
- },
994
- onMouseLeave: (e) => {
995
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
996
- },
997
- "aria-label": "Close chat",
998
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
999
- "svg",
1000
- {
1001
- width: "16",
1002
- height: "16",
1003
- viewBox: "0 0 24 24",
1004
- fill: "none",
1005
- stroke: "currentColor",
1006
- strokeWidth: "2",
1007
- strokeLinecap: "round",
1008
- strokeLinejoin: "round",
1009
- children: [
1010
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1011
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1012
- ]
1013
- }
1014
- )
1095
+ width: "16",
1096
+ height: "16",
1097
+ viewBox: "0 0 24 24",
1098
+ fill: "none",
1099
+ stroke: "currentColor",
1100
+ strokeWidth: "2",
1101
+ strokeLinecap: "round",
1102
+ strokeLinejoin: "round",
1103
+ children: [
1104
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1105
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1106
+ ]
1015
1107
  }
1016
1108
  )
1017
- ]
1018
- }
1019
- )
1109
+ }
1110
+ )
1111
+ ] })
1020
1112
  ] });
1021
1113
  }
1022
1114
  // Annotate the CommonJS export names for ESM import in node:
@@ -1026,6 +1118,7 @@ function ChannlizeChat({
1026
1118
  ContactForm,
1027
1119
  SupportChat,
1028
1120
  useChannlize,
1121
+ useChannlizeAnalytics,
1029
1122
  useChatSession,
1030
1123
  useContactForm
1031
1124
  });