@channlize/react 0.1.0-alpha.2 → 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,73 +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
- console.log("[Channlize SSE] Connecting to:", fullUrl);
142
- const eventSource = new EventSource(fullUrl);
143
- eventSourceRef.current = eventSource;
144
- eventSource.onopen = () => {
145
- console.log("[Channlize SSE] Connection opened");
146
- setIsConnected(true);
147
- setError(null);
148
- };
149
- eventSource.addEventListener("connected", (event) => {
150
- console.log("SSE connected:", event.data);
151
- });
152
- eventSource.addEventListener("message", (event) => {
153
- try {
154
- console.log("SSE message:", event.data);
155
- const message = JSON.parse(event.data);
156
- const chatMessage = {
157
- ...message,
158
- timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
159
- };
160
- setMessages((prev) => {
161
- const exists = prev.some((m) => m.id === chatMessage.id);
162
- return exists ? prev : [...prev, chatMessage];
163
- });
164
- options.onMessage?.(chatMessage);
165
- } catch (err) {
166
- 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();
167
147
  }
168
- });
169
- eventSource.onmessage = (event) => {
170
- try {
171
- const data = JSON.parse(event.data);
172
- if (data.type === "message" && data.message) {
173
- const message = {
174
- ...data.message,
175
- 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()
176
167
  };
177
168
  setMessages((prev) => {
178
- const exists = prev.some((m) => m.id === message.id);
179
- return exists ? prev : [...prev, message];
169
+ const exists = prev.some((m) => m.id === chatMessage.id);
170
+ return exists ? prev : [...prev, chatMessage];
180
171
  });
181
- options.onMessage?.(message);
172
+ options.onMessage?.(chatMessage);
173
+ } catch (err) {
174
+ console.warn("Failed to parse SSE message:", err, event.data);
182
175
  }
183
- } catch (err) {
184
- console.warn("Failed to parse default SSE message:", err);
185
- }
186
- };
187
- eventSource.onerror = (event) => {
188
- console.error("[Channlize SSE] Connection error", {
189
- readyState: eventSource.readyState,
190
- url: fullUrl,
191
- event
192
176
  });
193
- const stateMessage = eventSource.readyState === 0 ? "Failed to connect (CONNECTING)" : eventSource.readyState === 1 ? "Connection error while OPEN" : "Connection closed";
194
- setIsConnected(false);
195
- eventSource.close();
196
- eventSourceRef.current = null;
197
- const error2 = new Error(`SSE ${stateMessage}`);
198
- error2.code = "SSE_ERROR";
199
- setError(error2);
200
- options.onError?.(error2);
201
- };
202
- }, [baseUrl, options.onError, options.onMessage]);
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
+ );
203
217
  const startSession = (0, import_react3.useCallback)(async () => {
204
218
  if (isConnecting || session) return;
205
219
  setIsConnecting(true);
@@ -212,10 +226,12 @@ function useChatSession(options = {}) {
212
226
  const existingSession = await client.getChatSession(existingSessionId);
213
227
  const existingMessages = await client.getChatMessages(existingSessionId);
214
228
  setSession(existingSession);
215
- const normalizedMessages2 = existingMessages.map((msg) => ({
216
- ...msg,
217
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
218
- }));
229
+ const normalizedMessages2 = existingMessages.map(
230
+ (msg) => ({
231
+ ...msg,
232
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
233
+ })
234
+ );
219
235
  setMessages(normalizedMessages2);
220
236
  const sseEndpoint = `/v1/chat/sessions/${existingSessionId}/events`;
221
237
  connectToSSE(sseEndpoint);
@@ -230,10 +246,12 @@ function useChatSession(options = {}) {
230
246
  const response = await client.createChatSession(options.metadata);
231
247
  setSession(response.session);
232
248
  saveSessionToStorage(response.session.id);
233
- const normalizedMessages = (response.session.messages || []).map((msg) => ({
234
- ...msg,
235
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
236
- }));
249
+ const normalizedMessages = (response.session.messages || []).map(
250
+ (msg) => ({
251
+ ...msg,
252
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
253
+ })
254
+ );
237
255
  setMessages(normalizedMessages);
238
256
  if (response.sseEndpoint) {
239
257
  connectToSSE(response.sseEndpoint);
@@ -246,7 +264,18 @@ function useChatSession(options = {}) {
246
264
  } finally {
247
265
  setIsConnecting(false);
248
266
  }
249
- }, [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
+ ]);
250
279
  const sendMessage = (0, import_react3.useCallback)(
251
280
  async (content, attachments) => {
252
281
  if (!sessionRef.current) {
@@ -300,12 +329,15 @@ function useChatSession(options = {}) {
300
329
  isInitializedRef.current = true;
301
330
  startSession();
302
331
  }
332
+ }, [options.autoConnect, session, isConnecting, startSession]);
333
+ (0, import_react3.useEffect)(() => {
303
334
  return () => {
304
335
  if (eventSourceRef.current) {
305
336
  eventSourceRef.current.close();
337
+ eventSourceRef.current = null;
306
338
  }
307
339
  };
308
- }, [options.autoConnect, session, isConnecting, startSession]);
340
+ }, []);
309
341
  return {
310
342
  session,
311
343
  messages,
@@ -318,8 +350,19 @@ function useChatSession(options = {}) {
318
350
  };
319
351
  }
320
352
 
321
- // src/components/Form.tsx
353
+ // src/hooks/useChannlizeAnalytics.ts
322
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");
323
366
  var import_jsx_runtime2 = require("react/jsx-runtime");
324
367
  function Form({
325
368
  customFields = [],
@@ -330,7 +373,7 @@ function Form({
330
373
  submitText = "Send Message",
331
374
  successMessage = "Thank you! Your message has been sent."
332
375
  }) {
333
- const [formData, setFormData] = (0, import_react4.useState)({
376
+ const [formData, setFormData] = (0, import_react5.useState)({
334
377
  name: "",
335
378
  email: "",
336
379
  subject: "",
@@ -358,7 +401,10 @@ function Form({
358
401
  await submit(formData);
359
402
  };
360
403
  const handleInputChange = (field, value) => {
361
- setFormData((prev) => ({ ...prev, [field]: value }));
404
+ setFormData((prev) => ({
405
+ ...prev,
406
+ [field]: value
407
+ }));
362
408
  };
363
409
  const handleCustomFieldChange = (fieldName, value) => {
364
410
  setFormData((prev) => ({
@@ -370,18 +416,17 @@ function Form({
370
416
  }));
371
417
  };
372
418
  if (isSuccess) {
373
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `channlize-form-success ${className}`, style: styles.success, children: [
374
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: successMessage }),
375
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
376
- "button",
377
- {
378
- type: "button",
379
- onClick: reset,
380
- style: styles.button,
381
- children: "Send Another Message"
382
- }
383
- )
384
- ] });
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
+ );
385
430
  }
386
431
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
387
432
  "form",
@@ -486,15 +531,7 @@ function Form({
486
531
  )
487
532
  ] }),
488
533
  error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message }),
489
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
490
- "button",
491
- {
492
- type: "submit",
493
- disabled: isSubmitting,
494
- style: styles.button,
495
- children: isSubmitting ? "Sending..." : submitText
496
- }
497
- )
534
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "submit", disabled: isSubmitting, style: styles.button, children: isSubmitting ? "Sending..." : submitText })
498
535
  ]
