@aigentyc/chat-sdk 0.1.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.
Files changed (162) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +156 -0
  3. package/dist/JsonRenderResult-Ftw4AKwb.d.cts +18 -0
  4. package/dist/JsonRenderResult-Ftw4AKwb.d.ts +18 -0
  5. package/dist/JsonRenderResult-GQOYPLVH.cjs +15 -0
  6. package/dist/JsonRenderResult-GQOYPLVH.cjs.map +1 -0
  7. package/dist/JsonRenderResult-ZFJ6VWMS.js +6 -0
  8. package/dist/JsonRenderResult-ZFJ6VWMS.js.map +1 -0
  9. package/dist/SlotsContext-CBtt36al.d.ts +148 -0
  10. package/dist/SlotsContext-CHvISDJT.d.cts +148 -0
  11. package/dist/VisualizationRenderer-FNFYNN66.js +5 -0
  12. package/dist/VisualizationRenderer-FNFYNN66.js.map +1 -0
  13. package/dist/VisualizationRenderer-VKMZXRUX.cjs +20 -0
  14. package/dist/VisualizationRenderer-VKMZXRUX.cjs.map +1 -0
  15. package/dist/ai-elements.cjs +4608 -0
  16. package/dist/ai-elements.cjs.map +1 -0
  17. package/dist/ai-elements.d.cts +897 -0
  18. package/dist/ai-elements.d.ts +897 -0
  19. package/dist/ai-elements.js +4363 -0
  20. package/dist/ai-elements.js.map +1 -0
  21. package/dist/chunk-3MP2EGEJ.cjs +270 -0
  22. package/dist/chunk-3MP2EGEJ.cjs.map +1 -0
  23. package/dist/chunk-3RW7O444.js +26 -0
  24. package/dist/chunk-3RW7O444.js.map +1 -0
  25. package/dist/chunk-42ARGQXE.js +51 -0
  26. package/dist/chunk-42ARGQXE.js.map +1 -0
  27. package/dist/chunk-4FBVV64J.js +257 -0
  28. package/dist/chunk-4FBVV64J.js.map +1 -0
  29. package/dist/chunk-4QT25AXI.js +21 -0
  30. package/dist/chunk-4QT25AXI.js.map +1 -0
  31. package/dist/chunk-525KS5HM.cjs +30 -0
  32. package/dist/chunk-525KS5HM.cjs.map +1 -0
  33. package/dist/chunk-5F3O3ZJH.js +299 -0
  34. package/dist/chunk-5F3O3ZJH.js.map +1 -0
  35. package/dist/chunk-5QSXB6UL.cjs +259 -0
  36. package/dist/chunk-5QSXB6UL.cjs.map +1 -0
  37. package/dist/chunk-5T4FJ2SR.js +664 -0
  38. package/dist/chunk-5T4FJ2SR.js.map +1 -0
  39. package/dist/chunk-7BNYTOTE.cjs +67 -0
  40. package/dist/chunk-7BNYTOTE.cjs.map +1 -0
  41. package/dist/chunk-AWAJOSFP.cjs +96 -0
  42. package/dist/chunk-AWAJOSFP.cjs.map +1 -0
  43. package/dist/chunk-BKDV2H6Z.js +224 -0
  44. package/dist/chunk-BKDV2H6Z.js.map +1 -0
  45. package/dist/chunk-FQN6OBGN.cjs +171 -0
  46. package/dist/chunk-FQN6OBGN.cjs.map +1 -0
  47. package/dist/chunk-FYPJSHCL.js +190 -0
  48. package/dist/chunk-FYPJSHCL.js.map +1 -0
  49. package/dist/chunk-J2H6MLQF.cjs +680 -0
  50. package/dist/chunk-J2H6MLQF.cjs.map +1 -0
  51. package/dist/chunk-J2K7EJYP.cjs +198 -0
  52. package/dist/chunk-J2K7EJYP.cjs.map +1 -0
  53. package/dist/chunk-JI5KCSOI.cjs +23 -0
  54. package/dist/chunk-JI5KCSOI.cjs.map +1 -0
  55. package/dist/chunk-JOO6C3XT.cjs +44 -0
  56. package/dist/chunk-JOO6C3XT.cjs.map +1 -0
  57. package/dist/chunk-KBGPBUTI.cjs +78 -0
  58. package/dist/chunk-KBGPBUTI.cjs.map +1 -0
  59. package/dist/chunk-MT2AMINB.js +75 -0
  60. package/dist/chunk-MT2AMINB.js.map +1 -0
  61. package/dist/chunk-MZQKGNWF.js +4 -0
  62. package/dist/chunk-MZQKGNWF.js.map +1 -0
  63. package/dist/chunk-NG7OTWXQ.cjs +226 -0
  64. package/dist/chunk-NG7OTWXQ.cjs.map +1 -0
  65. package/dist/chunk-NPJKLYLV.js +68 -0
  66. package/dist/chunk-NPJKLYLV.js.map +1 -0
  67. package/dist/chunk-NW2ESHRV.js +685 -0
  68. package/dist/chunk-NW2ESHRV.js.map +1 -0
  69. package/dist/chunk-NWF735F5.js +1631 -0
  70. package/dist/chunk-NWF735F5.js.map +1 -0
  71. package/dist/chunk-NYQSM3EB.cjs +305 -0
  72. package/dist/chunk-NYQSM3EB.cjs.map +1 -0
  73. package/dist/chunk-OU7OROOE.cjs +1643 -0
  74. package/dist/chunk-OU7OROOE.cjs.map +1 -0
  75. package/dist/chunk-PS3U7T37.js +42 -0
  76. package/dist/chunk-PS3U7T37.js.map +1 -0
  77. package/dist/chunk-Q7T3VAJV.cjs +687 -0
  78. package/dist/chunk-Q7T3VAJV.cjs.map +1 -0
  79. package/dist/chunk-QYCEHFAB.js +265 -0
  80. package/dist/chunk-QYCEHFAB.js.map +1 -0
  81. package/dist/chunk-RPDJXB3U.js +676 -0
  82. package/dist/chunk-RPDJXB3U.js.map +1 -0
  83. package/dist/chunk-UKEL7FWS.js +64 -0
  84. package/dist/chunk-UKEL7FWS.js.map +1 -0
  85. package/dist/chunk-VS3NZ7FX.js +164 -0
  86. package/dist/chunk-VS3NZ7FX.js.map +1 -0
  87. package/dist/chunk-WZLWAVSS.cjs +73 -0
  88. package/dist/chunk-WZLWAVSS.cjs.map +1 -0
  89. package/dist/chunk-X5YEOOPK.cjs +758 -0
  90. package/dist/chunk-X5YEOOPK.cjs.map +1 -0
  91. package/dist/chunk-X7R334SB.cjs +5 -0
  92. package/dist/chunk-X7R334SB.cjs.map +1 -0
  93. package/dist/chunk-XXNDL5SJ.cjs +432 -0
  94. package/dist/chunk-XXNDL5SJ.cjs.map +1 -0
  95. package/dist/chunk-YQELMJW5.js +429 -0
  96. package/dist/chunk-YQELMJW5.js.map +1 -0
  97. package/dist/components.cjs +551 -0
  98. package/dist/components.cjs.map +1 -0
  99. package/dist/components.d.cts +181 -0
  100. package/dist/components.d.ts +181 -0
  101. package/dist/components.js +483 -0
  102. package/dist/components.js.map +1 -0
  103. package/dist/core.cjs +283 -0
  104. package/dist/core.cjs.map +1 -0
  105. package/dist/core.d.cts +455 -0
  106. package/dist/core.d.ts +455 -0
  107. package/dist/core.js +241 -0
  108. package/dist/core.js.map +1 -0
  109. package/dist/hooks.cjs +324 -0
  110. package/dist/hooks.cjs.map +1 -0
  111. package/dist/hooks.d.cts +163 -0
  112. package/dist/hooks.d.ts +163 -0
  113. package/dist/hooks.js +277 -0
  114. package/dist/hooks.js.map +1 -0
  115. package/dist/i18n.cjs +26 -0
  116. package/dist/i18n.cjs.map +1 -0
  117. package/dist/i18n.d.cts +50 -0
  118. package/dist/i18n.d.ts +50 -0
  119. package/dist/i18n.js +5 -0
  120. package/dist/i18n.js.map +1 -0
  121. package/dist/index.cjs +466 -0
  122. package/dist/index.cjs.map +1 -0
  123. package/dist/index.d.cts +80 -0
  124. package/dist/index.d.ts +80 -0
  125. package/dist/index.js +438 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/interaction-tracker-D9P1Oq4j.d.cts +83 -0
  128. package/dist/interaction-tracker-D9P1Oq4j.d.ts +83 -0
  129. package/dist/json-render.cjs +23 -0
  130. package/dist/json-render.cjs.map +1 -0
  131. package/dist/json-render.d.cts +857 -0
  132. package/dist/json-render.d.ts +857 -0
  133. package/dist/json-render.js +6 -0
  134. package/dist/json-render.js.map +1 -0
  135. package/dist/live-chat-transport-4XLOIPOE.js +4 -0
  136. package/dist/live-chat-transport-4XLOIPOE.js.map +1 -0
  137. package/dist/live-chat-transport-ALVRGWX7.cjs +13 -0
  138. package/dist/live-chat-transport-ALVRGWX7.cjs.map +1 -0
  139. package/dist/select-B4l9yoyn.d.cts +99 -0
  140. package/dist/select-B4l9yoyn.d.ts +99 -0
  141. package/dist/styles.css +2 -0
  142. package/dist/theme.cjs +18 -0
  143. package/dist/theme.cjs.map +1 -0
  144. package/dist/theme.d.cts +55 -0
  145. package/dist/theme.d.ts +55 -0
  146. package/dist/theme.js +5 -0
  147. package/dist/theme.js.map +1 -0
  148. package/dist/tools.cjs +32 -0
  149. package/dist/tools.cjs.map +1 -0
  150. package/dist/tools.d.cts +117 -0
  151. package/dist/tools.d.ts +117 -0
  152. package/dist/tools.js +11 -0
  153. package/dist/tools.js.map +1 -0
  154. package/dist/types-DKJ_-nbG.d.cts +349 -0
  155. package/dist/types-DKJ_-nbG.d.ts +349 -0
  156. package/dist/ui.cjs +667 -0
  157. package/dist/ui.cjs.map +1 -0
  158. package/dist/ui.d.cts +95 -0
  159. package/dist/ui.d.ts +95 -0
  160. package/dist/ui.js +414 -0
  161. package/dist/ui.js.map +1 -0
  162. package/package.json +255 -0
