@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.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,73 +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
- console.log("[Channlize SSE] Connecting to:", fullUrl);
110
- const eventSource = new EventSource(fullUrl);
111
- eventSourceRef.current = eventSource;
112
- eventSource.onopen = () => {
113
- console.log("[Channlize SSE] Connection opened");
114
- setIsConnected(true);
115
- setError(null);
116
- };
117
- eventSource.addEventListener("connected", (event) => {
118
- console.log("SSE connected:", event.data);
119
- });
120
- eventSource.addEventListener("message", (event) => {
121
- try {
122
- console.log("SSE message:", event.data);
123
- const message = JSON.parse(event.data);
124
- const chatMessage = {
125
- ...message,
126
- timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
127
- };
128
- setMessages((prev) => {
129
- const exists = prev.some((m) => m.id === chatMessage.id);
130
- return exists ? prev : [...prev, chatMessage];
131
- });
132
- options.onMessage?.(chatMessage);
133
- } catch (err) {
134
- console.warn("Failed to parse SSE message:", err, event.data);
110
+ const connectToSSE = useCallback2(
111
+ (sseEndpoint) => {
112
+ if (eventSourceRef.current) {
113
+ eventSourceRef.current.close();
135
114
  }
136
- });
137
- eventSource.onmessage = (event) => {
138
- try {
139
- const data = JSON.parse(event.data);
140
- if (data.type === "message" && data.message) {
141
- const message = {
142
- ...data.message,
143
- 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()
144
134
  };
145
135
  setMessages((prev) => {
146
- const exists = prev.some((m) => m.id === message.id);
147
- return exists ? prev : [...prev, message];
136
+ const exists = prev.some((m) => m.id === chatMessage.id);
137
+ return exists ? prev : [...prev, chatMessage];
148
138
  });
149
- options.onMessage?.(message);
139
+ options.onMessage?.(chatMessage);
140
+ } catch (err) {
141
+ console.warn("Failed to parse SSE message:", err, event.data);
150
142
  }
151
- } catch (err) {
152
- console.warn("Failed to parse default SSE message:", err);
153
- }
154
- };
155
- eventSource.onerror = (event) => {
156
- console.error("[Channlize SSE] Connection error", {
157
- readyState: eventSource.readyState,
158
- url: fullUrl,
159
- event
160
143
  });
161
- const stateMessage = eventSource.readyState === 0 ? "Failed to connect (CONNECTING)" : eventSource.readyState === 1 ? "Connection error while OPEN" : "Connection closed";
162
- setIsConnected(false);
163
- eventSource.close();
164
- eventSourceRef.current = null;
165
- const error2 = new Error(`SSE ${stateMessage}`);
166
- error2.code = "SSE_ERROR";
167
- setError(error2);
168
- options.onError?.(error2);
169
- };
170
- }, [baseUrl, options.onError, options.onMessage]);
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
+ );
171
184
  const startSession = useCallback2(async () => {
172
185
  if (isConnecting || session) return;
173
186
  setIsConnecting(true);
@@ -180,10 +193,12 @@ function useChatSession(options = {}) {
180
193
  const existingSession = await client.getChatSession(existingSessionId);
181
194
  const existingMessages = await client.getChatMessages(existingSessionId);
182
195
  setSession(existingSession);
183
- const normalizedMessages2 = existingMessages.map((msg) => ({
184
- ...msg,
185
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
186
- }));
196
+ const normalizedMessages2 = existingMessages.map(
197
+ (msg) => ({
198
+ ...msg,
199
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
200
+ })
201
+ );
187
202
  setMessages(normalizedMessages2);
188
203
  const sseEndpoint = `/v1/chat/sessions/${existingSessionId}/events`;
189
204
  connectToSSE(sseEndpoint);
@@ -198,10 +213,12 @@ function useChatSession(options = {}) {
198
213
  const response = await client.createChatSession(options.metadata);
199
214
  setSession(response.session);
200
215
  saveSessionToStorage(response.session.id);
201
- const normalizedMessages = (response.session.messages || []).map((msg) => ({
202
- ...msg,
203
- timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
204
- }));
216
+ const normalizedMessages = (response.session.messages || []).map(
217
+ (msg) => ({
218
+ ...msg,
219
+ timestamp: msg.timestamp ? new Date(msg.timestamp) : /* @__PURE__ */ new Date()
220
+ })
221
+ );
205
222
  setMessages(normalizedMessages);
206
223
  if (response.sseEndpoint) {
207
224
  connectToSSE(response.sseEndpoint);
@@ -214,7 +231,18 @@ function useChatSession(options = {}) {
214
231
  } finally {
215
232
  setIsConnecting(false);
216
233
  }
217
- }, [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
+ ]);
218
246
  const sendMessage = useCallback2(
219
247
  async (content, attachments) => {
220
248
  if (!sessionRef.current) {
@@ -268,12 +296,15 @@ function useChatSession(options = {}) {
268
296
  isInitializedRef.current = true;
269
297
  startSession();
270
298
  }
299
+ }, [options.autoConnect, session, isConnecting, startSession]);
300
+ useEffect(() => {
271
301
  return () => {
272
302
  if (eventSourceRef.current) {
273
303
  eventSourceRef.current.close();
304
+ eventSourceRef.current = null;
274
305
  }
275
306
  };
276
- }, [options.autoConnect, session, isConnecting, startSession]);
307
+ }, []);
277
308
  return {
278
309
  session,
279
310
  messages,
@@ -286,6 +317,17 @@ function useChatSession(options = {}) {
286
317
  };
287
318
  }
288
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
+
289
331
  // src/components/Form.tsx
290
332
  import { useState as useState3 } from "react";
291
333
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
@@ -326,7 +368,10 @@ function Form({
326
368
  await submit(formData);
327
369
  };
328
370
  const handleInputChange = (field, value) => {
329
- setFormData((prev) => ({ ...prev, [field]: value }));
371
+ setFormData((prev) => ({
372
+ ...prev,
373
+ [field]: value
374
+ }));
330
375
  };
331
376
  const handleCustomFieldChange = (fieldName, value) => {
332
377
  setFormData((prev) => ({
@@ -338,18 +383,17 @@ function Form({
338
383
  }));
339
384
  };
340
385
  if (isSuccess) {
341
- return /* @__PURE__ */ jsxs("div", { className: `channlize-form-success ${className}`, style: styles.success, children: [
342
- /* @__PURE__ */ jsx2("p", { children: successMessage }),
343
- /* @__PURE__ */ jsx2(
344
- "button",
345
- {
346
- type: "button",
347
- onClick: reset,
348
- style: styles.button,
349
- children: "Send Another Message"
350
- }
351
- )
352
- ] });
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
+ );
353
397
  }
354
398
  return /* @__PURE__ */ jsxs(
355
399
  "form",
@@ -454,15 +498,7 @@ function Form({
454
498
  )
455
499
  ] }),
456
500
  error && /* @__PURE__ */ jsx2("div", { className: "channlize-error", style: styles.error, children: error.message }),
457
- /* @__PURE__ */ jsx2(
458
- "button",
459
- {
460
- type: "submit",
461
- disabled: isSubmitting,
462
- style: styles.button,
463
- children: isSubmitting ? "Sending..." : submitText
464
- }
465
- )
501
+ /* @__PURE__ */ jsx2("button", { type: "submit", disabled: isSubmitting, style: styles.button, children: isSubmitting ? "Sending..." : submitText })
466
502
  ]
467
503
  }
468
504
  );
