@channlize/react 0.3.0 → 0.5.0

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
@@ -1,5 +1,5 @@
1
1
  // src/context/ChannlizeContext.tsx
2
- import { createContext, useContext } from "react";
2
+ import { createContext, useContext, useMemo } from "react";
3
3
  import { ChannlizeClient } from "@channlize/core";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  var ChannlizeContext = createContext(null);
@@ -7,8 +7,19 @@ function ChannlizeProvider({
7
7
  config,
8
8
  children
9
9
  }) {
10
- const client = new ChannlizeClient(config);
11
- return /* @__PURE__ */ jsx(ChannlizeContext.Provider, { value: { client, config }, children });
10
+ const { apiKey, baseUrl, projectId, timeout, serverApiKey } = config;
11
+ const client = useMemo(
12
+ () => new ChannlizeClient({
13
+ apiKey,
14
+ baseUrl,
15
+ projectId,
16
+ timeout,
17
+ serverApiKey
18
+ }),
19
+ [apiKey, baseUrl, projectId, timeout, serverApiKey]
20
+ );
21
+ const value = useMemo(() => ({ client, config }), [client, config]);
22
+ return /* @__PURE__ */ jsx(ChannlizeContext.Provider, { value, children });
12
23
  }
13
24
  function useChannlize() {
14
25
  const context = useContext(ChannlizeContext);
@@ -60,6 +71,7 @@ function useContactForm(options = {}) {
60
71
 
61
72
  // src/hooks/useChatSession.ts
62
73
  import { useState as useState2, useEffect, useCallback as useCallback2, useRef } from "react";
74
+ import { DEFAULT_BASE_URL } from "@channlize/core";
63
75
  function useChatSession(options = {}) {
64
76
  const { client, config } = useChannlize();
65
77
  const [session, setSession] = useState2(null);
@@ -70,9 +82,27 @@ function useChatSession(options = {}) {
70
82
  const eventSourceRef = useRef(null);
71
83
  const sessionRef = useRef(null);
72
84
  const isInitializedRef = useRef(false);
73
- const baseUrl = config.baseUrl || "https://api.channlize.com";
85
+ const baseUrl = config.baseUrl || DEFAULT_BASE_URL;
74
86
  const storageKey = options.storageKey || `channlize_session_${config.apiKey}`;
75
87
  const persistSession = options.persistSession ?? true;
88
+ const latest = useRef({
89
+ onMessage: options.onMessage,
90
+ onError: options.onError,
91
+ debug: options.debug
92
+ });
93
+ useEffect(() => {
94
+ latest.current = {
95
+ onMessage: options.onMessage,
96
+ onError: options.onError,
97
+ debug: options.debug
98
+ };
99
+ });
100
+ const log = useCallback2(
101
+ (level, ...args) => {
102
+ if (latest.current.debug) console[level]("[channlize]", ...args);
103
+ },
104
+ []
105
+ );
76
106
  useEffect(() => {
77
107
  sessionRef.current = session;
78
108
  }, [session]);
@@ -82,51 +112,50 @@ function useChatSession(options = {}) {
82
112
  try {
83
113
  localStorage.setItem(storageKey, sessionId);
84
114
  } catch (err) {
85
- console.warn("Failed to save session to localStorage:", err);
115
+ log("warn", "Failed to save session to localStorage:", err);
86
116
  }
87
117
  }
88
118
  },
89
- [persistSession, storageKey]
119
+ [persistSession, storageKey, log]
90
120
  );
91
121
  const getSessionFromStorage = useCallback2(() => {
92
122
  if (persistSession && typeof window !== "undefined") {
93
123
  try {
94
124
  return localStorage.getItem(storageKey);
95
125
  } catch (err) {
96
- console.warn("Failed to get session from localStorage:", err);
126
+ log("warn", "Failed to get session from localStorage:", err);
97
127
  }
98
128
  }
99
129
  return null;
100
- }, [persistSession, storageKey]);
130
+ }, [persistSession, storageKey, log]);
101
131
  const clearSessionFromStorage = useCallback2(() => {
102
132
  if (persistSession && typeof window !== "undefined") {
103
133
  try {
104
134
  localStorage.removeItem(storageKey);
105
135
  } catch (err) {
106
- console.warn("Failed to clear session from localStorage:", err);
136
+ log("warn", "Failed to clear session from localStorage:", err);
107
137
  }
108
138
  }
109
- }, [persistSession, storageKey]);
139
+ }, [persistSession, storageKey, log]);
110
140
  const connectToSSE = useCallback2(
111
141
  (sseEndpoint) => {
112
142
  if (eventSourceRef.current) {
113
143
  eventSourceRef.current.close();
114
144
  }
115
145
  const fullUrl = sseEndpoint.startsWith("http") ? sseEndpoint : `${baseUrl}${sseEndpoint}`;
116
- console.log("[Channlize SSE] Connecting to:", fullUrl);
146
+ log("log", "SSE connecting to", fullUrl);
117
147
  const eventSource = new EventSource(fullUrl);
118
148
  eventSourceRef.current = eventSource;
119
149
  eventSource.onopen = () => {
120
- console.log("[Channlize SSE] Connection opened");
150
+ log("log", "SSE connection opened");
121
151
  setIsConnected(true);
122
152
  setError(null);
123
153
  };
124
154
  eventSource.addEventListener("connected", (event) => {
125
- console.log("SSE connected:", event.data);
155
+ log("log", "SSE connected:", event.data);
126
156
  });
127
157
  eventSource.addEventListener("message", (event) => {
128
158
  try {
129
- console.log("SSE message:", event.data);
130
159
  const message = JSON.parse(event.data);
131
160
  const chatMessage = {
132
161
  ...message,
@@ -136,9 +165,9 @@ function useChatSession(options = {}) {
136
165
  const exists = prev.some((m) => m.id === chatMessage.id);
137
166
  return exists ? prev : [...prev, chatMessage];
138
167
  });
139
- options.onMessage?.(chatMessage);
168
+ latest.current.onMessage?.(chatMessage);
140
169
  } catch (err) {
141
- console.warn("Failed to parse SSE message:", err, event.data);
170
+ log("warn", "Failed to parse SSE message:", err, event.data);
142
171
  }
143
172
  });
144
173
  eventSource.onmessage = (event) => {
@@ -153,10 +182,10 @@ function useChatSession(options = {}) {
153
182
  const exists = prev.some((m) => m.id === message.id);
154
183
  return exists ? prev : [...prev, message];
155
184
  });
156
- options.onMessage?.(message);
185
+ latest.current.onMessage?.(message);
157
186
  }
158
187
  } catch (err) {
159
- console.warn("Failed to parse default SSE message:", err);
188
+ log("warn", "Failed to parse default SSE message:", err);
160
189
  }
