@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.mjs CHANGED
@@ -3,7 +3,10 @@ import { createContext, useContext } from "react";
3
3
  import { ChannlizeClient } from "@channlize/core";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  var ChannlizeContext = createContext(null);
6
- function ChannlizeProvider({ config, children }) {
6
+ function ChannlizeProvider({
7
+ config,
8
+ children
9
+ }) {
7
10
  const client = new ChannlizeClient(config);
8
11
  return /* @__PURE__ */ jsx(ChannlizeContext.Provider, { value: { client, config }, children });
9
12
  }
@@ -73,15 +76,18 @@ function useChatSession(options = {}) {
73
76
  useEffect(() => {
74
77
  sessionRef.current = session;
75
78
  }, [session]);
76
- const saveSessionToStorage = useCallback2((sessionId) => {
77
- if (persistSession && typeof window !== "undefined") {
78
- try {
79
- localStorage.setItem(storageKey, sessionId);
80
- } catch (err) {
81
- console.warn("Failed to save session to localStorage:", err);
79
+ const saveSessionToStorage = useCallback2(
80
+ (sessionId) => {
81
+ if (persistSession && typeof window !== "undefined") {
82
+ try {
83
+ localStorage.setItem(storageKey, sessionId);
84
+ } catch (err) {
85
+ console.warn("Failed to save session to localStorage:", err);
86
+ }
82
87
  }
83
- }
84
- }, [persistSession, storageKey]);
88
+ },
89
+ [persistSession, storageKey]
90
+ );
85
91
  const getSessionFromStorage = useCallback2(() => {
86
92
  if (persistSession && typeof window !== "undefined") {
87
93
  try {
@@ -101,64 +107,80 @@ function useChatSession(options = {}) {
101
107
  }
102
108
  }
103
109
  }, [persistSession, storageKey]);
104
- const connectToSSE = useCallback2((sseEndpoint) => {
105
- if (eventSourceRef.current) {
106
- eventSourceRef.current.close();
107
- }
108
- const fullUrl = sseEndpoint.startsWith("http") ? sseEndpoint : `${baseUrl}${sseEndpoint}`;
109
- const eventSource = new EventSource(fullUrl);
110
- eventSourceRef.current = eventSource;
111
- eventSource.onopen = () => {
112
- setIsConnected(true);
113
- setError(null);
114
- };
115
- eventSource.addEventListener("connected", (event) => {
116
- console.log("SSE connected:", event.data);
117
- });
118
- eventSource.addEventListener("message", (event) => {
119
- try {
120
- console.log("SSE message:", event.data);
121
- const message = JSON.parse(event.data);
122
- const chatMessage = {
123
- ...message,
124
- timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
125
- };
126
- setMessages((prev) => {
127
- const exists = prev.some((m) => m.id === chatMessage.id);
128
- return exists ? prev : [...prev, chatMessage];
129
- });
130
- options.onMessage?.(chatMessage);
131
- } catch (err) {
132
- console.warn("Failed to parse SSE message:", err, event.data);
110
+ const connectToSSE = useCallback2(
111
+ (sseEndpoint) => {
112
+ if (eventSourceRef.current) {
113
+ eventSourceRef.current.close();
133
114
  }
134
- });
135
- eventSource.onmessage = (event) => {
136
- try {
137
- const data = JSON.parse(event.data);
138
- if (data.type === "message" && data.message) {
139
- const message = {
140
- ...data.message,
141
- timestamp: data.message.timestamp ? new Date(data.message.timestamp) : /* @__PURE__ */ new Date()
115
+ const fullUrl = sseEndpoint.startsWith("http") ? sseEndpoint : `${baseUrl}${sseEndpoint}`;
116
+ console.log("[Channlize SSE] Connecting to:", fullUrl);
117
+ const eventSource = new EventSource(fullUrl);
118
+ eventSourceRef.current = eventSource;
119
+ eventSource.onopen = () => {
120
+ console.log("[Channlize SSE] Connection opened");
121
+ setIsConnected(true);
122
+ setError(null);
123
+ };
124
+ eventSource.addEventListener("connected", (event) => {
125
+ console.log("SSE connected:", event.data);
126
+ });
127
+ eventSource.addEventListener("message", (event) => {
128
+ try {
129
+ console.log("SSE message:", event.data);
130
+ const message = JSON.parse(event.data);
131
+ const chatMessage = {
132
+ ...message,
133
+ timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
142
134
  };
143
135
  setMessages((prev) => {
144
- const exists = prev.some((m) => m.id === message.id);
145
- return exists ? prev : [...prev, message];
136
+ const exists = prev.some((m) => m.id === chatMessage.id);
137
+ return exists ? prev : [...prev, chatMessage];
146
138
  });
147
- options.onMessage?.(message);
139
+ options.onMessage?.(chatMessage);
140
+ } catch (err) {
141
+ console.warn("Failed to parse SSE message:", err, event.data);
148
142
  }
149
- } catch (err) {
150
- console.warn("Failed to parse default SSE message:", err);
151
- }
152
- };
153
- eventSource.onerror = () => {
154
- setIsConnected(false);
155
- eventSource.close();
156
- eventSourceRef.current = null;
157
- const error2 = new Error("Connection lost");
158
- setError(error2);
159
- options.onError?.(error2);
160
- };
161
- }, [baseUrl, options.onError, options.onMessage]);
143
+ });
144
+ eventSource.onmessage = (event) => {
145
+ try {
146
+ const data = JSON.parse(event.data);
147
+ if (data.type === "message" && data.message) {
148
+ const message = {
149
+ ...data.message,
150
+ timestamp: data.message.timestamp ? new Date(data.message.timestamp) : /* @__PURE__ */ new Date()
151
+ };
152
+ setMessages((prev) => {
153
+ const exists = prev.some((m) => m.id === message.id);
154
+ return exists ? prev : [...prev, message];
155
+ });
156
+ options.onMessage?.(message);
157
+ }
158
+ } catch (err) {
159
+ console.warn("Failed to parse default SSE message:", err);
160
+ }
161
+ };
162
+ eventSource.onerror = (event) => {
163
+ if (eventSource.readyState === EventSource.CONNECTING) {
164
+ setIsConnected(false);
165
+ return;
166
+ }
167
+ console.error("[Channlize SSE] Connection error", {
168
+ readyState: eventSource.readyState,
169
+ url: fullUrl,
170
+ event
171
+ });
172
+ const stateMessage = eventSource.readyState === 0 ? "Failed to connect (CONNECTING)" : eventSource.readyState === 1 ? "Connection error while OPEN" : "Connection closed";
173
+ setIsConnected(false);
174
+ eventSource.close();
175
+ eventSourceRef.current = null;
176
+ const error2 = new Error(`SSE ${stateMessage}`);
177
+ error2.code = "SSE_ERROR";
178
+ setError(error2);
179
+ options.onError?.(error2);
180
+ };
181
+ },
182
+ [baseUrl, options.onError, options.onMessage]
183
+ );
162
184
  const startSession = useCallback2(async () => {
163
185
  if (isConnecting || session) return;
164
186
  setIsConnecting(true);
@@ -171,10 +193,12 @@ function useChatSession(options = {}) {
171
193
  const existingSession = await client.getChatSession(existingSessionId);
172
194
  const existingMessages = await client.getChatMessages(existingSessionId);
173
195
  setSession(existingSession);
174
- const normalizedMessages2 = existingMessages.map((msg) => ({
175
- ...msg,
176
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
177
- }));
196
+ const normalizedMessages2 = existingMessages.map(
197
+ (msg) => ({
198
+ ...msg,
199
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
200
+ })
201
+ );
178
202
  setMessages(normalizedMessages2);
179
203
  const sseEndpoint = `/v1/chat/sessions/${existingSessionId}/events`;
180
204
  connectToSSE(sseEndpoint);
@@ -189,10 +213,12 @@ function useChatSession(options = {}) {
189
213
  const response = await client.createChatSession(options.metadata);
190
214
  setSession(response.session);
191
215
  saveSessionToStorage(response.session.id);
192
- const normalizedMessages = (response.session.messages || []).map((msg) => ({
193
- ...msg,
194
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
195
- }));
216
+ const normalizedMessages = (response.session.messages || []).map(
217
+ (msg) => ({
218
+ ...msg,
219
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
220
+ })
221
+ );
196
222
  setMessages(normalizedMessages);
197
223
  if (response.sseEndpoint) {
198
224
  connectToSSE(response.sseEndpoint);
@@ -205,7 +231,18 @@ function useChatSession(options = {}) {
205
231
  } finally {
206
232
  setIsConnecting(false);
207
233
  }
208
- }, [client, connectToSSE, options.metadata, options.onError, options.sessionId, getSessionFromStorage, saveSessionToStorage, clearSessionFromStorage, isConnecting, session]);
234
+ }, [
235
+ client,
236
+ connectToSSE,
237
+ options.metadata,
238
+ options.onError,
239
+ options.sessionId,
240
+ getSessionFromStorage,
241
+ saveSessionToStorage,
242
+ clearSessionFromStorage,
243
+ isConnecting,
244
+ session
245
+ ]);
209
246
  const sendMessage = useCallback2(
210
247
  async (content, attachments) => {
211
248
  if (!sessionRef.current) {
@@ -259,12 +296,15 @@ function useChatSession(options = {}) {
259
296
  isInitializedRef.current = true;
260
297
  startSession();
261
298
  }
299
+ }, [options.autoConnect, session, isConnecting, startSession]);
300
+ useEffect(() => {
262
301
  return () => {
263
302
  if (eventSourceRef.current) {
264
303
  eventSourceRef.current.close();
304
+ eventSourceRef.current = null;
265
305
  }
266
306
  };
267
- }, [options.autoConnect, session, isConnecting, startSession]);
307
+ }, []);
268
308
  return {
269
309
  session,
270
310
  messages,
@@ -277,6 +317,17 @@ function useChatSession(options = {}) {
277
317
  };
278
318
  }
279
319
 
320
+ // src/hooks/useChannlizeAnalytics.ts
321
+ import { useCallback as useCallback3 } from "react";
322
+ function useChannlizeAnalytics() {
323
+ const { client } = useChannlize();
324
+ const track = useCallback3(
325
+ (name, options) => client.trackEvent(name, options),
326
+ [client]
327
+ );
328
+ return { track };
329
+ }
330
+
280
331
  // src/components/Form.tsx
281
332
  import { useState as useState3 } from "react";
282
333
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
@@ -317,7 +368,10 @@ function Form({
317
368
  await submit(formData);
318
369
  };
319
370
  const handleInputChange = (field, value) => {
320
- setFormData((prev) => ({ ...prev, [field]: value }));
371
+ setFormData((prev) => ({
372
+ ...prev,
373
+ [field]: value
374
+ }));
321
375
  };
322
376
  const handleCustomFieldChange = (fieldName, value) => {
323
377
  setFormData((prev) => ({
@@ -329,18 +383,17 @@ function Form({
329
383
  }));
330
384
  };
331
385
  if (isSuccess) {
332
- return /* @__PURE__ */ jsxs("div", { className: `channlize-form-success ${className}`, style: styles.success, children: [
333
- /* @__PURE__ */ jsx2("p", { children: successMessage }),
334
- /* @__PURE__ */ jsx2(
335
- "button",
336
- {
337
- type: "button",
338
- onClick: reset,
339
- style: styles.button,
340
- children: "Send Another Message"
341
- }
342
- )
343
- ] });
386
+ return /* @__PURE__ */ jsxs(
387
+ "div",
388
+ {
389
+ className: `channlize-form-success ${className}`,
390
+ style: styles.success,
391
+ children: [
392
+ /* @__PURE__ */ jsx2("p", { children: successMessage }),
393
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: reset, style: styles.button, children: "Send Another Message" })
394
+ ]
395
+ }
396
+ );
344
397
  }
345
398
  return /* @__PURE__ */ jsxs(
346
399
  "form",
@@ -445,15 +498,7 @@ function Form({
445
498
  )
446
499
  ] }),
447
500
  error && /* @__PURE__ */ jsx2("div", { className: "channlize-error", style: styles.error, children: error.message }),
448
- /* @__PURE__ */ jsx2(
449
- "button",
450
- {
451
- type: "submit",
452
- disabled: isSubmitting,
453
- style: styles.button,
454
- children: isSubmitting ? "Sending..." : submitText
455
- }
456
- )
501
+ /* @__PURE__ */ jsx2("button", { type: "submit", disabled: isSubmitting, style: styles.button, children: isSubmitting ? "Sending..." : submitText })
457
502
  ]
458
503
  }
459
504
  );
@@ -512,7 +557,10 @@ function SupportChat({
512
557
  e.preventDefault();
513
558
  if (!messageInput.trim() && attachments.length === 0) return;
514
559
  try {
515
- await sendMessage(messageInput, attachments.length > 0 ? attachments : void 0);
560
+ await sendMessage(
561
+ messageInput,
562
+ attachments.length > 0 ? attachments : void 0
563
+ );
516
564
  setMessageInput("");
517
565
  setAttachments([]);
518
566
  } catch (err) {
@@ -540,130 +588,183 @@ function SupportChat({
540
588
  }
541
589
  };
542
590
  if (!session && !isConnecting) {
543
- return /* @__PURE__ */ jsxs2("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
544
- /* @__PURE__ */ jsx4("div", { className: "channlize-chat-header", style: styles.header, children: /* @__PURE__ */ jsx4("h3", { children: title }) }),
545
- /* @__PURE__ */ jsx4("div", { className: "channlize-chat-start", children: /* @__PURE__ */ jsx4("button", { onClick: startSession, style: styles.button, children: "Start Chat" }) }),
546
- error && /* @__PURE__ */ jsx4("div", { className: "channlize-error", style: styles.error, children: error.message })
547
- ] });
548
- }
549
- return /* @__PURE__ */ jsxs2("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
550
- /* @__PURE__ */ jsxs2("div", { className: "channlize-chat-header", style: styles.header, children: [
551
- /* @__PURE__ */ jsx4("h3", { children: title }),
552
- /* @__PURE__ */ jsxs2("div", { className: "channlize-chat-status", style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
553
- isConnecting && /* @__PURE__ */ jsxs2(Fragment, { children: [
554
- /* @__PURE__ */ jsx4("span", { style: {
555
- display: "inline-block",
556
- width: "8px",
557
- height: "8px",
558
- borderRadius: "50%",
559
- backgroundColor: "#f59e0b"
560
- } }),
561
- /* @__PURE__ */ jsx4("span", { children: "Connecting..." })
562
- ] }),
563
- isConnected && /* @__PURE__ */ jsxs2(Fragment, { children: [
564
- /* @__PURE__ */ jsx4("span", { style: {
565
- display: "inline-block",
566
- width: "8px",
567
- height: "8px",
568
- borderRadius: "50%",
569
- backgroundColor: "#10b981"
570
- } }),
571
- /* @__PURE__ */ jsx4("span", { children: "Connected" })
572
- ] }),
573
- !isConnected && !isConnecting && /* @__PURE__ */ jsxs2(Fragment, { children: [
574
- /* @__PURE__ */ jsx4("span", { style: {
575
- display: "inline-block",
576
- width: "8px",
577
- height: "8px",
578
- borderRadius: "50%",
579
- backgroundColor: "#ef4444"
580
- } }),
581
- /* @__PURE__ */ jsx4("span", { children: "Disconnected" })
582
- ] })
583
- ] }),
584
- session && /* @__PURE__ */ jsx4(
585
- "button",
586
- {
587
- onClick: endSession,
588
- style: { ...styles.button, fontSize: "0.875rem" },
589
- type: "button",
590
- children: "End Chat"
591
- }
592
- )
593
- ] }),
594
- /* @__PURE__ */ jsxs2("div", { className: "channlize-messages", style: styles.messagesContainer, children: [
595
- messages.length === 0 && /* @__PURE__ */ jsx4("div", { style: { textAlign: "center", padding: "2rem", color: "#666" }, children: "No messages yet. Start the conversation!" }),
596
- messages.map((message, index) => /* @__PURE__ */ jsxs2(
597
- "div",
598
- {
599
- className: `channlize-message ${message.author === "user" ? "channlize-message-user" : "channlize-message-agent"}`,
600
- style: {
601
- ...styles.message,
602
- ...message.author === "user" ? styles.userMessage : styles.agentMessage
603
- },
604
- children: [
605
- /* @__PURE__ */ jsx4("div", { className: "channlize-message-content", children: message.content }),
606
- showTimestamps && /* @__PURE__ */ jsx4("div", { className: "channlize-message-timestamp", style: styles.timestamp, children: formatTimestamp(message.timestamp) })
607
- ]
608
- },
609
- message.id || index
610
- )),
611
- /* @__PURE__ */ jsx4("div", { ref: messagesEndRef })
612
- ] }),
613
- error && /* @__PURE__ */ jsx4("div", { className: "channlize-error", style: styles.error, children: error.message }),
614
- /* @__PURE__ */ jsxs2(
615
- "form",
591
+ return /* @__PURE__ */ jsxs2(
592
+ "div",
616
593
  {
617
- className: "channlize-chat-input-container",
618
- style: styles.inputContainer,
619
- onSubmit: handleSubmit,
594
+ className: `channlize-chat-container ${className}`,
595
+ style: styles.container,
620
596
  children: [
621
- allowAttachments && /* @__PURE__ */ jsxs2("div", { children: [
622
- /* @__PURE__ */ jsx4(
623
- "input",
624
- {
625
- type: "file",
626
- multiple: true,
627
- onChange: handleFileChange,
628
- style: { fontSize: "0.875rem" }
629
- }
630
- ),
631
- attachments.length > 0 && /* @__PURE__ */ jsxs2("div", { style: { fontSize: "0.75rem", marginTop: "0.25rem" }, children: [
632
- attachments.length,
633
- " file(s) selected"
634
- ] })
635
- ] }),
636
- /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "0.5rem" }, children: [
637
- /* @__PURE__ */ jsx4(
638
- "input",
639
- {
640
- type: "text",
641
- value: messageInput,
642
- onChange: (e) => setMessageInput(e.target.value),
643
- placeholder,
644
- disabled: !session || isConnecting,
645
- style: { ...styles.input, flex: 1 }
646
- }
647
- ),
648
- /* @__PURE__ */ jsx4(
649
- "button",
650
- {
651
- type: "submit",
652
- disabled: !session || isConnecting || !messageInput.trim() && attachments.length === 0,
653
- style: styles.button,
654
- children: sendButtonText
655
- }
656
- )
657
- ] })
597
+ /* @__PURE__ */ jsx4("div", { className: "channlize-chat-header", style: styles.header, children: /* @__PURE__ */ jsx4("h3", { children: title }) }),
598
+ /* @__PURE__ */ jsx4("div", { className: "channlize-chat-start", children: /* @__PURE__ */ jsx4("button", { onClick: startSession, style: styles.button, children: "Start Chat" }) }),
599
+ error && /* @__PURE__ */ jsx4("div", { className: "channlize-error", style: styles.error, children: error.message })
658
600
  ]
659
601
  }
660
- )
661
- ] });
602
+ );
603
+ }
604
+ return /* @__PURE__ */ jsxs2(
605
+ "div",
606
+ {
607
+ className: `channlize-chat-container ${className}`,
608
+ style: styles.container,
609
+ children: [
610
+ /* @__PURE__ */ jsxs2("div", { className: "channlize-chat-header", style: styles.header, children: [
611
+ /* @__PURE__ */ jsx4("h3", { children: title }),
612
+ /* @__PURE__ */ jsxs2(
613
+ "div",
614
+ {
615
+ className: "channlize-chat-status",
616
+ style: { display: "flex", alignItems: "center", gap: "0.5rem" },
617
+ children: [
618
+ isConnecting && /* @__PURE__ */ jsxs2(Fragment, { children: [
619
+ /* @__PURE__ */ jsx4(
620
+ "span",
621
+ {
622
+ style: {
623
+ display: "inline-block",
624
+ width: "8px",
625
+ height: "8px",
626
+ borderRadius: "50%",
627
+ backgroundColor: "#f59e0b"
628
+ }
629
+ }
630
+ ),
631
+ /* @__PURE__ */ jsx4("span", { children: "Connecting..." })
632
+ ] }),
633
+ isConnected && /* @__PURE__ */ jsxs2(Fragment, { children: [
634
+ /* @__PURE__ */ jsx4(
635
+ "span",
636
+ {
637
+ style: {
638
+ display: "inline-block",
639
+ width: "8px",
640
+ height: "8px",
641
+ borderRadius: "50%",
642
+ backgroundColor: "#10b981"
643
+ }
644
+ }
645
+ ),
646
+ /* @__PURE__ */ jsx4("span", { children: "Connected" })
647
+ ] }),
648
+ !isConnected && !isConnecting && /* @__PURE__ */ jsxs2(Fragment, { children: [
649
+ /* @__PURE__ */ jsx4(
650
+ "span",
651
+ {
652
+ style: {
653
+ display: "inline-block",
654
+ width: "8px",
655
+ height: "8px",
656
+ borderRadius: "50%",
657
+ backgroundColor: "#ef4444"
658
+ }
659
+ }
660
+ ),
661
+ /* @__PURE__ */ jsx4("span", { children: "Disconnected" })
662
+ ] })
663
+ ]
664
+ }
665
+ ),
666
+ session && /* @__PURE__ */ jsx4(
667
+ "button",
668
+ {
669
+ onClick: endSession,
670
+ style: { ...styles.button, fontSize: "0.875rem" },
671
+ type: "button",
672
+ children: "End Chat"
673
+ }
674
+ )
675
+ ] }),
676
+ /* @__PURE__ */ jsxs2("div", { className: "channlize-messages", style: styles.messagesContainer, children: [
677
+ messages.length === 0 && /* @__PURE__ */ jsx4("div", { style: { textAlign: "center", padding: "2rem", color: "#666" }, children: "No messages yet. Start the conversation!" }),
678
+ messages.map((message, index) => /* @__PURE__ */ jsxs2(
679
+ "div",
680
+ {
681
+ className: `channlize-message ${message.author === "user" ? "channlize-message-user" : "channlize-message-agent"}`,
682
+ style: {
683
+ ...styles.message,
684
+ ...message.author === "user" ? styles.userMessage : styles.agentMessage
685
+ },
686
+ children: [
687
+ /* @__PURE__ */ jsx4("div", { className: "channlize-message-content", children: message.content }),
688
+ showTimestamps && /* @__PURE__ */ jsx4(
689
+ "div",
690
+ {
691
+ className: "channlize-message-timestamp",
692
+ style: styles.timestamp,
693
+ children: formatTimestamp(message.timestamp)
694
+ }
695
+ )
696
+ ]
697
+ },
698
+ message.id || index
699
+ )),
700
+ /* @__PURE__ */ jsx4("div", { ref: messagesEndRef })
701
+ ] }),
702
+ error && /* @__PURE__ */ jsx4("div", { className: "channlize-error", style: styles.error, children: error.message }),
703
+ /* @__PURE__ */ jsxs2(
704
+ "form",
705
+ {
706
+ className: "channlize-chat-input-container",
707
+ style: styles.inputContainer,
708
+ onSubmit: handleSubmit,
709
+ children: [
710
+ allowAttachments && /* @__PURE__ */ jsxs2("div", { children: [
711
+ /* @__PURE__ */ jsx4(
712
+ "input",
713
+ {
714
+ type: "file",
715
+ multiple: true,
716
+ onChange: handleFileChange,
717
+ style: { fontSize: "0.875rem" }
718
+ }
719
+ ),
720
+ attachments.length > 0 && /* @__PURE__ */ jsxs2("div", { style: { fontSize: "0.75rem", marginTop: "0.25rem" }, children: [
721
+ attachments.length,
722
+ " file(s) selected"
723
+ ] })
724
+ ] }),
725
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "0.5rem" }, children: [
726
+ /* @__PURE__ */ jsx4(
727
+ "input",
728
+ {
729
+ type: "text",
730
+ value: messageInput,
731
+ onChange: (e) => setMessageInput(e.target.value),
732
+ placeholder,
733
+ disabled: !session || isConnecting,
734
+ style: { ...styles.input, flex: 1 }
735
+ }
736
+ ),
737
+ /* @__PURE__ */ jsx4(
738
+ "button",
739
+ {
740
+ type: "submit",
741
+ disabled: !session || isConnecting || !messageInput.trim() && attachments.length === 0,
742
+ style: styles.button,
743
+ children: sendButtonText
744
+ }
745
+ )
746
+ ] })
747
+ ]
748
+ }
749
+ )
750
+ ]
751
+ }
752
+ );
662
753
  }