@@ -521,7 +557,10 @@ function SupportChat({
521
557
  e.preventDefault();
522
558
  if (!messageInput.trim() && attachments.length === 0) return;
523
559
  try {
524
- await sendMessage(messageInput, attachments.length > 0 ? attachments : void 0);
560
+ await sendMessage(
561
+ messageInput,
562
+ attachments.length > 0 ? attachments : void 0
563
+ );
525
564
  setMessageInput("");
526
565
  setAttachments([]);
527
566
  } catch (err) {
@@ -549,130 +588,183 @@ function SupportChat({
549
588
  }
550
589
  };
551
590
  if (!session && !isConnecting) {
552
- return /* @__PURE__ */ jsxs2("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
553
- /* @__PURE__ */ jsx4("div", { className: "channlize-chat-header", style: styles.header, children: /* @__PURE__ */ jsx4("h3", { children: title }) }),
554
- /* @__PURE__ */ jsx4("div", { className: "channlize-chat-start", children: /* @__PURE__ */ jsx4("button", { onClick: startSession, style: styles.button, children: "Start Chat" }) }),
555
- error && /* @__PURE__ */ jsx4("div", { className: "channlize-error", style: styles.error, children: error.message })
556
- ] });
557
- }
558
- return /* @__PURE__ */ jsxs2("div", { className: `channlize-chat-container ${className}`, style: styles.container, children: [
559
- /* @__PURE__ */ jsxs2("div", { className: "channlize-chat-header", style: styles.header, children: [
560
- /* @__PURE__ */ jsx4("h3", { children: title }),
561
- /* @__PURE__ */ jsxs2("div", { className: "channlize-chat-status", style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
562
- isConnecting && /* @__PURE__ */ jsxs2(Fragment, { children: [
563
- /* @__PURE__ */ jsx4("span", { style: {
564
- display: "inline-block",
565
- width: "8px",
566
- height: "8px",
567
- borderRadius: "50%",
568
- backgroundColor: "#f59e0b"
569
- } }),
570
- /* @__PURE__ */ jsx4("span", { children: "Connecting..." })
571
- ] }),
572
- isConnected && /* @__PURE__ */ jsxs2(Fragment, { children: [
573
- /* @__PURE__ */ jsx4("span", { style: {
574
- display: "inline-block",
575
- width: "8px",
576
- height: "8px",
577
- borderRadius: "50%",
578
- backgroundColor: "#10b981"
579
- } }),
580
- /* @__PURE__ */ jsx4("span", { children: "Connected" })
581
- ] }),
582
- !isConnected && !isConnecting && /* @__PURE__ */ jsxs2(Fragment, { children: [
583
- /* @__PURE__ */ jsx4("span", { style: {
584
- display: "inline-block",
585
- width: "8px",
586
- height: "8px",
587
- borderRadius: "50%",
588
- backgroundColor: "#ef4444"
589
- } }),
590
- /* @__PURE__ */ jsx4("span", { children: "Disconnected" })
591
- ] })
592
- ] }),
593
- session && /* @__PURE__ */ jsx4(
594
- "button",
595
- {
596
- onClick: endSession,
597
- style: { ...styles.button, fontSize: "0.875rem" },
598
- type: "button",
599
- children: "End Chat"
600
- }
601
- )
602
- ] }),
603
- /* @__PURE__ */ jsxs2("div", { className: "channlize-messages", style: styles.messagesContainer, children: [
604
- messages.length === 0 && /* @__PURE__ */ jsx4("div", { style: { textAlign: "center", padding: "2rem", color: "#666" }, children: "No messages yet. Start the conversation!" }),
605
- messages.map((message, index) => /* @__PURE__ */ jsxs2(
606
- "div",
607
- {
608
- className: `channlize-message ${message.author === "user" ? "channlize-message-user" : "channlize-message-agent"}`,
609
- style: {
610
- ...styles.message,
611
- ...message.author === "user" ? styles.userMessage : styles.agentMessage
612
- },
613
- children: [
614
- /* @__PURE__ */ jsx4("div", { className: "channlize-message-content", children: message.content }),
615
- showTimestamps && /* @__PURE__ */ jsx4("div", { className: "channlize-message-timestamp", style: styles.timestamp, children: formatTimestamp(message.timestamp) })
616
- ]
617
- },
618
- message.id || index
619
- )),
620
- /* @__PURE__ */ jsx4("div", { ref: messagesEndRef })
621
- ] }),
622
- error && /* @__PURE__ */ jsx4("div", { className: "channlize-error", style: styles.error, children: error.message }),
623
- /* @__PURE__ */ jsxs2(
624
- "form",
591
+ return /* @__PURE__ */ jsxs2(
592
+ "div",
625
593
  {
626
- className: "channlize-chat-input-container",
627
- style: styles.inputContainer,
628
- onSubmit: handleSubmit,
594
+ className: `channlize-chat-container ${className}`,
595
+ style: styles.container,
629
596
  children: [
630
- allowAttachments && /* @__PURE__ */ jsxs2("div", { children: [
631
- /* @__PURE__ */ jsx4(
632
- "input",
633
- {
634
- type: "file",
635
- multiple: true,
636
- onChange: handleFileChange,
637
- style: { fontSize: "0.875rem" }
638
- }
639
- ),
640
- attachments.length > 0 && /* @__PURE__ */ jsxs2("div", { style: { fontSize: "0.75rem", marginTop: "0.25rem" }, children: [
641
- attachments.length,
642
- " file(s) selected"
643
- ] })
644
- ] }),
645
- /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "0.5rem" }, children: [
646
- /* @__PURE__ */ jsx4(
647
- "input",
648
- {
649
- type: "text",
650
- value: messageInput,
651
- onChange: (e) => setMessageInput(e.target.value),
652
- placeholder,
653
- disabled: !session || isConnecting,
654
- style: { ...styles.input, flex: 1 }
655
- }
656
- ),
657
- /* @__PURE__ */ jsx4(
658
- "button",
659
- {
660
- type: "submit",
661
- disabled: !session || isConnecting || !messageInput.trim() && attachments.length === 0,
662
- style: styles.button,
663
- children: sendButtonText
664
- }
665
- )
666
- ] })
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 })
667
600
  ]
668
601
  }