@@ -0,0 +1,257 @@
1
+ "use client";
2
+ import { LiveChatTransport } from './chunk-BKDV2H6Z.js';
3
+ import { useRef, useState, useMemo, useEffect, useCallback } from 'react';
4
+ import { useChat } from '@ai-sdk/react';
5
+ import { DefaultChatTransport } from 'ai';
6
+
7
+ var SESSION_KEY_PREFIX = "aigentyc-session-";
8
+ var MESSAGE_KEY_PREFIX = "aigentyc-messages-";
9
+ function getOrCreateSessionId(projectId) {
10
+ if (typeof window === "undefined") return crypto.randomUUID();
11
+ const key = SESSION_KEY_PREFIX + projectId;
12
+ try {
13
+ const stored = sessionStorage.getItem(key);
14
+ if (stored) return stored;
15
+ const id = crypto.randomUUID();
16
+ sessionStorage.setItem(key, id);
17
+ return id;
18
+ } catch {
19
+ return crypto.randomUUID();
20
+ }
21
+ }
22
+ function loadPersistedMessages(projectId) {
23
+ if (typeof window === "undefined") return [];
24
+ try {
25
+ const raw = localStorage.getItem(MESSAGE_KEY_PREFIX + projectId);
26
+ return raw ? JSON.parse(raw) : [];
27
+ } catch {
28
+ return [];
29
+ }
30
+ }
31
+ function persistMessages(projectId, messages) {
32
+ if (typeof window === "undefined") return;
33
+ try {
34
+ localStorage.setItem(MESSAGE_KEY_PREFIX + projectId, JSON.stringify(messages));
35
+ } catch {
36
+ }
37
+ }
38
+ function clearPersistedMessages(projectId) {
39
+ if (typeof window === "undefined") return;
40
+ try {
41
+ localStorage.removeItem(MESSAGE_KEY_PREFIX + projectId);
42
+ } catch {
43
+ }
44
+ }
45
+ var CALLBACK_KEYS = [
46
+ "onReady",
47
+ "onSessionStart",
48
+ "onSessionRestore",
49
+ "onMessageSent",
50
+ "onMessageReceived",
51
+ "onStreamStart",
52
+ "onStreamEnd",
53
+ "onToolCall",
54
+ "onToolResult",
55
+ "onToolAction",
56
+ "onLiveChatRequested",
57
+ "onLiveChatConnected",
58
+ "onLiveChatEnded",
59
+ "onError",
60
+ "onInteraction"
61
+ ];
62
+ function pickCallbacks(opts) {
63
+ const out = {};
64
+ for (const key of CALLBACK_KEYS) {
65
+ if (opts[key] !== void 0) out[key] = opts[key];
66
+ }
67
+ return out;
68
+ }
69
+ function useAigentycChat(options) {
70
+ const {
71
+ projectId,
72
+ apiEndpoint,
73
+ apiKey,
74
+ enableLiveChat = false,
75
+ chatServiceUrl,
76
+ persistMessages: shouldPersist = true
77
+ } = options;
78
+ const callbacks = pickCallbacks(options);
79
+ const callbacksRef = useRef(callbacks);
80
+ callbacksRef.current = callbacks;
81
+ const safeProjectId = projectId || "default";
82
+ const [sessionId, setSessionId] = useState(() => getOrCreateSessionId(safeProjectId));
83
+ const chatRef = useRef(null);
84
+ const initialMessages = useMemo(
85
+ () => shouldPersist ? loadPersistedMessages(safeProjectId) : [],
86
+ // eslint-disable-next-line react-hooks/exhaustive-deps
87
+ []
88
+ );
89
+ const transport = useMemo(
90
+ () => new DefaultChatTransport({
91
+ api: `${apiEndpoint || ""}/api/kb/chat`,
92
+ headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : void 0,
93
+ body: { projectId: safeProjectId, sessionId }
94
+ }),
95
+ [apiEndpoint, apiKey, safeProjectId, sessionId]
96
+ );
97
+ const {
98
+ messages,
99
+ sendMessage: sdkSendMessage,
100
+ status: sdkStatus,
101
+ error,
102
+ stop,
103
+ setMessages
104
+ } = useChat({
105
+ id: sessionId,
106
+ messages: initialMessages,
107
+ transport,
108
+ onFinish: (message) => {
109
+ callbacksRef.current?.onMessageReceived?.(message);
110
+ },
111
+ onError: (err) => {
112
+ callbacksRef.current?.onError?.(err);
113
+ }
114
+ });
115
+ const status = error ? "error" : sdkStatus === "streaming" || sdkStatus === "submitted" ? "streaming" : "idle";
116
+ useEffect(() => {
117
+ if (shouldPersist) persistMessages(safeProjectId, messages);
118
+ }, [messages, safeProjectId, shouldPersist]);
119
+ const activeTools = useMemo(() => {
120
+ if (messages.length === 0) return [];
121
+ const last = messages[messages.length - 1];
122
+ if (last.role !== "assistant" || !Array.isArray(last.parts)) return [];
123
+ return last.parts.filter((p) => typeof p.type === "string" && p.type.startsWith("tool-")).map((p) => ({
124
+ toolName: p.toolName || p.type.replace("tool-", ""),
125
+ state: p.state || "output-available",
126
+ args: p.args || {},
127
+ result: p.result,
128
+ renderMode: p.renderMode || "inline"
129
+ }));
130
+ }, [messages]);
131
+ const sendMessage = useCallback(
132
+ (content) => {
133
+ if (!content.trim()) return;
134
+ callbacksRef.current?.onMessageSent?.({
135
+ id: crypto.randomUUID(),
136
+ role: "user",
137
+ content
138
+ });
139
+ sdkSendMessage({ text: content });
140
+ },
141
+ [sdkSendMessage]
142
+ );
143
+ const stopGeneration = useCallback(() => stop(), [stop]);
144
+ const newConversation = useCallback(() => {
145
+ setMessages([]);
146
+ clearPersistedMessages(safeProjectId);
147
+ if (typeof window !== "undefined") {
148
+ try {
149
+ sessionStorage.removeItem(SESSION_KEY_PREFIX + safeProjectId);
150
+ } catch {
151
+ }
152
+ }
153
+ setSessionId(getOrCreateSessionId(safeProjectId));
154
+ }, [safeProjectId, setMessages]);
155
+ const clearMessages = useCallback(() => {
156
+ setMessages([]);
157
+ clearPersistedMessages(safeProjectId);
158
+ }, [safeProjectId, setMessages]);
159
+ const [lcState, setLcState] = useState("ai");
160
+ const [lcMessages, setLcMessages] = useState([]);
161
+ const [lcOperator, setLcOperator] = useState("");
162
+ const [lcQueue, setLcQueue] = useState(0);
163
+ const [lcShowIdentity, setLcShowIdentity] = useState(false);
164
+ const lcTransportRef = useRef(null);
165
+ const lcResetState = useCallback(() => {
166
+ lcTransportRef.current?.disconnect?.();
167
+ lcTransportRef.current = null;
168
+ setLcState("ai");
169
+ setLcMessages([]);
170
+ setLcOperator("");
171
+ setLcQueue(0);
172
+ setLcShowIdentity(false);
173
+ }, []);
174
+ const lcInitiate = useCallback(
175
+ async (visitorName, visitorEmail) => {
176
+ if (!enableLiveChat || lcTransportRef.current) return;
177
+ const url = chatServiceUrl ?? apiEndpoint;
178
+ if (!url || !apiKey) return;
179
+ try {
180
+ const transport2 = new LiveChatTransport({
181
+ chatServiceUrl: url,
182
+ apiKey,
183
+ projectId: safeProjectId,
184
+ visitorSessionId: sessionId
185
+ });
186
+ transport2.on("state-change", (s) => setLcState(s));
187
+ transport2.on("queued", (data) => setLcQueue(data.position));
188
+ transport2.on("queue-update", (data) => setLcQueue(data.position));
189
+ transport2.on("accepted", (data) => setLcOperator(data.operatorName));
190
+ transport2.on(
191
+ "message",
192
+ (data) => setLcMessages((prev) => [...prev, data])
193
+ );
194
+ transport2.on("ended", () => setLcState("ended"));
195
+ lcTransportRef.current = transport2;
196
+ await transport2.connect();
197
+ await transport2.requestHandoff({
198
+ visitorName,
199
+ visitorEmail,
200
+ aiChatHistory: []
201
+ });
202
+ callbacksRef.current?.onLiveChatRequested?.();
203
+ } catch (err) {
204
+ callbacksRef.current?.onError?.(err);
205
+ setLcState("ai");
206
+ }
207
+ },
208
+ [enableLiveChat, chatServiceUrl, apiEndpoint, apiKey, safeProjectId, sessionId]
209
+ );
210
+ const liveChat = useMemo(
211
+ () => ({
212
+ state: lcState,
213
+ messages: lcMessages,
214
+ operatorName: lcOperator,
215
+ queuePosition: lcQueue,
216
+ showIdentityForm: lcShowIdentity,
217
+ initiate: lcInitiate,
218
+ send: (content) => {
219
+ if (!content.trim()) return;
220
+ lcTransportRef.current?.sendMessage?.(content);
221
+ setLcMessages((prev) => [
222
+ ...prev,
223
+ {
224
+ id: Date.now(),
225
+ content,
226
+ senderType: "visitor",
227
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
228
+ }
229
+ ]);
230
+ },
231
+ end: () => lcTransportRef.current?.endChat?.(),
232
+ cancel: () => lcResetState(),
233
+ submitRating: (rating, comment) => lcTransportRef.current?.submitRating?.(rating, comment),
234
+ returnToAI: () => lcResetState(),
235
+ requestManualHandoff: () => setLcShowIdentity(true),
236
+ setShowIdentityForm: setLcShowIdentity
237
+ }),
238
+ [lcState, lcMessages, lcOperator, lcQueue, lcShowIdentity, lcInitiate, lcResetState]
239
+ );
240
+ return {
241
+ messages,
242
+ status,
243
+ error,
244
+ sessionId,
245
+ sendMessage,
246
+ stopGeneration,
247
+ newConversation,
248
+ clearMessages,
249
+ activeTools,
250
+ liveChat,
251
+ chatRef
252
+ };
253
+ }
254
+
255
+ export { useAigentycChat };
256
+ //# sourceMappingURL=chunk-4FBVV64J.js.map
257
+ //# sourceMappingURL=chunk-4FBVV64J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-aigentyc-chat.ts"],"names":["transport"],"mappings":"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","file":"chunk-4FBVV64J.js","sourcesContent":["\"use client\";\n\nimport {\n useState,\n useCallback,\n useRef,\n useMemo,\n useEffect,\n type RefObject,\n} from \"react\";\nimport type {\n ChatProviderProps,\n ChatMessage,\n ChatEventCallbacks,\n LiveChatState,\n LiveChatMessage,\n} from \"../core/types\";\n\ntype ChatStatus = \"idle\" | \"streaming\" | \"error\";\n\ninterface ActiveTool {\n toolName: string;\n state: \"partial-call\" | \"call\" | \"output-available\";\n args: Record<string, unknown>;\n result?: unknown;\n renderMode: string;\n}\n// NOTE: @ai-sdk/react and ai are optional peer dependencies.\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport } from \"ai\";\nimport { LiveChatTransport } from \"../core/live-chat-transport\";\n\nconst SESSION_KEY_PREFIX = \"aigentyc-session-\";\nconst MESSAGE_KEY_PREFIX = \"aigentyc-messages-\";\n\nfunction getOrCreateSessionId(projectId: string): string {\n if (typeof window === \"undefined\") return crypto.randomUUID();\n const key = SESSION_KEY_PREFIX + projectId;\n try {\n const stored = sessionStorage.getItem(key);\n if (stored) return stored;\n const id = crypto.randomUUID();\n sessionStorage.setItem(key, id);\n return id;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nfunction loadPersistedMessages(projectId: string): ChatMessage[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(MESSAGE_KEY_PREFIX + projectId);\n return raw ? JSON.parse(raw) : [];\n } catch {\n return [];\n }\n}\n\nfunction persistMessages(projectId: string, messages: unknown[]): void {\n if (typeof window === \"undefined\") return;\n try {\n localStorage.setItem(MESSAGE_KEY_PREFIX + projectId, JSON.stringify(messages));\n } catch {\n // Ignore.\n }\n}\n\nfunction clearPersistedMessages(projectId: string): void {\n if (typeof window === \"undefined\") return;\n try {\n localStorage.removeItem(MESSAGE_KEY_PREFIX + projectId);\n } catch {\n // Ignore.\n }\n}\n\n/** Options for the headless `useAigentycChat` hook (same shape as ChatProviderProps). */\nexport type UseAigentycChatOptions = Omit<ChatProviderProps, \"children\" | \"slots\" | \"theme\">;\n\n/** Live chat sub-object returned by the hook. */\nexport interface LiveChatReturn {\n state: LiveChatState;\n messages: LiveChatMessage[];\n operatorName: string;\n queuePosition: number;\n showIdentityForm: boolean;\n initiate: (visitorName?: string, visitorEmail?: string) => Promise<void>;\n send: (content: string) => void;\n end: () => void;\n cancel: () => void;\n submitRating: (rating: \"positive\" | \"negative\", comment?: string) => void;\n returnToAI: () => void;\n requestManualHandoff: () => void;\n setShowIdentityForm: (show: boolean) => void;\n}\n\n/** Return value of `useAigentycChat`. */\nexport interface UseAigentycChatReturn {\n messages: ChatMessage[];\n status: ChatStatus;\n error: Error | undefined;\n sessionId: string;\n sendMessage: (content: string) => void;\n stopGeneration: () => void;\n newConversation: () => void;\n clearMessages: () => void;\n activeTools: ActiveTool[];\n liveChat: LiveChatReturn;\n chatRef: RefObject<HTMLDivElement | null>;\n}\n\nconst CALLBACK_KEYS: (keyof ChatEventCallbacks)[] = [\n \"onReady\",\n \"onSessionStart\",\n \"onSessionRestore\",\n \"onMessageSent\",\n \"onMessageReceived\",\n \"onStreamStart\",\n \"onStreamEnd\",\n \"onToolCall\",\n \"onToolResult\",\n \"onToolAction\",\n \"onLiveChatRequested\",\n \"onLiveChatConnected\",\n \"onLiveChatEnded\",\n \"onError\",\n \"onInteraction\",\n];\n\nfunction pickCallbacks(opts: Record<string, unknown>): ChatEventCallbacks {\n const out: Record<string, unknown> = {};\n for (const key of CALLBACK_KEYS) {\n if (opts[key] !== undefined) out[key] = opts[key];\n }\n return out as ChatEventCallbacks;\n}\n\n/**\n * Standalone headless hook for Aigentyc Chat. No provider needed.\n *\n * Creates its own transport, session, and persistence internally. Use this\n * when you want full control over the UI but still want all SDK features\n * (chat, tools, live chat, persistence).\n */\nexport function useAigentycChat(options: UseAigentycChatOptions): UseAigentycChatReturn {\n const {\n projectId,\n apiEndpoint,\n apiKey,\n enableLiveChat = false,\n chatServiceUrl,\n persistMessages: shouldPersist = true,\n } = options;\n\n const callbacks = pickCallbacks(options as unknown as Record<string, unknown>);\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n\n const safeProjectId = projectId || \"default\";\n const [sessionId, setSessionId] = useState(() => getOrCreateSessionId(safeProjectId));\n const chatRef = useRef<HTMLDivElement | null>(null);\n\n const initialMessages = useMemo(\n () => (shouldPersist ? loadPersistedMessages(safeProjectId) : []),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n []\n );\n\n const transport = useMemo(\n () =>\n new DefaultChatTransport({\n api: `${apiEndpoint || \"\"}/api/kb/chat`,\n headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined,\n body: { projectId: safeProjectId, sessionId },\n }),\n [apiEndpoint, apiKey, safeProjectId, sessionId]\n );\n\n const {\n messages,\n sendMessage: sdkSendMessage,\n status: sdkStatus,\n error,\n stop,\n setMessages,\n } = useChat({\n id: sessionId,\n messages: initialMessages as never,\n transport,\n onFinish: (message) => {\n callbacksRef.current?.onMessageReceived?.(message as unknown as ChatMessage);\n },\n onError: (err) => {\n callbacksRef.current?.onError?.(err);\n },\n });\n\n const status: ChatStatus = error\n ? \"error\"\n : sdkStatus === \"streaming\" || sdkStatus === \"submitted\"\n ? \"streaming\"\n : \"idle\";\n\n // Persist messages\n useEffect(() => {\n if (shouldPersist) persistMessages(safeProjectId, messages);\n }, [messages, safeProjectId, shouldPersist]);\n\n // Derive active tools from the latest assistant message\n const activeTools = useMemo<ActiveTool[]>(() => {\n if (messages.length === 0) return [];\n const last = messages[messages.length - 1] as { role: string; parts?: unknown[] };\n if (last.role !== \"assistant\" || !Array.isArray(last.parts)) return [];\n return (last.parts as Array<Record<string, unknown>>)\n .filter((p) => typeof p.type === \"string\" && (p.type as string).startsWith(\"tool-\"))\n .map((p) => ({\n toolName: (p.toolName as string) || (p.type as string).replace(\"tool-\", \"\"),\n state: (p.state as ActiveTool[\"state\"]) || \"output-available\",\n args: (p.args as Record<string, unknown>) || {},\n result: p.result,\n renderMode: (p.renderMode as string) || \"inline\",\n }));\n }, [messages]);\n\n const sendMessage = useCallback(\n (content: string) => {\n if (!content.trim()) return;\n callbacksRef.current?.onMessageSent?.({\n id: crypto.randomUUID(),\n role: \"user\",\n content,\n } as ChatMessage);\n sdkSendMessage({ text: content });\n },\n [sdkSendMessage]\n );\n\n const stopGeneration = useCallback(() => stop(), [stop]);\n\n const newConversation = useCallback(() => {\n setMessages([]);\n clearPersistedMessages(safeProjectId);\n if (typeof window !== \"undefined\") {\n try {\n sessionStorage.removeItem(SESSION_KEY_PREFIX + safeProjectId);\n } catch {\n // Ignore.\n }\n }\n setSessionId(getOrCreateSessionId(safeProjectId));\n }, [safeProjectId, setMessages]);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n clearPersistedMessages(safeProjectId);\n }, [safeProjectId, setMessages]);\n\n // --- Live Chat (self-contained) ---\n const [lcState, setLcState] = useState<LiveChatState>(\"ai\");\n const [lcMessages, setLcMessages] = useState<LiveChatMessage[]>([]);\n const [lcOperator, setLcOperator] = useState(\"\");\n const [lcQueue, setLcQueue] = useState(0);\n const [lcShowIdentity, setLcShowIdentity] = useState(false);\n const lcTransportRef = useRef<LiveChatTransport | null>(null);\n\n const lcResetState = useCallback(() => {\n lcTransportRef.current?.disconnect?.();\n lcTransportRef.current = null;\n setLcState(\"ai\");\n setLcMessages([]);\n setLcOperator(\"\");\n setLcQueue(0);\n setLcShowIdentity(false);\n }, []);\n\n const lcInitiate = useCallback(\n async (visitorName?: string, visitorEmail?: string) => {\n if (!enableLiveChat || lcTransportRef.current) return;\n const url = chatServiceUrl ?? apiEndpoint;\n if (!url || !apiKey) return;\n try {\n const transport = new LiveChatTransport({\n chatServiceUrl: url,\n apiKey,\n projectId: safeProjectId,\n visitorSessionId: sessionId,\n });\n transport.on(\"state-change\", (s: LiveChatState) => setLcState(s));\n transport.on(\"queued\", (data: { position: number }) => setLcQueue(data.position));\n transport.on(\"queue-update\", (data: { position: number }) => setLcQueue(data.position));\n transport.on(\"accepted\", (data: { operatorName: string }) => setLcOperator(data.operatorName));\n transport.on(\"message\", (data: LiveChatMessage) =>\n setLcMessages((prev) => [...prev, data])\n );\n transport.on(\"ended\", () => setLcState(\"ended\"));\n lcTransportRef.current = transport;\n await transport.connect();\n await transport.requestHandoff({\n visitorName,\n visitorEmail,\n aiChatHistory: [],\n });\n callbacksRef.current?.onLiveChatRequested?.();\n } catch (err) {\n callbacksRef.current?.onError?.(err as Error);\n setLcState(\"ai\");\n }\n },\n [enableLiveChat, chatServiceUrl, apiEndpoint, apiKey, safeProjectId, sessionId]\n );\n\n const liveChat = useMemo<LiveChatReturn>(\n () => ({\n state: lcState,\n messages: lcMessages,\n operatorName: lcOperator,\n queuePosition: lcQueue,\n showIdentityForm: lcShowIdentity,\n initiate: lcInitiate,\n send: (content: string) => {\n if (!content.trim()) return;\n lcTransportRef.current?.sendMessage?.(content);\n setLcMessages((prev) => [\n ...prev,\n {\n id: Date.now(),\n content,\n senderType: \"visitor\",\n timestamp: new Date().toISOString(),\n },\n ]);\n },\n end: () => lcTransportRef.current?.endChat?.(),\n cancel: () => lcResetState(),\n submitRating: (rating, comment) =>\n lcTransportRef.current?.submitRating?.(rating, comment),\n returnToAI: () => lcResetState(),\n requestManualHandoff: () => setLcShowIdentity(true),\n setShowIdentityForm: setLcShowIdentity,\n }),\n [lcState, lcMessages, lcOperator, lcQueue, lcShowIdentity, lcInitiate, lcResetState]\n );\n\n return {\n messages: messages as unknown as ChatMessage[],\n status,\n error: error as Error | undefined,\n sessionId,\n sendMessage,\n stopGeneration,\n newConversation,\n clearMessages,\n activeTools,\n liveChat,\n chatRef,\n };\n}\n"]}
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { cn } from './chunk-3RW7O444.js';
3
+ import { Loader2Icon } from 'lucide-react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ function Spinner({ className, style, ...props }) {
7
+ return /* @__PURE__ */ jsx(
8
+ Loader2Icon,
9
+ {
10
+ role: "status",
11
+ "aria-label": "Loading",
12
+ className: cn("size-4 animate-spin", className),
13
+ style: { color: "var(--loader-color, var(--primary, currentColor))", ...style },
14
+ ...props
15
+ }
16
+ );
17
+ }
18
+
19
+ export { Spinner };
20
+ //# sourceMappingURL=chunk-4QT25AXI.js.map
21
+ //# sourceMappingURL=chunk-4QT25AXI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/spinner.tsx"],"names":[],"mappings":";;;;AAMA,SAAS,QAAQ,EAAE,SAAA,EAAW,KAAA,EAAO,GAAG,OAAM,EAAgC;AAC5E,EAAA,uBACE,GAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAW,SAAA;AAAA,MACX,SAAA,EAAW,EAAA,CAAG,qBAAA,EAAuB,SAAS,CAAA;AAAA,MAC9C,KAAA,EAAO,EAAE,KAAA,EAAO,mDAAA,EAAqD,GAAG,KAAA,EAAM;AAAA,MAC7E,GAAG;AAAA;AAAA,GACN;AAEJ","file":"chunk-4QT25AXI.js","sourcesContent":["\"use client\";\n\nimport { Loader2Icon } from \"lucide-react\"\n\nimport { cn } from \"../core/utils\"\n\nfunction Spinner({ className, style, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <Loader2Icon\n role=\"status\"\n aria-label=\"Loading\"\n className={cn(\"size-4 animate-spin\", className)}\n style={{ color: \"var(--loader-color, var(--primary, currentColor))\", ...style }}\n {...props}\n />\n )\n}\n\nexport { Spinner }\n"]}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var clsx = require('clsx');
5
+ var tailwindMerge = require('tailwind-merge');
6
+
7
+ // src/core/utils.ts
8
+ function cn(...inputs) {
9
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
10
+ }
11
+ function addUtmParams(url) {
12
+ if (isSsr()) return url;
13
+ try {
14
+ const urlObj = new URL(url);
15
+ urlObj.searchParams.set("utm_source", "chat");
16
+ urlObj.searchParams.set("utm_medium", "referral");
17
+ return urlObj.toString();
18
+ } catch {
19
+ return url;
20
+ }
21
+ }
22
+ function isSsr() {
23
+ return typeof window === "undefined";
24
+ }
25
+
26
+ exports.addUtmParams = addUtmParams;
27
+ exports.cn = cn;
28
+ exports.isSsr = isSsr;
29
+ //# sourceMappingURL=chunk-525KS5HM.cjs.map
30
+ //# sourceMappingURL=chunk-525KS5HM.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/utils.ts"],"names":["twMerge","clsx"],"mappings":";;;;;;AAcO,SAAS,MAAM,MAAA,EAA8B;AAClD,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;AAUO,SAAS,aAAa,GAAA,EAAqB;AAChD,EAAA,IAAI,KAAA,IAAS,OAAO,GAAA;AACpB,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,MAAA,CAAO,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,MAAM,CAAA;AAC5C,IAAA,MAAA,CAAO,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,UAAU,CAAA;AAChD,IAAA,OAAO,OAAO,QAAA,EAAS;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AAMO,SAAS,KAAA,GAAiB;AAC/B,EAAA,OAAO,OAAO,MAAA,KAAW,WAAA;AAC3B","file":"chunk-525KS5HM.cjs","sourcesContent":["\"use client\";\n\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge Tailwind CSS class names with conflict resolution.\n *\n * Combines `clsx` (conditional classes) with `tailwind-merge` (deduplication).\n *\n * @example\n * cn(\"px-2 py-1\", condition && \"bg-red-500\", \"px-4\")\n * // → \"py-1 px-4 bg-red-500\" (px-2 is overridden by px-4)\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n\n/**\n * Append UTM parameters to a URL for analytics tracking.\n *\n * If the URL is malformed, it is returned unchanged.\n *\n * @param url - The target URL\n * @returns The URL with `utm_source=chat` and `utm_medium=referral` appended\n */\nexport function addUtmParams(url: string): string {\n if (isSsr()) return url;\n try {\n const urlObj = new URL(url);\n urlObj.searchParams.set(\"utm_source\", \"chat\");\n urlObj.searchParams.set(\"utm_medium\", \"referral\");\n return urlObj.toString();\n } catch {\n return url;\n }\n}\n\n/**\n * Returns `true` when running in a server-side rendering context\n * (i.e. `window` is not available).\n */\nexport function isSsr(): boolean {\n return typeof window === \"undefined\";\n}\n"]}
@@ -0,0 +1,299 @@
1
+ "use client";
2
+ import { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ // src/providers/LiveChatProvider.tsx
6
+ var LiveChatContext = createContext(null);
7
+ function LiveChatProvider({
8
+ children,
9
+ chatServiceUrl,
10
+ apiKey,
11
+ projectId,
12
+ sessionId,
13
+ userInfo
14
+ }) {
15
+ const [state, setState] = useState("ai");
16
+ const [messages, setMessages] = useState([]);
17
+ const [operatorName, setOperatorName] = useState("");
18
+ const [queuePosition, setQueuePosition] = useState(0);
19
+ const [showIdentityForm, setShowIdentityForm] = useState(false);
20
+ const transportRef = useRef(null);
21
+ const aiHistoryGetterRef = useRef(null);
22
+ const STORAGE_KEY = `livechat-session-${projectId}`;
23
+ const registerAiHistoryGetter = useCallback(
24
+ (getter) => {
25
+ aiHistoryGetterRef.current = getter;
26
+ },
27
+ []
28
+ );
29
+ const resetState = useCallback(() => {
30
+ transportRef.current?.disconnect?.();
31
+ transportRef.current = null;
32
+ setState("ai");
33
+ setMessages([]);
34
+ setOperatorName("");
35
+ setQueuePosition(0);
36
+ setShowIdentityForm(false);
37
+ if (typeof window !== "undefined") {
38
+ try {
39
+ sessionStorage.removeItem(STORAGE_KEY);
40
+ } catch {
41
+ }
42
+ }
43
+ }, [STORAGE_KEY]);
44
+ const persistSession = useCallback(
45
+ (liveChatSessionId) => {
46
+ if (typeof window === "undefined") return;
47
+ try {
48
+ sessionStorage.setItem(STORAGE_KEY, liveChatSessionId);
49
+ } catch {
50
+ }
51
+ },
52
+ [STORAGE_KEY]
53
+ );
54
+ const attachListeners = useCallback(
55
+ (transport) => {
56
+ transport.on("state-change", setState);
57
+ transport.on("queued", (data) => {
58
+ setQueuePosition(data.position);
59
+ if (data.liveChatSessionId) persistSession(data.liveChatSessionId);
60
+ });
61
+ transport.on(
62
+ "queue-update",
63
+ (data) => setQueuePosition(data.position)
64
+ );
65
+ transport.on(
66
+ "accepted",
67
+ (data) => setOperatorName(data.operatorName)
68
+ );
69
+ transport.on(
70
+ "message",
71
+ (data) => setMessages((prev) => [...prev, data])
72
+ );
73
+ transport.on("system", (data) => {
74
+ setMessages((prev) => [
75
+ ...prev,
76
+ {
77
+ id: Date.now(),
78
+ content: data.message,
79
+ senderType: "system",
80
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
81
+ systemMessageType: data.type
82
+ }
83
+ ]);
84
+ });
85
+ transport.on("ended", () => setState("ended"));
86
+ transport.on("handback-ai", () => resetState());
87
+ },
88
+ [persistSession, resetState]
89
+ );
90
+ useEffect(() => {
91
+ if (typeof window === "undefined") return;
92
+ let cancelled = false;
93
+ const storedSessionId = (() => {
94
+ try {
95
+ return sessionStorage.getItem(STORAGE_KEY);
96
+ } catch {
97
+ return null;
98
+ }
99
+ })();
100
+ if (!storedSessionId || transportRef.current) return;
101
+ async function rejoin() {
102
+ const { LiveChatTransport } = await import('./live-chat-transport-4XLOIPOE.js');
103
+ if (cancelled || !LiveChatTransport) return;
104
+ const transportConfig = {
105
+ chatServiceUrl,
106
+ apiKey,
107
+ projectId,
108
+ visitorSessionId: sessionId
109
+ };
110
+ const transport = new LiveChatTransport(transportConfig);
111
+ attachListeners(transport);
112
+ transport.on("rejoin-success", (data) => {
113
+ if (cancelled) return;
114
+ if (data.state === "live") {
115
+ setState("live");
116
+ setOperatorName(data.operatorName || "Operator");
117
+ } else if (data.state === "queued") {
118
+ setState("queued");
119
+ setQueuePosition(data.position || 1);
120
+ }
121
+ if (data.messages?.length) {
122
+ setMessages(data.messages);
123
+ }
124
+ });
125
+ transport.on("rejoin-failed", () => {
126
+ if (cancelled) return;
127
+ if (typeof window !== "undefined") {
128
+ try {
129
+ sessionStorage.removeItem(STORAGE_KEY);
130
+ } catch {
131
+ }
132
+ }
133
+ transport.disconnect?.();
134
+ transportRef.current = null;
135
+ });
136
+ transportRef.current = transport;
137
+ await transport.connect();
138
+ transport.rejoinSession(storedSessionId);
139
+ }
140
+ rejoin().catch(() => {
141
+ if (typeof window !== "undefined") {
142
+ try {
143
+ sessionStorage.removeItem(STORAGE_KEY);
144
+ } catch {
145
+ }
146
+ }
147
+ });
148
+ return () => {
149
+ cancelled = true;
150
+ };
151
+ }, []);
152
+ const initiate = useCallback(
153
+ async (visitorName, visitorEmail) => {
154
+ if (transportRef.current) return;
155
+ try {
156
+ const { LiveChatTransport } = await import('./live-chat-transport-4XLOIPOE.js');
157
+ if (!LiveChatTransport) {
158
+ console.error("[LiveChat] LiveChatTransport not available");
159
+ return;
160
+ }
161
+ const transportConfig = {
162
+ chatServiceUrl,
163
+ apiKey,
164
+ projectId,
165
+ visitorSessionId: sessionId
166
+ };
167
+ const transport = new LiveChatTransport(transportConfig);
168
+ attachListeners(transport);
169
+ transportRef.current = transport;
170
+ await transport.connect();
171
+ transport.requestHandoff({
172
+ visitorName,
173
+ visitorEmail,
174
+ aiChatHistory: aiHistoryGetterRef.current?.() || []
175
+ });
176
+ } catch (error) {
177
+ console.error("[LiveChat] Failed to initiate:", error);
178
+ setState("ai");
179
+ }
180
+ },
181
+ [chatServiceUrl, apiKey, projectId, sessionId, attachListeners]
182
+ );
183
+ const cancel = useCallback(() => {
184
+ const sid = transportRef.current?.getSessionId?.();
185
+ if (sid) transportRef.current?.cancelRequest?.(sid);
186
+ resetState();
187
+ }, [resetState]);
188
+ const end = useCallback(() => {
189
+ transportRef.current?.endChat?.();
190
+ }, []);
191
+ const send = useCallback((content) => {
192
+ if (!content.trim()) return;
193
+ transportRef.current?.sendMessage?.(content);
194
+ setMessages((prev) => [
195
+ ...prev,
196
+ {
197
+ id: Date.now(),
198
+ content,
199
+ senderType: "visitor",
200
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
201
+ }
202
+ ]);
203
+ }, []);
204
+ const submitRating = useCallback(
205
+ (rating, comment) => {
206
+ transportRef.current?.submitRating?.(rating, comment);
207
+ },
208
+ []
209
+ );
210
+ const returnToAI = useCallback(() => {
211
+ resetState();
212
+ }, [resetState]);
213
+ const requestManualHandoff = useCallback(() => {
214
+ setShowIdentityForm(true);
215
+ }, []);
216
+ const value = useMemo(
217
+ () => ({
218
+ state,
219
+ messages,
220
+ operatorName,
221
+ queuePosition,
222
+ showIdentityForm,
223
+ initiate,
224
+ send,
225
+ end,
226
+ cancel,
227
+ submitRating,
228
+ returnToAI,
229
+ requestManualHandoff,
230
+ setShowIdentityForm,
231
+ registerAiHistoryGetter,
232
+ userInfo
233
+ }),
234
+ [
235
+ state,
236
+ messages,
237
+ operatorName,
238
+ queuePosition,
239
+ showIdentityForm,
240
+ initiate,
241
+ send,
242
+ end,
243
+ cancel,
244
+ submitRating,
245
+ returnToAI,
246
+ requestManualHandoff,
247
+ registerAiHistoryGetter,
248
+ userInfo
249
+ ]
250
+ );
251
+ return /* @__PURE__ */ jsx(LiveChatContext.Provider, { value, children });
252
+ }
253
+ function useLiveChat() {
254
+ return useContext(LiveChatContext);
255
+ }
256
+ var PreviewEmbedContext = createContext(null);
257
+ function PreviewEmbedProvider({ children }) {
258
+ const [preview, setPreview] = useState(null);
259
+ const openPreview = useCallback(
260
+ (info) => setPreview(info),
261
+ []
262
+ );
263
+ const closePreview = useCallback(() => setPreview(null), []);
264
+ const value = useMemo(
265
+ () => ({ preview, openPreview, closePreview }),
266
+ [preview, openPreview, closePreview]
267
+ );
268
+ return /* @__PURE__ */ jsx(PreviewEmbedContext.Provider, { value, children });
269
+ }
270
+ function usePreviewEmbed() {
271
+ return useContext(PreviewEmbedContext);
272
+ }
273
+ var MOBILE_BREAKPOINT = 768;
274
+ var getIsMobile = () => typeof window !== "undefined" && window.innerWidth < MOBILE_BREAKPOINT;
275
+ function useIsMobile() {
276
+ const [isMobile, setIsMobile] = useState(getIsMobile);
277
+ const initialWidthRef = useRef(null);
278
+ useEffect(() => {
279
+ if (typeof window === "undefined") return;
280
+ if (initialWidthRef.current === null) {
281
+ initialWidthRef.current = window.innerWidth;
282
+ }
283
+ const checkMobile = () => {
284
+ const currentWidth = window.innerWidth;
285
+ const widthCrossedBreakpoint = currentWidth < MOBILE_BREAKPOINT !== initialWidthRef.current < MOBILE_BREAKPOINT || Math.abs(currentWidth - initialWidthRef.current) > 100;
286
+ if (widthCrossedBreakpoint) {
287
+ initialWidthRef.current = currentWidth;
288
+ setIsMobile(currentWidth < MOBILE_BREAKPOINT);
289
+ }
290
+ };
291
+ window.addEventListener("resize", checkMobile);
292
+ return () => window.removeEventListener("resize", checkMobile);
293
+ }, []);
294
+ return isMobile;
295
+ }
296
+
297
+ export { LiveChatProvider, PreviewEmbedProvider, useIsMobile, useLiveChat, usePreviewEmbed };
298
+ //# sourceMappingURL=chunk-5F3O3ZJH.js.map
299
+ //# sourceMappingURL=chunk-5F3O3ZJH.js.map