663
754
 
664
755
  // src/components/ChannlizeChat.tsx
665
- import { useState as useState5, useEffect as useEffect3 } from "react";
756
+ import { useState as useState5, useSyncExternalStore } from "react";
666
757
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
758
+ var emptySubscribe = () => () => {
759
+ };
760
+ function subscribeDarkMode(onStoreChange) {
761
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
762
+ mediaQuery.addEventListener("change", onStoreChange);
763
+ return () => mediaQuery.removeEventListener("change", onStoreChange);
764
+ }
765
+ function getDarkModeSnapshot() {
766
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
767
+ }
667
768
  function ChannlizeChat({
668
769
  config,
669
770
  position = "bottom-right",
@@ -689,19 +790,16 @@ function ChannlizeChat({
689
790
  chatClassName = ""
690
791
  }) {
691
792
  const [isOpen, setIsOpen] = useState5(defaultOpen);
692
- const [isMounted, setIsMounted] = useState5(false);
693
- const [isDarkMode, setIsDarkMode] = useState5(false);
694
- useEffect3(() => {
695
- setIsMounted(true);
696
- }, []);
697
- useEffect3(() => {
698
- if (typeof window === "undefined") return;
699
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
700
- setIsDarkMode(mediaQuery.matches);
701
- const handler = (e) => setIsDarkMode(e.matches);
702
- mediaQuery.addEventListener("change", handler);
703
- return () => mediaQuery.removeEventListener("change", handler);
704
- }, []);
793
+ const isMounted = useSyncExternalStore(
794
+ emptySubscribe,
795
+ () => true,
796
+ () => false
797
+ );
798
+ const isDarkMode = useSyncExternalStore(
799
+ subscribeDarkMode,
800
+ getDarkModeSnapshot,
801
+ () => false
802
+ );
705
803
  if (!isMounted) {
706
804
  return null;
707
805
  }
@@ -818,173 +916,166 @@ function ChannlizeChat({
818
916
  )
819
917
  }
820
918
  ),
821
- /* @__PURE__ */ jsxs3(
822
- "div",
823
- {
824
- style: chatContainerStyle,
825
- className: chatClassName,
826
- children: [
827
- /* @__PURE__ */ jsx5(
828
- SupportChat,
829
- {
830
- autoConnect: isOpen,
831
- persistSession: true,
832
- title: "Support Chat",
833
- placeholder: "Type your message...",
834
- showTimestamps: true,
835
- ...chatProps,
836
- styles: {
837
- container: {
838
- width: "384px",
839
- height: "600px",
840
- maxHeight: "calc(100vh - 120px)",
841
- borderRadius: "16px",
842
- overflow: "hidden",
843
- 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)",
844
- backgroundColor: isDarkMode ? "#1f2937" : "#ffffff",
845
- display: "flex",
846
- flexDirection: "column",
847
- position: "relative",
848
- ...chatProps.styles?.container
849
- },
850
- header: {
851
- background: "linear-gradient(135deg, #3b82f6 0%, #9333ea 100%)",
852
- padding: "20px",
853
- borderRadius: "16px 16px 0 0",
854
- color: "white",
855
- display: "flex",
856
- alignItems: "center",
857
- justifyContent: "space-between",
858
- ...chatProps.styles?.header
859
- },
860
- messagesContainer: {
861
- flex: 1,
862
- overflowY: "auto",
863
- padding: "20px",
864
- backgroundColor: isDarkMode ? "#111827" : "#f9fafb",
865
- ...chatProps.styles?.messagesContainer
866
- },
867
- inputContainer: {
868
- padding: "16px",
869
- backgroundColor: isDarkMode ? "#1f2937" : "white",
870
- borderTop: `1px solid ${isDarkMode ? "#374151" : "#e5e7eb"}`,
871
- ...chatProps.styles?.inputContainer
872
- },
873
- input: {
874
- ...chatProps.styles?.input,
875
- borderRadius: "12px",
876
- padding: "12px 16px",
877
- fontSize: "14px",
878
- border: `1px solid ${isDarkMode ? "#374151" : "#d1d5db"}`,
879
- outline: "none",
880
- backgroundColor: isDarkMode ? "#374151" : "#ffffff",
881
- color: isDarkMode ? "#f9fafb" : "#111827",
882
- fontWeight: "400"
883
- },
884
- button: {
885
- backgroundColor: "#3b82f6",
886
- color: "white",
887
- borderRadius: "12px",
888
- padding: "12px 24px",
889
- fontSize: "14px",
890
- fontWeight: "500",
891
- border: "none",
892
- cursor: "pointer",
893
- transition: "background-color 0.2s",
894
- ...chatProps.styles?.button
895
- },
896
- userMessage: {
897
- backgroundColor: "#3b82f6",
898
- color: "white",
899
- padding: "10px 14px",
900
- borderRadius: "12px 12px 4px 12px",
901
- marginBottom: "8px",
902
- marginLeft: "auto",
903
- maxWidth: "80%",
904
- width: "fit-content",
905
- ...chatProps.styles?.userMessage
906
- },
907
- agentMessage: {
908
- backgroundColor: isDarkMode ? "#374151" : "white",
909
- color: isDarkMode ? "#f9fafb" : "#1f2937",
910
- padding: "10px 14px",
911
- borderRadius: "12px 12px 12px 4px",
912
- marginBottom: "8px",
913
- marginRight: "auto",
914
- maxWidth: "80%",
915
- width: "fit-content",
916
- boxShadow: isDarkMode ? "0 1px 2px 0 rgb(0 0 0 / 0.3)" : "0 1px 2px 0 rgb(0 0 0 / 0.05)",
917
- ...chatProps.styles?.agentMessage
918
- },
919
- timestamp: {
920
- fontSize: "11px",
921
- opacity: 0.7,
922
- marginTop: "4px",
923
- color: isDarkMode ? "#d1d5db" : "inherit",
924
- ...chatProps.styles?.timestamp
925
- },
926
- error: {
927
- backgroundColor: isDarkMode ? "#7f1d1d" : "#fee2e2",
928
- color: isDarkMode ? "#fca5a5" : "#991b1b",
929
- padding: "12px",
930
- margin: "8px 16px",
931
- borderRadius: "8px",
932
- fontSize: "14px",
933
- ...chatProps.styles?.error
934
- }
935
- }
919
+ /* @__PURE__ */ jsxs3("div", { style: chatContainerStyle, className: chatClassName, children: [
920
+ /* @__PURE__ */ jsx5(
921
+ SupportChat,
922
+ {
923
+ autoConnect: isOpen,
924
+ persistSession: true,
925
+ title: "Support Chat",
926
+ placeholder: "Type your message...",
927
+ showTimestamps: true,
928
+ ...chatProps,
929
+ styles: {
930
+ container: {
931
+ width: "384px",
932
+ height: "600px",
933
+ maxHeight: "calc(100vh - 120px)",
934
+ borderRadius: "16px",
935
+ overflow: "hidden",
936
+ 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)",
937
+ backgroundColor: isDarkMode ? "#1f2937" : "#ffffff",
938
+ display: "flex",
939
+ flexDirection: "column",
940
+ position: "relative",
941
+ ...chatProps.styles?.container
942
+ },
943
+ header: {
944
+ background: "linear-gradient(135deg, #3b82f6 0%, #9333ea 100%)",
945
+ padding: "20px",
946
+ borderRadius: "16px 16px 0 0",
947
+ color: "white",
948
+ display: "flex",
949
+ alignItems: "center",
950
+ justifyContent: "space-between",
951
+ ...chatProps.styles?.header
952
+ },
953
+ messagesContainer: {
954
+ flex: 1,
955
+ overflowY: "auto",
956
+ padding: "20px",
957
+ backgroundColor: isDarkMode ? "#111827" : "#f9fafb",
958
+ ...chatProps.styles?.messagesContainer
959
+ },
960
+ inputContainer: {
961
+ padding: "16px",
962
+ backgroundColor: isDarkMode ? "#1f2937" : "white",
963
+ borderTop: `1px solid ${isDarkMode ? "#374151" : "#e5e7eb"}`,
964
+ ...chatProps.styles?.inputContainer
965
+ },
966
+ input: {
967
+ ...chatProps.styles?.input,
968
+ borderRadius: "12px",
969
+ padding: "12px 16px",
970
+ fontSize: "14px",
971
+ border: `1px solid ${isDarkMode ? "#374151" : "#d1d5db"}`,
972
+ outline: "none",
973
+ backgroundColor: isDarkMode ? "#374151" : "#ffffff",
974
+ color: isDarkMode ? "#f9fafb" : "#111827",
975
+ fontWeight: "400"
976
+ },
977
+ button: {
978
+ backgroundColor: "#3b82f6",
979
+ color: "white",
980
+ borderRadius: "12px",
981
+ padding: "12px 24px",
982
+ fontSize: "14px",
983
+ fontWeight: "500",
984
+ border: "none",
985
+ cursor: "pointer",
986
+ transition: "background-color 0.2s",
987
+ ...chatProps.styles?.button
988
+ },
989
+ userMessage: {
990
+ backgroundColor: "#3b82f6",
991
+ color: "white",
992
+ padding: "10px 14px",
993
+ borderRadius: "12px 12px 4px 12px",
994
+ marginBottom: "8px",
995
+ marginLeft: "auto",
996
+ maxWidth: "80%",
997
+ width: "fit-content",
998
+ ...chatProps.styles?.userMessage
999
+ },
1000
+ agentMessage: {
1001
+ backgroundColor: isDarkMode ? "#374151" : "white",
1002
+ color: isDarkMode ? "#f9fafb" : "#1f2937",
1003
+ padding: "10px 14px",
1004
+ borderRadius: "12px 12px 12px 4px",
1005
+ marginBottom: "8px",
1006
+ marginRight: "auto",
1007
+ maxWidth: "80%",
1008
+ width: "fit-content",
1009
+ boxShadow: isDarkMode ? "0 1px 2px 0 rgb(0 0 0 / 0.3)" : "0 1px 2px 0 rgb(0 0 0 / 0.05)",
1010
+ ...chatProps.styles?.agentMessage
1011
+ },
1012
+ timestamp: {
1013
+ fontSize: "11px",
1014
+ opacity: 0.7,
1015
+ marginTop: "4px",
1016
+ color: isDarkMode ? "#d1d5db" : "inherit",
1017
+ ...chatProps.styles?.timestamp
1018
+ },
1019
+ error: {
1020
+ backgroundColor: isDarkMode ? "#7f1d1d" : "#fee2e2",
1021
+ color: isDarkMode ? "#fca5a5" : "#991b1b",
1022
+ padding: "12px",
1023
+ margin: "8px 16px",
1024
+ borderRadius: "8px",
1025
+ fontSize: "14px",
1026
+ ...chatProps.styles?.error
936
1027
  }
937
- ),
938
- /* @__PURE__ */ jsx5(
939
- "button",
1028
+ }
1029
+ }
1030
+ ),
1031
+ /* @__PURE__ */ jsx5(
1032
+ "button",
1033
+ {
1034
+ onClick: handleToggle,
1035
+ style: {
1036
+ position: "absolute",
1037
+ top: "16px",
1038
+ right: "16px",
1039
+ width: "32px",
1040
+ height: "32px",
1041
+ borderRadius: "50%",
1042
+ backgroundColor: "rgba(255, 255, 255, 0.2)",
1043
+ border: "none",
1044
+ cursor: "pointer",
1045
+ display: "flex",
1046
+ alignItems: "center",
1047
+ justifyContent: "center",
1048
+ color: "white",
1049
+ transition: "background-color 0.2s",
1050
+ zIndex: 10
1051
+ },
1052
+ onMouseEnter: (e) => {
1053
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
1054
+ },
1055
+ onMouseLeave: (e) => {
1056
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
1057
+ },
1058
+ "aria-label": "Close chat",
1059
+ children: /* @__PURE__ */ jsxs3(
1060
+ "svg",
940
1061
  {
941
- onClick: handleToggle,
942
- style: {
943
- position: "absolute",
944
- top: "16px",
945
- right: "16px",
946
- width: "32px",
947
- height: "32px",
948
- borderRadius: "50%",
949
- backgroundColor: "rgba(255, 255, 255, 0.2)",
950
- border: "none",
951
- cursor: "pointer",
952
- display: "flex",
953
- alignItems: "center",
954
- justifyContent: "center",
955
- color: "white",
956
- transition: "background-color 0.2s",
957
- zIndex: 10
958
- },
959
- onMouseEnter: (e) => {
960
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
961
- },
962
- onMouseLeave: (e) => {
963
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
964
- },
965
- "aria-label": "Close chat",
966
- children: /* @__PURE__ */ jsxs3(
967
- "svg",
968
- {
969
- width: "16",
970
- height: "16",
971
- viewBox: "0 0 24 24",
972
- fill: "none",
973
- stroke: "currentColor",
974
- strokeWidth: "2",
975
- strokeLinecap: "round",
976
- strokeLinejoin: "round",
977
- children: [
978
- /* @__PURE__ */ jsx5("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
979
- /* @__PURE__ */ jsx5("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
980
- ]
981
- }
982
- )
1062
+ width: "16",
1063
+ height: "16",
1064
+ viewBox: "0 0 24 24",
1065
+ fill: "none",
1066
+ stroke: "currentColor",
1067
+ strokeWidth: "2",
1068
+ strokeLinecap: "round",
1069
+ strokeLinejoin: "round",
1070
+ children: [
1071
+ /* @__PURE__ */ jsx5("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1072
+ /* @__PURE__ */ jsx5("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1073
+ ]
983
1074
  }
984
1075
  )
985
- ]
986
- }
987
- )
1076
+ }
1077
+ )
1078
+ ] })
988
1079
  ] });
989
1080
  }
990
1081
  export {
@@ -993,6 +1084,7 @@ export {
993
1084
  ContactForm,
994
1085
  SupportChat,
995
1086
  useChannlize,
1087
+ useChannlizeAnalytics,
996
1088
  useChatSession,
997
1089
  useContactForm
998
1090
  };