669
- )
670
- ] });
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
+ );
671
753
  }
672
754
 
673
755
  // src/components/ChannlizeChat.tsx
674
- import { useState as useState5, useEffect as useEffect3 } from "react";
756
+ import { useState as useState5, useSyncExternalStore } from "react";
675
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
+ }
676
768
  function ChannlizeChat({
677
769
  config,
678
770
  position = "bottom-right",
@@ -698,19 +790,16 @@ function ChannlizeChat({
698
790
  chatClassName = ""
699
791
  }) {
700
792
  const [isOpen, setIsOpen] = useState5(defaultOpen);
701
- const [isMounted, setIsMounted] = useState5(false);
702
- const [isDarkMode, setIsDarkMode] = useState5(false);
703
- useEffect3(() => {
704
- setIsMounted(true);
705
- }, []);
706
- useEffect3(() => {
707
- if (typeof window === "undefined") return;
708
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
709
- setIsDarkMode(mediaQuery.matches);
710
- const handler = (e) => setIsDarkMode(e.matches);
711
- mediaQuery.addEventListener("change", handler);
712
- return () => mediaQuery.removeEventListener("change", handler);
713
- }, []);
793
+ const isMounted = useSyncExternalStore(
794
+ emptySubscribe,
795
+ () => true,
796
+ () => false
797
+ );
798
+ const isDarkMode = useSyncExternalStore(
799
+ subscribeDarkMode,
800
+ getDarkModeSnapshot,
801
+ () => false
802
+ );
714
803
  if (!isMounted) {
715
804
  return null;
716
805
  }
@@ -827,173 +916,166 @@ function ChannlizeChat({
827
916
  )
828
917
  }
829
918
  ),
830
- /* @__PURE__ */ jsxs3(
831
- "div",
832
- {
833
- style: chatContainerStyle,
834
- className: chatClassName,
835
- children: [
836
- /* @__PURE__ */ jsx5(
837
- SupportChat,
838
- {
839
- autoConnect: isOpen,
840
- persistSession: true,
841
- title: "Support Chat",
842
- placeholder: "Type your message...",
843
- showTimestamps: true,
844
- ...chatProps,
845
- styles: {
846
- container: {
847
- width: "384px",
848
- height: "600px",
849
- maxHeight: "calc(100vh - 120px)",
850
- borderRadius: "16px",
851
- overflow: "hidden",
852
- 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)",
853
- backgroundColor: isDarkMode ? "#1f2937" : "#ffffff",
854
- display: "flex",
855
- flexDirection: "column",
856
- position: "relative",
857
- ...chatProps.styles?.container
858
- },
859
- header: {
860
- background: "linear-gradient(135deg, #3b82f6 0%, #9333ea 100%)",
861
- padding: "20px",
862
- borderRadius: "16px 16px 0 0",
863
- color: "white",
864
- display: "flex",
865
- alignItems: "center",
866
- justifyContent: "space-between",
867
- ...chatProps.styles?.header
868
- },
869
- messagesContainer: {
870
- flex: 1,
871
- overflowY: "auto",
872
- padding: "20px",
873
- backgroundColor: isDarkMode ? "#111827" : "#f9fafb",
874
- ...chatProps.styles?.messagesContainer
875
- },
876
- inputContainer: {
877
- padding: "16px",
878
- backgroundColor: isDarkMode ? "#1f2937" : "white",
879
- borderTop: `1px solid ${isDarkMode ? "#374151" : "#e5e7eb"}`,
880
- ...chatProps.styles?.inputContainer
881
- },
882
- input: {
883
- ...chatProps.styles?.input,
884
- borderRadius: "12px",
885
- padding: "12px 16px",
886
- fontSize: "14px",
887
- border: `1px solid ${isDarkMode ? "#374151" : "#d1d5db"}`,
888
- outline: "none",
889
- backgroundColor: isDarkMode ? "#374151" : "#ffffff",
890
- color: isDarkMode ? "#f9fafb" : "#111827",
891
- fontWeight: "400"
892
- },
893
- button: {
894
- backgroundColor: "#3b82f6",
895
- color: "white",
896
- borderRadius: "12px",
897
- padding: "12px 24px",
898
- fontSize: "14px",
899
- fontWeight: "500",
900
- border: "none",
901
- cursor: "pointer",
902
- transition: "background-color 0.2s",
903
- ...chatProps.styles?.button
904
- },
905
- userMessage: {
906
- backgroundColor: "#3b82f6",
907
- color: "white",
908
- padding: "10px 14px",
909
- borderRadius: "12px 12px 4px 12px",
910
- marginBottom: "8px",
911
- marginLeft: "auto",
912
- maxWidth: "80%",
913
- width: "fit-content",
914
- ...chatProps.styles?.userMessage
915
- },
916
- agentMessage: {
917
- backgroundColor: isDarkMode ? "#374151" : "white",
918
- color: isDarkMode ? "#f9fafb" : "#1f2937",
919
- padding: "10px 14px",
920
- borderRadius: "12px 12px 12px 4px",
921
- marginBottom: "8px",
922
- marginRight: "auto",
923
- maxWidth: "80%",
924
- width: "fit-content",
925
- boxShadow: isDarkMode ? "0 1px 2px 0 rgb(0 0 0 / 0.3)" : "0 1px 2px 0 rgb(0 0 0 / 0.05)",
926
- ...chatProps.styles?.agentMessage
927
- },
928
- timestamp: {
929
- fontSize: "11px",
930
- opacity: 0.7,
931
- marginTop: "4px",
932
- color: isDarkMode ? "#d1d5db" : "inherit",
933
- ...chatProps.styles?.timestamp
934
- },
935
- error: {
936
- backgroundColor: isDarkMode ? "#7f1d1d" : "#fee2e2",
937
- color: isDarkMode ? "#fca5a5" : "#991b1b",
938
- padding: "12px",
939
- margin: "8px 16px",
940
- borderRadius: "8px",
941
- fontSize: "14px",
942
- ...chatProps.styles?.error
943
- }
944
- }
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
945
1027
  }
946
- ),
947
- /* @__PURE__ */ jsx5(
948
- "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",
949
1061
  {
950
- onClick: handleToggle,
951
- style: {
952
- position: "absolute",
953
- top: "16px",
954
- right: "16px",
955
- width: "32px",
956
- height: "32px",
957
- borderRadius: "50%",
958
- backgroundColor: "rgba(255, 255, 255, 0.2)",
959
- border: "none",
960
- cursor: "pointer",
961
- display: "flex",
962
- alignItems: "center",
963
- justifyContent: "center",
964
- color: "white",
965
- transition: "background-color 0.2s",
966
- zIndex: 10
967
- },
968
- onMouseEnter: (e) => {
969
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
970
- },
971
- onMouseLeave: (e) => {
972
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
973
- },
974
- "aria-label": "Close chat",
975
- children: /* @__PURE__ */ jsxs3(
976
- "svg",
977
- {
978
- width: "16",
979
- height: "16",
980
- viewBox: "0 0 24 24",
981
- fill: "none",
982
- stroke: "currentColor",
983
- strokeWidth: "2",
984
- strokeLinecap: "round",
985
- strokeLinejoin: "round",
986
- children: [
987
- /* @__PURE__ */ jsx5("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
988
- /* @__PURE__ */ jsx5("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
989
- ]
990
- }
991
- )
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
+ ]
992
1074
  }
993
1075
  )
994
- ]
995
- }
996
- )
1076
+ }
1077
+ )
1078
+ ] })
997
1079
  ] });
998
1080
  }
999
1081
  export {
@@ -1002,6 +1084,7 @@ export {
1002
1084
  ContactForm,
1003
1085
  SupportChat,
1004
1086
  useChannlize,
1087
+ useChannlizeAnalytics,
1005
1088
  useChatSession,
1006
1089
  useContactForm
1007
1090
  };