499
536
  }
500
537
  );
@@ -507,7 +544,7 @@ function ContactForm(props) {
507
544
  }
508
545
 
509
546
  // src/components/SupportChat.tsx
510
- var import_react5 = require("react");
547
+ var import_react6 = require("react");
511
548
  var import_jsx_runtime4 = require("react/jsx-runtime");
512
549
  function SupportChat({
513
550
  autoConnect = true,
@@ -525,9 +562,9 @@ function SupportChat({
525
562
  showTimestamps = true,
526
563
  allowAttachments = false
527
564
  }) {
528
- const [messageInput, setMessageInput] = (0, import_react5.useState)("");
529
- const [attachments, setAttachments] = (0, import_react5.useState)([]);
530
- 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);
531
568
  const {
532
569
  session,
533
570
  messages,
@@ -546,14 +583,17 @@ function SupportChat({
546
583
  persistSession,
547
584
  storageKey
548
585
  });
549
- (0, import_react5.useEffect)(() => {
586
+ (0, import_react6.useEffect)(() => {
550
587
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
551
588
  }, [messages]);
552
589
  const handleSubmit = async (e) => {
553
590
  e.preventDefault();
554
591
  if (!messageInput.trim() && attachments.length === 0) return;
555
592
  try {
556
- await sendMessage(messageInput, attachments.length > 0 ? attachments : void 0);
593
+ await sendMessage(
594
+ messageInput,
595
+ attachments.length > 0 ? attachments : void 0
596
+ );
557
597
  setMessageInput("");
558
598
  setAttachments([]);
559
599
  } catch (err) {
@@ -581,130 +621,183 @@ function SupportChat({
581
621
  }
582
622
  };
583
623
  if (!session && !isConnecting) {
584
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
585
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-chat-header", style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: title }) }),
586
- /* @__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" }) }),
587
- error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message })
588
- ] });
589
- }
590
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
591
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-chat-header", style: styles.header, children: [
592
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { children: title }),
593
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-chat-status", style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
594
- isConnecting && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
595
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
596
- display: "inline-block",
597
- width: "8px",
598
- height: "8px",
599
- borderRadius: "50%",
600
- backgroundColor: "#f59e0b"
601
- } }),
602
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Connecting..." })
603
- ] }),
604
- isConnected && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
605
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
606
- display: "inline-block",
607
- width: "8px",
608
- height: "8px",
609
- borderRadius: "50%",
610
- backgroundColor: "#10b981"
611
- } }),
612
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Connected" })
613
- ] }),
614
- !isConnected && !isConnecting && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
615
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
616
- display: "inline-block",
617
- width: "8px",
618
- height: "8px",
619
- borderRadius: "50%",
620
- backgroundColor: "#ef4444"
621
- } }),
622
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Disconnected" })
623
- ] })
624
- ] }),
625
- session && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
626
- "button",
627
- {
628
- onClick: endSession,
629
- style: { ...styles.button, fontSize: "0.875rem" },
630
- type: "button",
631
- children: "End Chat"
632
- }
633
- )
634
- ] }),
635
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "channlize-messages", style: styles.messagesContainer, children: [
636
- messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { textAlign: "center", padding: "2rem", color: "#666" }, children: "No messages yet. Start the conversation!" }),
637
- messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
638
- "div",
639
- {
640
- className: `channlize-message ${message.author === "user" ? "channlize-message-user" : "channlize-message-agent"}`,
641
- style: {
642
- ...styles.message,
643
- ...message.author === "user" ? styles.userMessage : styles.agentMessage
644
- },
645
- children: [
646
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-message-content", children: message.content }),
647
- showTimestamps && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-message-timestamp", style: styles.timestamp, children: formatTimestamp(message.timestamp) })
648
- ]
649
- },
650
- message.id || index
651
- )),
652
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: messagesEndRef })
653
- ] }),
654
- error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "channlize-error", style: styles.error, children: error.message }),
655
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
656
- "form",
624
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
625
+ "div",
657
626
  {
658
- className: "channlize-chat-input-container",
659
- style: styles.inputContainer,
660
- onSubmit: handleSubmit,
627
+ className: `channlize-chat-container ${className}`,
628
+ style: styles.container,
661
629
  children: [
662
- allowAttachments && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
663
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
664
- "input",
665
- {
666
- type: "file",
667
- multiple: true,
668
- onChange: handleFileChange,
669
- style: { fontSize: "0.875rem" }
670
- }
671
- ),
672
- attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: "0.75rem", marginTop: "0.25rem" }, children: [
673
- attachments.length,
674
- " file(s) selected"
675
- ] })
676
- ] }),
677
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "0.5rem" }, children: [
678
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
679
- "input",
680
- {
681
- type: "text",
682
- value: messageInput,
683
- onChange: (e) => setMessageInput(e.target.value),
684
- placeholder,
685
- disabled: !session || isConnecting,
686
- style: { ...styles.input, flex: 1 }
687
- }
688
- ),
689
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
690
- "button",
691
- {
692
- type: "submit",
693
- disabled: !session || isConnecting || !messageInput.trim() && attachments.length === 0,
694
- style: styles.button,
695
- children: sendButtonText
696
- }
697
- )
698
- ] })
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 })
699
633
  ]
700
634
  }
701
- )
702
- ] });
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
+ );
703
786
  }
704
787
 
705
788
  // src/components/ChannlizeChat.tsx
706
- var import_react6 = require("react");
789
+ var import_react7 = require("react");
707
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
+ }
708
801
  function ChannlizeChat({
709
802
  config,
710
803
  position = "bottom-right",
@@ -729,20 +822,17 @@ function ChannlizeChat({
729
822
  buttonClassName = "",
730
823
  chatClassName = ""
731
824
  }) {
732
- const [isOpen, setIsOpen] = (0, import_react6.useState)(defaultOpen);
733
- const [isMounted, setIsMounted] = (0, import_react6.useState)(false);
734
- const [isDarkMode, setIsDarkMode] = (0, import_react6.useState)(false);
735
- (0, import_react6.useEffect)(() => {
736
- setIsMounted(true);
737
- }, []);
738
- (0, import_react6.useEffect)(() => {
739
- if (typeof window === "undefined") return;
740
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
741
- setIsDarkMode(mediaQuery.matches);
742
- const handler = (e) => setIsDarkMode(e.matches);
743
- mediaQuery.addEventListener("change", handler);
744
- return () => mediaQuery.removeEventListener("change", handler);
745
- }, []);
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
+ );
746
836
  if (!isMounted) {
747
837
  return null;
748
838
  }
@@ -859,173 +949,166 @@ function ChannlizeChat({
859
949
  )
860
950
  }
861
951
  ),
862
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
863
- "div",
864
- {
865
- style: chatContainerStyle,
866
- className: chatClassName,
867
- children: [
868
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
869
- SupportChat,
870
- {
871
- autoConnect: isOpen,
872
- persistSession: true,
873
- title: "Support Chat",
874
- placeholder: "Type your message...",
875
- showTimestamps: true,
876
- ...chatProps,
877
- styles: {
878
- container: {
879
- width: "384px",
880
- height: "600px",
881
- maxHeight: "calc(100vh - 120px)",
882
- borderRadius: "16px",
883
- overflow: "hidden",
884
- 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)",
885
- backgroundColor: isDarkMode ? "#1f2937" : "#ffffff",
886
- display: "flex",
887
- flexDirection: "column",
888
- position: "relative",
889
- ...chatProps.styles?.container
890
- },
891
- header: {
892
- background: "linear-gradient(135deg, #3b82f6 0%, #9333ea 100%)",
893
- padding: "20px",
894
- borderRadius: "16px 16px 0 0",
895
- color: "white",
896
- display: "flex",
897
- alignItems: "center",
898
- justifyContent: "space-between",
899
- ...chatProps.styles?.header
900
- },
901
- messagesContainer: {
902
- flex: 1,
903
- overflowY: "auto",
904
- padding: "20px",
905
- backgroundColor: isDarkMode ? "#111827" : "#f9fafb",
906
- ...chatProps.styles?.messagesContainer
907
- },
908
- inputContainer: {
909
- padding: "16px",
910
- backgroundColor: isDarkMode ? "#1f2937" : "white",
911
- borderTop: `1px solid ${isDarkMode ? "#374151" : "#e5e7eb"}`,
912
- ...chatProps.styles?.inputContainer
913
- },
914
- input: {
915
- ...chatProps.styles?.input,
916
- borderRadius: "12px",
917
- padding: "12px 16px",
918
- fontSize: "14px",
919
- border: `1px solid ${isDarkMode ? "#374151" : "#d1d5db"}`,
920
- outline: "none",
921
- backgroundColor: isDarkMode ? "#374151" : "#ffffff",
922
- color: isDarkMode ? "#f9fafb" : "#111827",
923
- fontWeight: "400"
924
- },
925
- button: {
926
- backgroundColor: "#3b82f6",
927
- color: "white",
928
- borderRadius: "12px",
929
- padding: "12px 24px",
930
- fontSize: "14px",
931
- fontWeight: "500",
932
- border: "none",
933
- cursor: "pointer",
934
- transition: "background-color 0.2s",
935
- ...chatProps.styles?.button
936
- },
937
- userMessage: {
938
- backgroundColor: "#3b82f6",
939
- color: "white",
940
- padding: "10px 14px",
941
- borderRadius: "12px 12px 4px 12px",
942
- marginBottom: "8px",
943
- marginLeft: "auto",
944
- maxWidth: "80%",
945
- width: "fit-content",
946
- ...chatProps.styles?.userMessage
947
- },
948
- agentMessage: {
949
- backgroundColor: isDarkMode ? "#374151" : "white",
950
- color: isDarkMode ? "#f9fafb" : "#1f2937",
951
- padding: "10px 14px",
952
- borderRadius: "12px 12px 12px 4px",
953
- marginBottom: "8px",
954
- marginRight: "auto",
955
- maxWidth: "80%",
956
- width: "fit-content",
957
- boxShadow: isDarkMode ? "0 1px 2px 0 rgb(0 0 0 / 0.3)" : "0 1px 2px 0 rgb(0 0 0 / 0.05)",
958
- ...chatProps.styles?.agentMessage
959
- },
960
- timestamp: {
961
- fontSize: "11px",
962
- opacity: 0.7,
963
- marginTop: "4px",
964
- color: isDarkMode ? "#d1d5db" : "inherit",
965
- ...chatProps.styles?.timestamp
966
- },
967
- error: {
968
- backgroundColor: isDarkMode ? "#7f1d1d" : "#fee2e2",
969
- color: isDarkMode ? "#fca5a5" : "#991b1b",
970
- padding: "12px",
971
- margin: "8px 16px",
972
- borderRadius: "8px",
973
- fontSize: "14px",
974
- ...chatProps.styles?.error
975
- }
976
- }
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
977
1060
  }
978
- ),
979
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
980
- "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",
981
1094
  {
982
- onClick: handleToggle,
983
- style: {
984
- position: "absolute",
985
- top: "16px",
986
- right: "16px",
987
- width: "32px",
988
- height: "32px",
989
- borderRadius: "50%",
990
- backgroundColor: "rgba(255, 255, 255, 0.2)",
991
- border: "none",
992
- cursor: "pointer",
993
- display: "flex",
994
- alignItems: "center",
995
- justifyContent: "center",
996
- color: "white",
997
- transition: "background-color 0.2s",
998
- zIndex: 10
999
- },
1000
- onMouseEnter: (e) => {
1001
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
1002
- },
1003
- onMouseLeave: (e) => {
1004
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
1005
- },
1006
- "aria-label": "Close chat",
1007
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1008
- "svg",
1009
- {
1010
- width: "16",
1011
- height: "16",
1012
- viewBox: "0 0 24 24",
1013
- fill: "none",
1014
- stroke: "currentColor",
1015
- strokeWidth: "2",
1016
- strokeLinecap: "round",
1017
- strokeLinejoin: "round",
1018
- children: [
1019
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1020
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1021
- ]
1022
- }
1023
- )
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
+ ]
1024
1107
  }
1025
1108
  )
1026
- ]
1027
- }
1028
- )
1109
+ }
1110
+ )
1111
+ ] })
1029
1112
  ] });
1030
1113
  }
1031
1114
  // Annotate the CommonJS export names for ESM import in node:
@@ -1035,6 +1118,7 @@ function ChannlizeChat({
1035
1118
  ContactForm,
1036
1119
  SupportChat,
1037
1120
  useChannlize,
1121
+ useChannlizeAnalytics,
1038
1122
  useChatSession,
1039
1123
  useContactForm
1040
1124
  });