161
190
  };
162
191
  eventSource.onerror = (event) => {
@@ -164,7 +193,7 @@ function useChatSession(options = {}) {
164
193
  setIsConnected(false);
165
194
  return;
166
195
  }
167
- console.error("[Channlize SSE] Connection error", {
196
+ log("error", "SSE connection error", {
168
197
  readyState: eventSource.readyState,
169
198
  url: fullUrl,
170
199
  event
@@ -176,10 +205,10 @@ function useChatSession(options = {}) {
176
205
  const error2 = new Error(`SSE ${stateMessage}`);
177
206
  error2.code = "SSE_ERROR";
178
207
  setError(error2);
179
- options.onError?.(error2);
208
+ latest.current.onError?.(error2);
180
209
  };
181
210
  },
182
- [baseUrl, options.onError, options.onMessage]
211
+ [baseUrl, log]
183
212
  );
184
213
  const startSession = useCallback2(async () => {
185
214
  if (isConnecting || session) return;
@@ -189,7 +218,7 @@ function useChatSession(options = {}) {
189
218
  const existingSessionId = options.sessionId || getSessionFromStorage();
190
219
  if (existingSessionId) {
191
220
  try {
192
- console.log("\u{1F4E6} Resuming session from storage:", existingSessionId);
221
+ log("log", "Resuming session", existingSessionId);
193
222
  const existingSession = await client.getChatSession(existingSessionId);
194
223
  const existingMessages = await client.getChatMessages(existingSessionId);
195
224
  sessionRef.current = existingSession;
@@ -203,14 +232,14 @@ function useChatSession(options = {}) {
203
232
  setMessages(normalizedMessages2);
204
233
  const sseEndpoint = `/v1/chat/sessions/${existingSessionId}/events`;
205
234
  connectToSSE(sseEndpoint);
206
- console.log("\u2705 Session resumed successfully");
235
+ log("log", "Session resumed");
207
236
  return;
208
237
  } catch (err) {
209
- console.warn("\u26A0\uFE0F Failed to resume session, creating new one:", err);
238
+ log("warn", "Could not resume the session, starting a new one:", err);
210
239
  clearSessionFromStorage();
211
240
  }
212
241
  }
213
- console.log("\u{1F195} Creating new chat session");
242
+ log("log", "Creating a chat session");
214
243
  const response = await client.createChatSession(options.metadata);
215
244
  sessionRef.current = response.session;
216
245
  setSession(response.session);
@@ -225,19 +254,19 @@ function useChatSession(options = {}) {
225
254
  if (response.sseEndpoint) {
226
255
  connectToSSE(response.sseEndpoint);
227
256
  }
228
- console.log("\u2705 New session created:", response.session.id);
257
+ log("log", "Session created", response.session.id);
229
258
  } catch (err) {
230
259
  const error2 = err;
231
260
  setError(error2);
232
- options.onError?.(error2);
261
+ latest.current.onError?.(error2);
233
262
  } finally {
234
263
  setIsConnecting(false);
235
264
  }
236
265
  }, [
237
266
  client,
238
267
  connectToSSE,
268
+ log,
239
269
  options.metadata,
240
- options.onError,
241
270
  options.sessionId,
242
271
  getSessionFromStorage,
243
272
  saveSessionToStorage,
@@ -268,11 +297,11 @@ function useChatSession(options = {}) {
268
297
  } catch (err) {
269
298
  const error2 = err;
270
299
  setError(error2);
271
- options.onError?.(error2);
300
+ latest.current.onError?.(error2);
272
301
  throw error2;
273
302
  }
274
303
  },
275
- [client, options.onError]
304
+ [client]
276
305
  );
277
306
  const endSession = useCallback2(async () => {
278
307
  if (!sessionRef.current) return;
@@ -287,13 +316,13 @@ function useChatSession(options = {}) {
287
316
  setSession(null);
288
317
  setMessages([]);
289
318
  setIsConnected(false);
290
- console.log("\u2705 Session ended and cleared from storage");
319
+ log("log", "Session ended");
291
320
  } catch (err) {
292
321
  const error2 = err;
293
322
  setError(error2);
294
- options.onError?.(error2);
323
+ latest.current.onError?.(error2);
295
324
  }
296
- }, [client, options.onError, clearSessionFromStorage]);
325
+ }, [client, log, clearSessionFromStorage]);
297
326
  const reconnect = useCallback2(() => {
298
327
  const current = sessionRef.current;
299
328
  if (!current) return;
@@ -344,7 +373,7 @@ function useChannlizeAnalytics() {
344
373
  // src/components/Form.tsx
345
374
  import {
346
375
  useEffect as useEffect2,
347
- useMemo,
376
+ useMemo as useMemo2,
348
377
  useRef as useRef2,
349
378
  useState as useState3
350
379
  } from "react";
@@ -787,7 +816,7 @@ function Form({
787
816
  ...submitText !== void 0 && { submit: submitText },
788
817
  ...successMessage !== void 0 && { successMessage }
789
818
  };
790
- const topicOptions = useMemo(() => normalizeTopics(topics), [topics]);
819
+ const topicOptions = useMemo2(() => normalizeTopics(topics), [topics]);
791
820
  const modes = {
792
821
  name: fields.name ?? "required",
793
822
  company: fields.company ?? "hidden",
@@ -1284,10 +1313,11 @@ import {
1284
1313
  useCallback as useCallback4,
1285
1314
  useEffect as useEffect4,
1286
1315
  useId,
1287
- useMemo as useMemo2,
1316
+ useMemo as useMemo3,
1288
1317
  useRef as useRef3,
1289
1318
  useState as useState5
1290
1319
  } from "react";
1320
+ import { DEFAULT_BASE_URL as DEFAULT_BASE_URL2 } from "@channlize/core";
1291
1321
 
1292
1322
  // src/components/chat/internal.tsx
1293
1323
  import {
@@ -1650,6 +1680,7 @@ function SupportChat({
1650
1680
  sessionId,
1651
1681
  persistSession,
1652
1682
  storageKey,
1683
+ debug,
1653
1684
  className = "",
1654
1685
  styles = {},
1655
1686
  placeholder = "Write a message\u2026",
@@ -1672,12 +1703,12 @@ function SupportChat({
1672
1703
  onMinimize,
1673
1704
  labels: labelOverrides
1674
1705
  }) {
1675
- const labels = useMemo2(
1706
+ const labels = useMemo3(
1676
1707
  () => ({ ...defaultSupportChatLabels, ...labelOverrides }),
1677
1708
  [labelOverrides]
1678
1709
  );
1679
1710
  const { config } = useChannlize();
1680
- const baseUrl = config.baseUrl || "https://api.channlize.com";
1711
+ const baseUrl = config.baseUrl || DEFAULT_BASE_URL2;
1681
1712
  const [text, setText] = useState5("");
1682
1713
  const [files, setFiles] = useState5([]);
1683
1714
  const [pending, setPending] = useState5([]);
@@ -1715,7 +1746,8 @@ function SupportChat({
1715
1746
  onError,
1716
1747
  sessionId,
1717
1748
  persistSession,
1718
- storageKey
1749
+ storageKey,
1750
+ debug
1719
1751
  });
1720
1752
  const sseFailed = error?.code === "SSE_ERROR";
1721
1753
  const ownSendError = !!error && error === sendError;
@@ -1731,7 +1763,7 @@ function SupportChat({
1731
1763
  );
1732
1764
  const status = sseFailed || startFailed ? "offline" : showConnecting ? "connecting" : "online";
1733
1765
  const statusLabel = status === "offline" ? labels.offline : status === "connecting" ? session ? labels.reconnecting : labels.connecting : statusText ? `${labels.online} \xB7 ${statusText}` : labels.online;
1734
- const displayMessages = useMemo2(() => {
1766
+ const displayMessages = useMemo3(() => {
1735
1767
  const fromServer = messages.map(
1736
1768
  (m, i) => ({
1737
1769
  key: m.id || `m-${i}`,
@@ -1761,7 +1793,7 @@ function SupportChat({
1761
1793
  }));
1762
1794
  return [...fromServer, ...local];
1763
1795
  }, [messages, pending, title, baseUrl]);
1764
- const sections = useMemo2(
1796
+ const sections = useMemo3(
1765
1797
  () => groupMessages(displayMessages),
1766
1798
  [displayMessages]
1767
1799
  );
@@ -2303,7 +2335,7 @@ function MessageBubble({
2303
2335
  onRemove
2304
2336
  }) {
2305
2337
  const isUser = msg.author === "user";
2306
- const parts = useMemo2(() => linkify(msg.content), [msg.content]);
2338
+ const parts = useMemo3(() => linkify(msg.content), [msg.content]);
2307
2339
  return /* @__PURE__ */ jsxs4(Fragment, { children: [
2308
2340
  /* @__PURE__ */ jsxs4(
2309
2341
  "div",
@@ -2600,11 +2632,23 @@ function ChannlizeChat({
2600
2632
  ) }) });
2601
2633
  return typeof document !== "undefined" ? createPortal(widget, document.body) : widget;
2602
2634
  }
2635
+
2636
+ // src/index.ts
2637
+ import {
2638
+ ChannlizeError,
2639
+ ValidationError,
2640
+ AuthenticationError,
2641
+ RateLimitError
2642
+ } from "@channlize/core";
2603
2643
  export {
2644
+ AuthenticationError,
2604
2645
  ChannlizeChat,
2646
+ ChannlizeError,
2605
2647
  ChannlizeProvider,
2606
2648
  ContactForm,
2649
+ RateLimitError,
2607
2650
  SupportChat,
2651
+ ValidationError,
2608
2652
  defaultContactFormLabels,
2609
2653
  defaultSupportChatLabels,
2610
2654
  useChannlize,