@agentcrafta/chat-next 0.0.3 → 0.0.5

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.
@@ -0,0 +1,68 @@
1
+ // src/server/actions.ts
2
+ import "@agentcrafta/core";
3
+ var getRegionalSettings = async (tokenEndpoint) => {
4
+ if (!tokenEndpoint || tokenEndpoint.trim() === "") {
5
+ throw new Error("Token endpoint no configurado");
6
+ }
7
+ const environmentEndPoint = tokenEndpoint.slice(
8
+ 0,
9
+ tokenEndpoint.indexOf("/powervirtualagents")
10
+ );
11
+ const regex = /api-version=([^&]+)/;
12
+ const apiVersionMatch = regex.exec(tokenEndpoint);
13
+ const apiVersion = apiVersionMatch ? apiVersionMatch[1] : "2022-03-01-preview";
14
+ const regionalChannelSettingsURL = `${environmentEndPoint}/powervirtualagents/regionalchannelsettings?api-version=${apiVersion}`;
15
+ const response = await fetch(regionalChannelSettingsURL);
16
+ if (!response.ok) {
17
+ throw new Error(`Error ${response.status}: ${response.statusText}`);
18
+ }
19
+ const data = await response.json();
20
+ return data;
21
+ };
22
+ var getConversationToken = async (tokenEndpoint) => {
23
+ if (!tokenEndpoint || tokenEndpoint.trim() === "") {
24
+ throw new Error("Token endpoint no configurado");
25
+ }
26
+ const conversationResponse = await fetch(tokenEndpoint);
27
+ if (!conversationResponse.ok) {
28
+ throw new Error(
29
+ `Error al obtener token: ${conversationResponse.status} ${conversationResponse.statusText}`
30
+ );
31
+ }
32
+ const conversationInfo = await conversationResponse.json();
33
+ if (!conversationInfo.token)
34
+ throw new Error("Token no encontrado en la respuesta");
35
+ return conversationInfo.token;
36
+ };
37
+ var getChatStoreConfig = async () => {
38
+ const config = {
39
+ initialState: {},
40
+ eventConfig: {
41
+ startConversation: {
42
+ channelData: { postBack: true },
43
+ name: "startConversation",
44
+ type: "event"
45
+ }
46
+ },
47
+ filterConfig: {
48
+ enableTraceFilter: true,
49
+ traceErrorMessage: "Error de conectividad"
50
+ }
51
+ };
52
+ return config;
53
+ };
54
+ var logChatError = async (input) => {
55
+ console.error("[Chat Error]:", {
56
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
57
+ ...input
58
+ });
59
+ return { logged: true };
60
+ };
61
+
62
+ export {
63
+ getRegionalSettings,
64
+ getConversationToken,
65
+ getChatStoreConfig,
66
+ logChatError
67
+ };
68
+ //# sourceMappingURL=chunk-Y2JYBEV6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server/actions.ts"],"sourcesContent":["\"use server\";\r\n\r\nimport { type LogChatErrorInput } from \"@agentcrafta/core\";\r\n\r\n//#region Inicializar Chat\r\nexport const getRegionalSettings = async (tokenEndpoint?: string) => {\r\n if (!tokenEndpoint || tokenEndpoint.trim() === \"\") {\r\n throw new Error(\"Token endpoint no configurado\");\r\n }\r\n const environmentEndPoint = tokenEndpoint.slice(\r\n 0,\r\n tokenEndpoint.indexOf(\"/powervirtualagents\"),\r\n );\r\n const regex = /api-version=([^&]+)/;\r\n const apiVersionMatch = regex.exec(tokenEndpoint);\r\n const apiVersion = apiVersionMatch\r\n ? apiVersionMatch[1]\r\n : \"2022-03-01-preview\";\r\n\r\n const regionalChannelSettingsURL = `${environmentEndPoint}/powervirtualagents/regionalchannelsettings?api-version=${apiVersion}`;\r\n const response = await fetch(regionalChannelSettingsURL);\r\n if (!response.ok) {\r\n throw new Error(`Error ${response.status}: ${response.statusText}`);\r\n }\r\n const data = await response.json();\r\n return data;\r\n};\r\n\r\nexport const getConversationToken = async (\r\n tokenEndpoint?: string,\r\n): Promise<string> => {\r\n if (!tokenEndpoint || tokenEndpoint.trim() === \"\") {\r\n throw new Error(\"Token endpoint no configurado\");\r\n }\r\n const conversationResponse = await fetch(tokenEndpoint);\r\n if (!conversationResponse.ok) {\r\n throw new Error(\r\n `Error al obtener token: ${conversationResponse.status} ${conversationResponse.statusText}`,\r\n );\r\n }\r\n const conversationInfo = await conversationResponse.json();\r\n if (!conversationInfo.token)\r\n throw new Error(\"Token no encontrado en la respuesta\");\r\n return conversationInfo.token;\r\n};\r\n//#endregion\r\n\r\n//#region Configuración Store Chat\r\nexport const getChatStoreConfig = async () => {\r\n const config = {\r\n initialState: {},\r\n eventConfig: {\r\n startConversation: {\r\n channelData: { postBack: true },\r\n name: \"startConversation\",\r\n type: \"event\",\r\n },\r\n },\r\n filterConfig: {\r\n enableTraceFilter: true,\r\n traceErrorMessage: \"Error de conectividad\",\r\n },\r\n };\r\n return config;\r\n};\r\n//#endregion\r\n\r\n//#region Log de errores del chat\r\nexport const logChatError = async (input: LogChatErrorInput) => {\r\n // Registrar errores en el servidor\r\n console.error(\"[Chat Error]:\", {\r\n timestamp: new Date().toISOString(),\r\n ...input,\r\n });\r\n\r\n // Aquí podrías guardar en base de datos, enviar a servicio de logging, etc.\r\n\r\n return { logged: true };\r\n};\r\n"],"mappings":";AAEA,OAAuC;AAGhC,IAAM,sBAAsB,OAAO,kBAA2B;AACnE,MAAI,CAAC,iBAAiB,cAAc,KAAK,MAAM,IAAI;AACjD,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,QAAM,sBAAsB,cAAc;AAAA,IACxC;AAAA,IACA,cAAc,QAAQ,qBAAqB;AAAA,EAC7C;AACA,QAAM,QAAQ;AACd,QAAM,kBAAkB,MAAM,KAAK,aAAa;AAChD,QAAM,aAAa,kBACf,gBAAgB,CAAC,IACjB;AAEJ,QAAM,6BAA6B,GAAG,mBAAmB,2DAA2D,UAAU;AAC9H,QAAM,WAAW,MAAM,MAAM,0BAA0B;AACvD,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,SAAS,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,EACpE;AACA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,SAAO;AACT;AAEO,IAAM,uBAAuB,OAClC,kBACoB;AACpB,MAAI,CAAC,iBAAiB,cAAc,KAAK,MAAM,IAAI;AACjD,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,QAAM,uBAAuB,MAAM,MAAM,aAAa;AACtD,MAAI,CAAC,qBAAqB,IAAI;AAC5B,UAAM,IAAI;AAAA,MACR,2BAA2B,qBAAqB,MAAM,IAAI,qBAAqB,UAAU;AAAA,IAC3F;AAAA,EACF;AACA,QAAM,mBAAmB,MAAM,qBAAqB,KAAK;AACzD,MAAI,CAAC,iBAAiB;AACpB,UAAM,IAAI,MAAM,qCAAqC;AACvD,SAAO,iBAAiB;AAC1B;AAIO,IAAM,qBAAqB,YAAY;AAC5C,QAAM,SAAS;AAAA,IACb,cAAc,CAAC;AAAA,IACf,aAAa;AAAA,MACX,mBAAmB;AAAA,QACjB,aAAa,EAAE,UAAU,KAAK;AAAA,QAC9B,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,cAAc;AAAA,MACZ,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,IACrB;AAAA,EACF;AACA,SAAO;AACT;AAIO,IAAM,eAAe,OAAO,UAA6B;AAE9D,UAAQ,MAAM,iBAAiB;AAAA,IAC7B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,GAAG;AAAA,EACL,CAAC;AAID,SAAO,EAAE,QAAQ,KAAK;AACxB;","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { WebChatLib, StyleOptions } from '@agentcrafta/core';
3
- export { C as ChatServer } from './chat-server-DoG_Rvk7.js';
4
3
 
5
4
  declare global {
6
5
  interface Window {
@@ -12,6 +11,7 @@ type ChatProps = {
12
11
  botName?: string;
13
12
  logoUrl?: string;
14
13
  styleOptions?: Partial<StyleOptions>;
14
+ entryPoint: string;
15
15
  };
16
16
  /**
17
17
  * @description Componente de chat para interactuar con un agente virtual utilizando Bot Framework Web Chat. Permite iniciar y reiniciar conversaciones, y se adapta a la configuración de estilo definida en el hook useChat.
@@ -19,15 +19,9 @@ type ChatProps = {
19
19
  * @param logoUrl URL del logo a mostrar junto al nombre del bot (opcional)
20
20
  * @param show Indica si el chat debe mostrarse o no (por defecto es true)
21
21
  * @param styleOptions: StyleOptions Opciones de estilo personalizadas para el chat (opcional)
22
+ * @param entryPoint Punto de entrada para la conversación (opcional)
22
23
  * @returns
23
24
  */
24
- declare const Chat: ({ botName, show, logoUrl, styleOptions, }: ChatProps) => react_jsx_runtime.JSX.Element | null;
25
+ declare const Chat: ({ botName, show, logoUrl, styleOptions, entryPoint, }: ChatProps) => react_jsx_runtime.JSX.Element | null;
25
26
 
26
- /**
27
- * Convierte una variable CSS (ej: "var(--primary)") a su equivalente en formato hex
28
- * @param cssVar - String en formato "var(--variable-name)"
29
- * @returns Color en formato hex (ej: "#0078d4") o el valor original si no se puede convertir
30
- */
31
- declare const getCssVariableAsHex: (cssVar: string) => string;
32
-
33
- export { Chat, getCssVariableAsHex };
27
+ export { Chat };
package/dist/index.js CHANGED
@@ -1,45 +1,344 @@
1
1
  import {
2
- Chat,
3
- ChatServer
4
- } from "./chunk-MOTD6MKH.js";
2
+ getChatStoreConfig,
3
+ getConversationToken,
4
+ getRegionalSettings,
5
+ logChatError
6
+ } from "./chunk-Y2JYBEV6.js";
5
7
 
6
- // src/shared/utils/utils.ts
7
- var getCssVariableAsHex = (cssVar) => {
8
- if (!cssVar.startsWith("var(--")) {
9
- return cssVar;
10
- }
11
- const variableName = cssVar.slice(4, -1);
12
- try {
13
- const cssValue = getComputedStyle(document.documentElement).getPropertyValue(variableName).trim();
14
- if (!cssValue) {
15
- console.warn(`Variable CSS ${variableName} no encontrada`);
16
- return cssVar;
8
+ // src/client/chat.tsx
9
+ import React2 from "react";
10
+
11
+ // src/client/use-chat.ts
12
+ import React from "react";
13
+ import {
14
+ TypeDispatch,
15
+ styleOptionsBase
16
+ } from "@agentcrafta/core";
17
+ var useChat = (styleOptionsProps, entryPoint) => {
18
+ const [isVisible, setIsVisible] = React.useState(false);
19
+ const [isRestarting, setIsRestarting] = React.useState(false);
20
+ const [chatKey, setChatKey] = React.useState(Date.now());
21
+ const webChatRef = React.useRef(null);
22
+ const webChatInstanceRef = React.useRef(null);
23
+ const directLineUrlRef = React.useRef(null);
24
+ const isInitializedRef = React.useRef(false);
25
+ const styleOptionsMerged = { ...styleOptionsBase, ...styleOptionsProps };
26
+ const handleChangeVisibility = (visible) => {
27
+ setIsVisible(visible);
28
+ };
29
+ const createCustomStore = async () => {
30
+ const configResult = await getChatStoreConfig();
31
+ const { eventConfig, filterConfig, initialState } = configResult ?? {};
32
+ return globalThis.window.WebChat.createStore(
33
+ initialState || {},
34
+ ({ dispatch }) => (next) => (action) => {
35
+ if (action.type === TypeDispatch.CONNECTED_FULFILLED) {
36
+ dispatch({
37
+ type: TypeDispatch.POST_ACTIVITY,
38
+ meta: { method: "keyboard" },
39
+ payload: {
40
+ activity: eventConfig?.startConversation || {
41
+ channelData: { postBack: true },
42
+ name: "startConversation",
43
+ type: "event"
44
+ }
45
+ }
46
+ });
47
+ }
48
+ if (action.type === TypeDispatch.INCOMING_ACTIVITY && action.payload?.activity?.type === "trace") {
49
+ const errorMessage = filterConfig?.traceErrorMessage || "Error de conectividad";
50
+ console.error(errorMessage);
51
+ logChatError({
52
+ errorType: "trace_activity",
53
+ errorMessage: "Trace activity filtered",
54
+ actionType: action.type
55
+ });
56
+ return action;
57
+ }
58
+ return next(action);
59
+ }
60
+ );
61
+ };
62
+ const restartConversation = async () => {
63
+ if (isRestarting) return;
64
+ try {
65
+ setIsRestarting(true);
66
+ isInitializedRef.current = false;
67
+ webChatInstanceRef.current = null;
68
+ setChatKey(Date.now());
69
+ } catch (err) {
70
+ const errorMessage = err instanceof Error ? err.message : "Error desconocido";
71
+ console.error("Error al reiniciar conversaci\xF3n:", errorMessage);
72
+ logChatError({
73
+ errorType: "restart_conversation",
74
+ errorMessage,
75
+ actionType: "Error reiniciando conversaci\xF3n"
76
+ });
77
+ } finally {
78
+ setIsRestarting(false);
79
+ }
80
+ };
81
+ const initializeChat = async () => {
82
+ if (isInitializedRef.current) return;
83
+ try {
84
+ const data = await getRegionalSettings(entryPoint);
85
+ directLineUrlRef.current = data.channelUrlsById.directline;
86
+ if (!directLineUrlRef.current) {
87
+ logChatError({
88
+ errorType: "initialize_chat",
89
+ errorMessage: "DirectLine URL not found in regional settings",
90
+ actionType: "Error inicializando chat"
91
+ });
92
+ console.error("No se pudo obtener la URL de DirectLine");
93
+ return;
94
+ }
95
+ const token = await getConversationToken(entryPoint);
96
+ const directLine = globalThis.window.WebChat.createDirectLine({
97
+ domain: `${directLineUrlRef.current}v3/directline`,
98
+ token
99
+ });
100
+ if (webChatRef.current && !isInitializedRef.current) {
101
+ const store = await createCustomStore();
102
+ webChatInstanceRef.current = globalThis.window.WebChat.renderWebChat(
103
+ {
104
+ directLine,
105
+ styleOptions: styleOptionsMerged,
106
+ store
107
+ },
108
+ webChatRef.current
109
+ );
110
+ isInitializedRef.current = true;
111
+ }
112
+ } catch (err) {
113
+ const errorMessage = err instanceof Error ? err.message : "Error desconocido";
114
+ console.error("Error detallado al inicializar el chat:", err);
115
+ logChatError({
116
+ errorType: "initialize_chat",
117
+ errorMessage,
118
+ actionType: "Error inicializando chat"
119
+ });
17
120
  }
18
- const hslValue = `hsl(${cssValue})`;
19
- return hslToHex(hslValue);
20
- } catch (error) {
21
- console.error(`Error al convertir variable CSS ${cssVar}:`, error);
22
- return cssVar;
23
- }
121
+ };
122
+ const cleanup = () => {
123
+ isInitializedRef.current = false;
124
+ webChatInstanceRef.current = null;
125
+ };
126
+ return {
127
+ isVisible,
128
+ isRestarting,
129
+ chatKey,
130
+ webChatRef,
131
+ styleOptionsMerged,
132
+ handleChangeVisibility,
133
+ initializeChat,
134
+ restartConversation,
135
+ cleanup
136
+ };
24
137
  };
25
- var hslToHex = (hsl) => {
26
- const tempDiv = document.createElement("div");
27
- tempDiv.style.color = hsl;
28
- document.body.appendChild(tempDiv);
29
- const computedColor = getComputedStyle(tempDiv).color;
30
- tempDiv.remove();
31
- const rgbMatch = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/.exec(computedColor);
32
- if (rgbMatch) {
33
- const r = rgbMatch[1] ?? "0";
34
- const g = rgbMatch[2] ?? "0";
35
- const b = rgbMatch[3] ?? "0";
36
- return `#${((1 << 24) + (Number.parseInt(r) << 16) + (Number.parseInt(g) << 8) + Number.parseInt(b)).toString(16).slice(1)}`;
37
- }
38
- return hsl;
138
+
139
+ // src/client/chat.tsx
140
+ import "@agentcrafta/core";
141
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
142
+ var Chat = ({
143
+ botName = "Agent",
144
+ show = true,
145
+ logoUrl,
146
+ styleOptions,
147
+ entryPoint
148
+ }) => {
149
+ const {
150
+ isVisible,
151
+ isRestarting,
152
+ chatKey,
153
+ webChatRef,
154
+ styleOptionsMerged,
155
+ initializeChat,
156
+ restartConversation,
157
+ cleanup,
158
+ handleChangeVisibility
159
+ } = useChat(styleOptions, entryPoint);
160
+ const scriptLoadedRef = React2.useRef(false);
161
+ React2.useEffect(() => {
162
+ if (!show) return;
163
+ const existingScript = document.querySelector(
164
+ 'script[src*="botframework-webchat"]'
165
+ );
166
+ if (existingScript || scriptLoadedRef.current) {
167
+ if (globalThis.window.WebChat) {
168
+ initializeChat();
169
+ }
170
+ return;
171
+ }
172
+ const script = document.createElement("script");
173
+ script.src = "https://cdn.botframework.com/botframework-webchat/latest/webchat.js";
174
+ script.async = true;
175
+ script.onload = () => {
176
+ scriptLoadedRef.current = true;
177
+ initializeChat();
178
+ };
179
+ script.onerror = () => {
180
+ console.error("Error al cargar el script de WebChat");
181
+ scriptLoadedRef.current = false;
182
+ };
183
+ document.head.appendChild(script);
184
+ return () => {
185
+ cleanup();
186
+ };
187
+ }, [chatKey]);
188
+ if (!show) return null;
189
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
190
+ /* @__PURE__ */ jsxs(
191
+ "div",
192
+ {
193
+ className: `fixed bottom-8 right-8 z-[999] h-[520px] w-[450px] origin-bottom-right overflow-hidden rounded-2xl bg-white shadow-2xl transition-all duration-300 ease-in-out ${isVisible ? "block scale-100 opacity-100" : "hidden scale-95 opacity-0"}`,
194
+ role: "complementary",
195
+ "aria-label": `Chat ${botName}`,
196
+ children: [
197
+ /* @__PURE__ */ jsxs(
198
+ "div",
199
+ {
200
+ className: "flex h-14 items-center justify-between bg-primary px-5 py-4 text-white",
201
+ style: { color: styleOptionsMerged.suggestedActionTextColor },
202
+ children: [
203
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-base font-medium", children: [
204
+ logoUrl && /* @__PURE__ */ jsx(
205
+ "img",
206
+ {
207
+ src: logoUrl,
208
+ alt: "Logo",
209
+ width: 24,
210
+ height: 24,
211
+ className: "h-7 w-7 rounded-sm"
212
+ }
213
+ ),
214
+ /* @__PURE__ */ jsx("span", { children: botName })
215
+ ] }),
216
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
217
+ /* @__PURE__ */ jsx(
218
+ "button",
219
+ {
220
+ className: `flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50 ${isRestarting ? "cursor-not-allowed opacity-50" : ""}`,
221
+ onClick: restartConversation,
222
+ disabled: isRestarting,
223
+ "aria-label": isRestarting ? "Restarting Conversation..." : "Restart Conversation",
224
+ style: { color: styleOptionsMerged.suggestedActionTextColor },
225
+ children: isRestarting ? /* @__PURE__ */ jsx(
226
+ "svg",
227
+ {
228
+ width: "20",
229
+ height: "20",
230
+ viewBox: "0 0 24 24",
231
+ fill: "none",
232
+ stroke: "currentColor",
233
+ strokeWidth: "2",
234
+ strokeLinecap: "round",
235
+ strokeLinejoin: "round",
236
+ "aria-hidden": "true",
237
+ className: "animate-spin",
238
+ children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
239
+ }
240
+ ) : /* @__PURE__ */ jsxs(
241
+ "svg",
242
+ {
243
+ width: "20",
244
+ height: "20",
245
+ viewBox: "0 0 24 24",
246
+ fill: "none",
247
+ stroke: "currentColor",
248
+ strokeWidth: "2",
249
+ strokeLinecap: "round",
250
+ strokeLinejoin: "round",
251
+ "aria-hidden": "true",
252
+ children: [
253
+ /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
254
+ /* @__PURE__ */ jsx("path", { d: "M3 3v5h5" })
255
+ ]
256
+ }
257
+ )
258
+ }
259
+ ),
260
+ /* @__PURE__ */ jsx(
261
+ "button",
262
+ {
263
+ className: "flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50",
264
+ onClick: () => handleChangeVisibility(false),
265
+ "aria-label": "Close Chat",
266
+ style: { color: styleOptionsMerged.suggestedActionTextColor },
267
+ children: /* @__PURE__ */ jsxs(
268
+ "svg",
269
+ {
270
+ width: "20",
271
+ height: "20",
272
+ viewBox: "0 0 24 24",
273
+ fill: "none",
274
+ stroke: "currentColor",
275
+ strokeWidth: "2",
276
+ strokeLinecap: "round",
277
+ strokeLinejoin: "round",
278
+ "aria-hidden": "true",
279
+ children: [
280
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
281
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
282
+ ]
283
+ }
284
+ )
285
+ }
286
+ )
287
+ ] })
288
+ ]
289
+ }
290
+ ),
291
+ /* @__PURE__ */ jsx(
292
+ "div",
293
+ {
294
+ className: "relative h-[calc(100%-56px)] bg-gray-50",
295
+ role: "main",
296
+ ref: webChatRef,
297
+ children: isRestarting && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-gray-50/80", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 text-gray-600", children: [
298
+ /* @__PURE__ */ jsx(
299
+ "svg",
300
+ {
301
+ className: "h-8 w-8 animate-spin",
302
+ viewBox: "0 0 24 24",
303
+ fill: "none",
304
+ stroke: "currentColor",
305
+ strokeWidth: "2",
306
+ children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
307
+ }
308
+ ),
309
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Reiniciando conversaci\xF3n..." })
310
+ ] }) })
311
+ },
312
+ chatKey
313
+ )
314
+ ]
315
+ }
316
+ ),
317
+ /* @__PURE__ */ jsx(
318
+ "button",
319
+ {
320
+ className: `focus:outline-3 fixed bottom-24 right-8 z-[998] flex h-16 w-16 cursor-pointer items-center justify-center rounded-full border-none bg-primary shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-1 hover:shadow-xl focus:outline focus:outline-offset-2 focus:outline-indigo-500/50 ${isVisible ? "pointer-events-none translate-y-2 scale-95 opacity-0" : "scale-100 opacity-100"}`,
321
+ onClick: () => handleChangeVisibility(true),
322
+ "aria-label": "Open Chat Assistant",
323
+ children: /* @__PURE__ */ jsx(
324
+ "svg",
325
+ {
326
+ className: "h-7 w-7 text-white transition-transform",
327
+ viewBox: "0 0 24 24",
328
+ fill: "none",
329
+ stroke: "currentColor",
330
+ strokeWidth: "2",
331
+ strokeLinecap: "round",
332
+ strokeLinejoin: "round",
333
+ "aria-hidden": "true",
334
+ children: /* @__PURE__ */ jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
335
+ }
336
+ )
337
+ }
338
+ )
339
+ ] });
39
340
  };
40
341
  export {
41
- Chat,
42
- ChatServer,
43
- getCssVariableAsHex
342
+ Chat
44
343
  };
45
344
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/utils/utils.ts"],"sourcesContent":["/**\r\n * Convierte una variable CSS (ej: \"var(--primary)\") a su equivalente en formato hex\r\n * @param cssVar - String en formato \"var(--variable-name)\"\r\n * @returns Color en formato hex (ej: \"#0078d4\") o el valor original si no se puede convertir\r\n */\r\nexport const getCssVariableAsHex = (cssVar: string): string => {\r\n // Si no es una variable CSS, devolver el valor original\r\n if (!cssVar.startsWith(\"var(--\")) {\r\n return cssVar;\r\n }\r\n\r\n // Extraer el nombre de la variable (ej: \"--primary\" de \"var(--primary)\")\r\n const variableName = cssVar.slice(4, -1); // Remover \"var(\" y \")\"\r\n\r\n try {\r\n // Obtener el valor de la variable CSS del documento\r\n const cssValue = getComputedStyle(document.documentElement)\r\n .getPropertyValue(variableName)\r\n .trim();\r\n\r\n if (!cssValue) {\r\n console.warn(`Variable CSS ${variableName} no encontrada`);\r\n return cssVar;\r\n }\r\n\r\n // Convertir HSL a hex (las variables están en formato \"204 97% 41%\")\r\n const hslValue = `hsl(${cssValue})`;\r\n return hslToHex(hslValue);\r\n } catch (error) {\r\n console.error(`Error al convertir variable CSS ${cssVar}:`, error);\r\n return cssVar;\r\n }\r\n};\r\n\r\n/**\r\n * Convierte un color HSL a formato hex\r\n * @param hsl - Color en formato \"hsl(h, s%, l%)\"\r\n * @returns Color en formato hex\r\n */\r\nconst hslToHex = (hsl: string): string => {\r\n const tempDiv = document.createElement(\"div\");\r\n tempDiv.style.color = hsl;\r\n document.body.appendChild(tempDiv);\r\n\r\n const computedColor = getComputedStyle(tempDiv).color;\r\n tempDiv.remove();\r\n\r\n // Convertir rgb a hex\r\n const rgbMatch = /rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)/.exec(computedColor);\r\n if (rgbMatch) {\r\n const r = rgbMatch[1] ?? \"0\";\r\n const g = rgbMatch[2] ?? \"0\";\r\n const b = rgbMatch[3] ?? \"0\";\r\n return `#${((1 << 24) + (Number.parseInt(r) << 16) + (Number.parseInt(g) << 8) + Number.parseInt(b)).toString(16).slice(1)}`;\r\n }\r\n\r\n return hsl;\r\n};\r\n"],"mappings":";;;;;;AAKO,IAAM,sBAAsB,CAAC,WAA2B;AAE7D,MAAI,CAAC,OAAO,WAAW,QAAQ,GAAG;AAChC,WAAO;AAAA,EACT;AAGA,QAAM,eAAe,OAAO,MAAM,GAAG,EAAE;AAEvC,MAAI;AAEF,UAAM,WAAW,iBAAiB,SAAS,eAAe,EACvD,iBAAiB,YAAY,EAC7B,KAAK;AAER,QAAI,CAAC,UAAU;AACb,cAAQ,KAAK,gBAAgB,YAAY,gBAAgB;AACzD,aAAO;AAAA,IACT;AAGA,UAAM,WAAW,OAAO,QAAQ;AAChC,WAAO,SAAS,QAAQ;AAAA,EAC1B,SAAS,OAAO;AACd,YAAQ,MAAM,mCAAmC,MAAM,KAAK,KAAK;AACjE,WAAO;AAAA,EACT;AACF;AAOA,IAAM,WAAW,CAAC,QAAwB;AACxC,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,MAAM,QAAQ;AACtB,WAAS,KAAK,YAAY,OAAO;AAEjC,QAAM,gBAAgB,iBAAiB,OAAO,EAAE;AAChD,UAAQ,OAAO;AAGf,QAAM,WAAW,iCAAiC,KAAK,aAAa;AACpE,MAAI,UAAU;AACZ,UAAM,IAAI,SAAS,CAAC,KAAK;AACzB,UAAM,IAAI,SAAS,CAAC,KAAK;AACzB,UAAM,IAAI,SAAS,CAAC,KAAK;AACzB,WAAO,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC,KAAK,OAAO,OAAO,SAAS,CAAC,KAAK,KAAK,OAAO,SAAS,CAAC,GAAG,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,EAC5H;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/client/chat.tsx","../src/client/use-chat.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport { useChat } from \"./use-chat\";\r\nimport { type StyleOptions, type WebChatLib } from \"@agentcrafta/core\";\r\n\r\ndeclare global {\r\n interface Window {\r\n WebChat: WebChatLib;\r\n }\r\n}\r\n\r\ntype ChatProps = {\r\n show?: boolean;\r\n botName?: string;\r\n logoUrl?: string;\r\n styleOptions?: Partial<StyleOptions>;\r\n entryPoint: string;\r\n};\r\n\r\n/**\r\n * @description Componente de chat para interactuar con un agente virtual utilizando Bot Framework Web Chat. Permite iniciar y reiniciar conversaciones, y se adapta a la configuración de estilo definida en el hook useChat.\r\n * @param botName Nombre del bot a mostrar en el encabezado del chat\r\n * @param logoUrl URL del logo a mostrar junto al nombre del bot (opcional)\r\n * @param show Indica si el chat debe mostrarse o no (por defecto es true)\r\n * @param styleOptions: StyleOptions Opciones de estilo personalizadas para el chat (opcional)\r\n * @param entryPoint Punto de entrada para la conversación (opcional)\r\n * @returns\r\n */\r\nexport const Chat = ({\r\n botName = \"Agent\",\r\n show = true,\r\n logoUrl,\r\n styleOptions,\r\n entryPoint,\r\n}: ChatProps) => {\r\n const {\r\n isVisible,\r\n isRestarting,\r\n chatKey,\r\n webChatRef,\r\n styleOptionsMerged,\r\n initializeChat,\r\n restartConversation,\r\n cleanup,\r\n handleChangeVisibility,\r\n } = useChat(styleOptions, entryPoint);\r\n\r\n const scriptLoadedRef = React.useRef(false);\r\n\r\n React.useEffect(() => {\r\n if (!show) return;\r\n // Verificar si el script ya existe en el DOM\r\n const existingScript = document.querySelector(\r\n 'script[src*=\"botframework-webchat\"]',\r\n );\r\n\r\n if (existingScript || scriptLoadedRef.current) {\r\n // Si WebChat ya está disponible, inicializar\r\n if (globalThis.window.WebChat) {\r\n initializeChat();\r\n }\r\n return;\r\n }\r\n\r\n // Cargar el script solo si no existe\r\n const script = document.createElement(\"script\");\r\n script.src =\r\n \"https://cdn.botframework.com/botframework-webchat/latest/webchat.js\";\r\n script.async = true;\r\n\r\n script.onload = () => {\r\n scriptLoadedRef.current = true;\r\n initializeChat();\r\n };\r\n\r\n script.onerror = () => {\r\n console.error(\"Error al cargar el script de WebChat\");\r\n scriptLoadedRef.current = false;\r\n };\r\n\r\n document.head.appendChild(script);\r\n\r\n return () => {\r\n cleanup();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [chatKey]);\r\n\r\n if (!show) return null;\r\n return (\r\n <>\r\n <div\r\n className={`fixed bottom-8 right-8 z-[999] h-[520px] w-[450px] origin-bottom-right overflow-hidden rounded-2xl bg-white shadow-2xl transition-all duration-300 ease-in-out ${\r\n isVisible\r\n ? \"block scale-100 opacity-100\"\r\n : \"hidden scale-95 opacity-0\"\r\n }`}\r\n role=\"complementary\"\r\n aria-label={`Chat ${botName}`}\r\n >\r\n <div\r\n className=\"flex h-14 items-center justify-between bg-primary px-5 py-4 text-white\"\r\n style={{ color: styleOptionsMerged.suggestedActionTextColor }}\r\n >\r\n <div className=\"flex items-center gap-3 text-base font-medium\">\r\n {logoUrl && (\r\n <img\r\n src={logoUrl}\r\n alt=\"Logo\"\r\n width={24}\r\n height={24}\r\n className=\"h-7 w-7 rounded-sm\"\r\n />\r\n )}\r\n <span>{botName}</span>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <button\r\n className={`flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50 ${\r\n isRestarting ? \"cursor-not-allowed opacity-50\" : \"\"\r\n }`}\r\n onClick={restartConversation}\r\n disabled={isRestarting}\r\n aria-label={\r\n isRestarting\r\n ? \"Restarting Conversation...\"\r\n : \"Restart Conversation\"\r\n }\r\n style={{ color: styleOptionsMerged.suggestedActionTextColor }}\r\n >\r\n {isRestarting ? (\r\n <svg\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n className=\"animate-spin\"\r\n >\r\n <path d=\"M21 12a9 9 0 11-6.219-8.56\" />\r\n </svg>\r\n ) : (\r\n <svg\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"></path>\r\n <path d=\"M3 3v5h5\"></path>\r\n </svg>\r\n )}\r\n </button>\r\n <button\r\n className=\"flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50\"\r\n onClick={() => handleChangeVisibility(false)}\r\n aria-label=\"Close Chat\"\r\n style={{ color: styleOptionsMerged.suggestedActionTextColor }}\r\n >\r\n <svg\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div\r\n key={chatKey}\r\n className=\"relative h-[calc(100%-56px)] bg-gray-50\"\r\n role=\"main\"\r\n ref={webChatRef}\r\n >\r\n {isRestarting && (\r\n <div className=\"absolute inset-0 z-10 flex items-center justify-center bg-gray-50/80\">\r\n <div className=\"flex flex-col items-center gap-3 text-gray-600\">\r\n <svg\r\n className=\"h-8 w-8 animate-spin\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n >\r\n <path d=\"M21 12a9 9 0 11-6.219-8.56\" />\r\n </svg>\r\n <span className=\"text-sm font-medium\">\r\n Reiniciando conversación...\r\n </span>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <button\r\n className={`focus:outline-3 fixed bottom-24 right-8 z-[998] flex h-16 w-16 cursor-pointer items-center justify-center rounded-full border-none bg-primary shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-1 hover:shadow-xl focus:outline focus:outline-offset-2 focus:outline-indigo-500/50 ${isVisible ? \"pointer-events-none translate-y-2 scale-95 opacity-0\" : \"scale-100 opacity-100\"}`}\r\n onClick={() => handleChangeVisibility(true)}\r\n aria-label=\"Open Chat Assistant\"\r\n >\r\n <svg\r\n className=\"h-7 w-7 text-white transition-transform\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\r\n </svg>\r\n </button>\r\n </>\r\n );\r\n};\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport {\r\n TypeDispatch,\r\n styleOptionsBase,\r\n type StyleOptions,\r\n type WebChatAction,\r\n type WebChatStore,\r\n} from \"@agentcrafta/core\";\r\nimport {\r\n getChatStoreConfig,\r\n getConversationToken,\r\n getRegionalSettings,\r\n logChatError,\r\n} from \"../server\";\r\n\r\nexport const useChat = (\r\n styleOptionsProps: Partial<StyleOptions> | undefined,\r\n entryPoint: string,\r\n) => {\r\n const [isVisible, setIsVisible] = React.useState(false);\r\n const [isRestarting, setIsRestarting] = React.useState(false);\r\n const [chatKey, setChatKey] = React.useState(Date.now());\r\n const webChatRef = React.useRef<HTMLDivElement>(null);\r\n const webChatInstanceRef = React.useRef<unknown>(null);\r\n const directLineUrlRef = React.useRef<string | null>(null);\r\n const isInitializedRef = React.useRef(false);\r\n\r\n const styleOptionsMerged = { ...styleOptionsBase, ...styleOptionsProps };\r\n\r\n const handleChangeVisibility = (visible: boolean) => {\r\n setIsVisible(visible);\r\n };\r\n\r\n /**\r\n * Crea una tienda personalizada para Web Chat que maneja la conexión y filtra actividades específicas.\r\n *\r\n * @returns action: WebChatAction\r\n */\r\n const createCustomStore = async () => {\r\n const configResult = await getChatStoreConfig();\r\n const { eventConfig, filterConfig, initialState } = configResult ?? {};\r\n\r\n return globalThis.window.WebChat.createStore(\r\n initialState || {},\r\n ({ dispatch }: WebChatStore) =>\r\n (next: (action: WebChatAction) => WebChatAction) =>\r\n (action: WebChatAction) => {\r\n if (action.type === TypeDispatch.CONNECTED_FULFILLED) {\r\n dispatch({\r\n type: TypeDispatch.POST_ACTIVITY,\r\n meta: { method: \"keyboard\" },\r\n payload: {\r\n activity: eventConfig?.startConversation || {\r\n channelData: { postBack: true },\r\n name: \"startConversation\",\r\n type: \"event\",\r\n },\r\n },\r\n });\r\n }\r\n\r\n // Filtrar actividades trace con configuración del servidor\r\n if (\r\n action.type === TypeDispatch.INCOMING_ACTIVITY &&\r\n action.payload?.activity?.type === \"trace\"\r\n ) {\r\n const errorMessage =\r\n filterConfig?.traceErrorMessage || \"Error de conectividad\";\r\n console.error(errorMessage);\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n logChatError({\r\n errorType: \"trace_activity\",\r\n errorMessage: \"Trace activity filtered\",\r\n actionType: action.type,\r\n });\r\n\r\n return action;\r\n }\r\n\r\n return next(action);\r\n },\r\n );\r\n };\r\n\r\n /**\r\n * Reinicia la conversación del chat usando el patrón React key para remount completo.\r\n * @returns\r\n */\r\n const restartConversation = async () => {\r\n if (isRestarting) return;\r\n\r\n try {\r\n setIsRestarting(true);\r\n isInitializedRef.current = false;\r\n webChatInstanceRef.current = null;\r\n setChatKey(Date.now());\r\n } catch (err) {\r\n const errorMessage =\r\n err instanceof Error ? err.message : \"Error desconocido\";\r\n console.error(\"Error al reiniciar conversación:\", errorMessage);\r\n logChatError({\r\n errorType: \"restart_conversation\",\r\n errorMessage,\r\n actionType: \"Error reiniciando conversación\",\r\n });\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n } finally {\r\n setIsRestarting(false);\r\n }\r\n };\r\n\r\n /**\r\n * Inicializa el chat embebido obteniendo la URL de DirectLine y el token de conversación.\r\n * @returns\r\n */\r\n const initializeChat = async () => {\r\n if (isInitializedRef.current) return;\r\n\r\n try {\r\n const data = await getRegionalSettings(entryPoint);\r\n directLineUrlRef.current = data.channelUrlsById.directline;\r\n\r\n if (!directLineUrlRef.current) {\r\n logChatError({\r\n errorType: \"initialize_chat\",\r\n errorMessage: \"DirectLine URL not found in regional settings\",\r\n actionType: \"Error inicializando chat\",\r\n });\r\n console.error(\"No se pudo obtener la URL de DirectLine\");\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n return;\r\n }\r\n const token = await getConversationToken(entryPoint);\r\n const directLine = globalThis.window.WebChat.createDirectLine({\r\n domain: `${directLineUrlRef.current}v3/directline`,\r\n token,\r\n });\r\n\r\n if (webChatRef.current && !isInitializedRef.current) {\r\n const store = await createCustomStore();\r\n webChatInstanceRef.current = globalThis.window.WebChat.renderWebChat(\r\n {\r\n directLine,\r\n styleOptions: styleOptionsMerged,\r\n store,\r\n },\r\n webChatRef.current,\r\n );\r\n isInitializedRef.current = true;\r\n }\r\n } catch (err) {\r\n const errorMessage =\r\n err instanceof Error ? err.message : \"Error desconocido\";\r\n console.error(\"Error detallado al inicializar el chat:\", err);\r\n logChatError({\r\n errorType: \"initialize_chat\",\r\n errorMessage,\r\n actionType: \"Error inicializando chat\",\r\n });\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n }\r\n };\r\n\r\n /**\r\n * Limpia la instancia del chat embebido de forma simple.\r\n */\r\n const cleanup = () => {\r\n isInitializedRef.current = false;\r\n webChatInstanceRef.current = null;\r\n // No manipular DOM directamente - dejar que React maneje el ciclo de vida\r\n };\r\n\r\n return {\r\n isVisible,\r\n isRestarting,\r\n chatKey,\r\n webChatRef,\r\n styleOptionsMerged,\r\n handleChangeVisibility,\r\n initializeChat,\r\n restartConversation,\r\n cleanup,\r\n };\r\n};\r\n"],"mappings":"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","names":["React","React"]}
@@ -1,9 +1,7 @@
1
1
  import { LogChatErrorInput } from '@agentcrafta/core';
2
- export { C as ChatServer } from '../chat-server-DoG_Rvk7.js';
3
- import 'react/jsx-runtime';
4
2
 
5
- declare const getRegionalSettings: () => Promise<any>;
6
- declare const getConversationToken: () => Promise<string>;
3
+ declare const getRegionalSettings: (tokenEndpoint?: string) => Promise<any>;
4
+ declare const getConversationToken: (tokenEndpoint?: string) => Promise<string>;
7
5
  declare const getChatStoreConfig: () => Promise<{
8
6
  initialState: {};
9
7
  eventConfig: {
@@ -1,12 +1,10 @@
1
1
  import {
2
- ChatServer,
3
2
  getChatStoreConfig,
4
3
  getConversationToken,
5
4
  getRegionalSettings,
6
5
  logChatError
7
- } from "../chunk-MOTD6MKH.js";
6
+ } from "../chunk-Y2JYBEV6.js";
8
7
  export {
9
- ChatServer,
10
8
  getChatStoreConfig,
11
9
  getConversationToken,
12
10
  getRegionalSettings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcrafta/chat-next",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Customizable chat agent",
@@ -1,20 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { StyleOptions } from '@agentcrafta/core';
3
-
4
- type ChatProps = {
5
- show?: boolean;
6
- botName?: string;
7
- logoUrl?: string;
8
- styleOptions?: Partial<StyleOptions>;
9
- };
10
- /**
11
- * @description Componente de servidor para el chat. Este componente se encarga de manejar la lógica del servidor y la comunicación con el cliente.
12
- * @param botName Nombre del bot a mostrar en el encabezado del chat
13
- * @param logoUrl URL del logo a mostrar junto al nombre del bot (opcional)
14
- * @param show Indica si el chat debe mostrarse o no (por defecto es true)
15
- * @param styleOptions: StyleOptions Opciones de estilo personalizadas para el chat (opcional)
16
- * @returns
17
- */
18
- declare function ChatServer(props: ChatProps): react_jsx_runtime.JSX.Element;
19
-
20
- export { ChatServer as C };
@@ -1,410 +0,0 @@
1
- // src/server/actions.ts
2
- import "@agentcrafta/core";
3
- var tokenEndpoint = process.env.TOKEN_AGENTE_URL || "";
4
- var getRegionalSettings = async () => {
5
- if (!tokenEndpoint || tokenEndpoint.trim() === "") {
6
- throw new Error("Token endpoint no configurado");
7
- }
8
- const environmentEndPoint = tokenEndpoint.slice(
9
- 0,
10
- tokenEndpoint.indexOf("/powervirtualagents")
11
- );
12
- const regex = /api-version=([^&]+)/;
13
- const apiVersionMatch = regex.exec(tokenEndpoint);
14
- const apiVersion = apiVersionMatch ? apiVersionMatch[1] : "2022-03-01-preview";
15
- const regionalChannelSettingsURL = `${environmentEndPoint}/powervirtualagents/regionalchannelsettings?api-version=${apiVersion}`;
16
- const response = await fetch(regionalChannelSettingsURL);
17
- if (!response.ok) {
18
- throw new Error(`Error ${response.status}: ${response.statusText}`);
19
- }
20
- const data = await response.json();
21
- return data;
22
- };
23
- var getConversationToken = async () => {
24
- if (!tokenEndpoint || tokenEndpoint.trim() === "") {
25
- throw new Error("Token endpoint no configurado");
26
- }
27
- const conversationResponse = await fetch(tokenEndpoint);
28
- if (!conversationResponse.ok) {
29
- throw new Error(
30
- `Error al obtener token: ${conversationResponse.status} ${conversationResponse.statusText}`
31
- );
32
- }
33
- const conversationInfo = await conversationResponse.json();
34
- if (!conversationInfo.token)
35
- throw new Error("Token no encontrado en la respuesta");
36
- return conversationInfo.token;
37
- };
38
- var getChatStoreConfig = async () => {
39
- const config = {
40
- initialState: {},
41
- eventConfig: {
42
- startConversation: {
43
- channelData: { postBack: true },
44
- name: "startConversation",
45
- type: "event"
46
- }
47
- },
48
- filterConfig: {
49
- enableTraceFilter: true,
50
- traceErrorMessage: "Error de conectividad"
51
- }
52
- };
53
- return config;
54
- };
55
- var logChatError = async (input) => {
56
- console.error("[Chat Error]:", {
57
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
58
- ...input
59
- });
60
- return { logged: true };
61
- };
62
-
63
- // src/client/chat.tsx
64
- import React2 from "react";
65
-
66
- // src/client/use-chat.ts
67
- import React from "react";
68
- import {
69
- TypeDispatch,
70
- styleOptionsBase
71
- } from "@agentcrafta/core";
72
- var useChat = (styleOptionsProps) => {
73
- const [isVisible, setIsVisible] = React.useState(false);
74
- const [isRestarting, setIsRestarting] = React.useState(false);
75
- const [chatKey, setChatKey] = React.useState(Date.now());
76
- const webChatRef = React.useRef(null);
77
- const webChatInstanceRef = React.useRef(null);
78
- const directLineUrlRef = React.useRef(null);
79
- const isInitializedRef = React.useRef(false);
80
- const styleOptionsMerged = { ...styleOptionsBase, ...styleOptionsProps };
81
- const handleChangeVisibility = (visible) => {
82
- setIsVisible(visible);
83
- };
84
- const createCustomStore = async () => {
85
- const configResult = await getChatStoreConfig();
86
- const { eventConfig, filterConfig, initialState } = configResult ?? {};
87
- return globalThis.window.WebChat.createStore(
88
- initialState || {},
89
- ({ dispatch }) => (next) => (action) => {
90
- if (action.type === TypeDispatch.CONNECTED_FULFILLED) {
91
- dispatch({
92
- type: TypeDispatch.POST_ACTIVITY,
93
- meta: { method: "keyboard" },
94
- payload: {
95
- activity: eventConfig?.startConversation || {
96
- channelData: { postBack: true },
97
- name: "startConversation",
98
- type: "event"
99
- }
100
- }
101
- });
102
- }
103
- if (action.type === TypeDispatch.INCOMING_ACTIVITY && action.payload?.activity?.type === "trace") {
104
- const errorMessage = filterConfig?.traceErrorMessage || "Error de conectividad";
105
- console.error(errorMessage);
106
- logChatError({
107
- errorType: "trace_activity",
108
- errorMessage: "Trace activity filtered",
109
- actionType: action.type
110
- });
111
- return action;
112
- }
113
- return next(action);
114
- }
115
- );
116
- };
117
- const restartConversation = async () => {
118
- if (isRestarting) return;
119
- try {
120
- setIsRestarting(true);
121
- isInitializedRef.current = false;
122
- webChatInstanceRef.current = null;
123
- setChatKey(Date.now());
124
- } catch (err) {
125
- const errorMessage = err instanceof Error ? err.message : "Error desconocido";
126
- console.error("Error al reiniciar conversaci\xF3n:", errorMessage);
127
- logChatError({
128
- errorType: "restart_conversation",
129
- errorMessage,
130
- actionType: "Error reiniciando conversaci\xF3n"
131
- });
132
- } finally {
133
- setIsRestarting(false);
134
- }
135
- };
136
- const initializeChat = async () => {
137
- if (isInitializedRef.current) return;
138
- try {
139
- const data = await getRegionalSettings();
140
- directLineUrlRef.current = data.channelUrlsById.directline;
141
- if (!directLineUrlRef.current) {
142
- logChatError({
143
- errorType: "initialize_chat",
144
- errorMessage: "DirectLine URL not found in regional settings",
145
- actionType: "Error inicializando chat"
146
- });
147
- console.error("No se pudo obtener la URL de DirectLine");
148
- return;
149
- }
150
- const token = await getConversationToken();
151
- const directLine = globalThis.window.WebChat.createDirectLine({
152
- domain: `${directLineUrlRef.current}v3/directline`,
153
- token
154
- });
155
- if (webChatRef.current && !isInitializedRef.current) {
156
- const store = await createCustomStore();
157
- webChatInstanceRef.current = globalThis.window.WebChat.renderWebChat(
158
- {
159
- directLine,
160
- styleOptions: styleOptionsMerged,
161
- store
162
- },
163
- webChatRef.current
164
- );
165
- isInitializedRef.current = true;
166
- }
167
- } catch (err) {
168
- const errorMessage = err instanceof Error ? err.message : "Error desconocido";
169
- console.error("Error detallado al inicializar el chat:", err);
170
- logChatError({
171
- errorType: "initialize_chat",
172
- errorMessage,
173
- actionType: "Error inicializando chat"
174
- });
175
- }
176
- };
177
- const cleanup = () => {
178
- isInitializedRef.current = false;
179
- webChatInstanceRef.current = null;
180
- };
181
- return {
182
- isVisible,
183
- isRestarting,
184
- chatKey,
185
- webChatRef,
186
- styleOptionsMerged,
187
- handleChangeVisibility,
188
- initializeChat,
189
- restartConversation,
190
- cleanup
191
- };
192
- };
193
-
194
- // src/client/chat.tsx
195
- import "@agentcrafta/core";
196
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
197
- var Chat = ({
198
- botName = "Agent",
199
- show = true,
200
- logoUrl,
201
- styleOptions
202
- }) => {
203
- const {
204
- isVisible,
205
- isRestarting,
206
- chatKey,
207
- webChatRef,
208
- styleOptionsMerged,
209
- initializeChat,
210
- restartConversation,
211
- cleanup,
212
- handleChangeVisibility
213
- } = useChat(styleOptions);
214
- const scriptLoadedRef = React2.useRef(false);
215
- React2.useEffect(() => {
216
- if (!show) return;
217
- const existingScript = document.querySelector(
218
- 'script[src*="botframework-webchat"]'
219
- );
220
- if (existingScript || scriptLoadedRef.current) {
221
- if (globalThis.window.WebChat) {
222
- initializeChat();
223
- }
224
- return;
225
- }
226
- const script = document.createElement("script");
227
- script.src = "https://cdn.botframework.com/botframework-webchat/latest/webchat.js";
228
- script.async = true;
229
- script.onload = () => {
230
- scriptLoadedRef.current = true;
231
- initializeChat();
232
- };
233
- script.onerror = () => {
234
- console.error("Error al cargar el script de WebChat");
235
- scriptLoadedRef.current = false;
236
- };
237
- document.head.appendChild(script);
238
- return () => {
239
- cleanup();
240
- };
241
- }, [chatKey]);
242
- if (!show) return null;
243
- return /* @__PURE__ */ jsxs(Fragment, { children: [
244
- /* @__PURE__ */ jsxs(
245
- "div",
246
- {
247
- className: `fixed bottom-8 right-8 z-[999] h-[520px] w-[450px] origin-bottom-right overflow-hidden rounded-2xl bg-white shadow-2xl transition-all duration-300 ease-in-out ${isVisible ? "block scale-100 opacity-100" : "hidden scale-95 opacity-0"}`,
248
- role: "complementary",
249
- "aria-label": `Chat ${botName}`,
250
- children: [
251
- /* @__PURE__ */ jsxs(
252
- "div",
253
- {
254
- className: "flex h-14 items-center justify-between bg-primary px-5 py-4 text-white",
255
- style: { color: styleOptionsMerged.suggestedActionTextColor },
256
- children: [
257
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-base font-medium", children: [
258
- logoUrl && /* @__PURE__ */ jsx(
259
- "img",
260
- {
261
- src: logoUrl,
262
- alt: "Logo",
263
- width: 24,
264
- height: 24,
265
- className: "h-7 w-7 rounded-sm"
266
- }
267
- ),
268
- /* @__PURE__ */ jsx("span", { children: botName })
269
- ] }),
270
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
271
- /* @__PURE__ */ jsx(
272
- "button",
273
- {
274
- className: `flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50 ${isRestarting ? "cursor-not-allowed opacity-50" : ""}`,
275
- onClick: restartConversation,
276
- disabled: isRestarting,
277
- "aria-label": isRestarting ? "Restarting Conversation..." : "Restart Conversation",
278
- style: { color: styleOptionsMerged.suggestedActionTextColor },
279
- children: isRestarting ? /* @__PURE__ */ jsx(
280
- "svg",
281
- {
282
- width: "20",
283
- height: "20",
284
- viewBox: "0 0 24 24",
285
- fill: "none",
286
- stroke: "currentColor",
287
- strokeWidth: "2",
288
- strokeLinecap: "round",
289
- strokeLinejoin: "round",
290
- "aria-hidden": "true",
291
- className: "animate-spin",
292
- children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
293
- }
294
- ) : /* @__PURE__ */ jsxs(
295
- "svg",
296
- {
297
- width: "20",
298
- height: "20",
299
- viewBox: "0 0 24 24",
300
- fill: "none",
301
- stroke: "currentColor",
302
- strokeWidth: "2",
303
- strokeLinecap: "round",
304
- strokeLinejoin: "round",
305
- "aria-hidden": "true",
306
- children: [
307
- /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
308
- /* @__PURE__ */ jsx("path", { d: "M3 3v5h5" })
309
- ]
310
- }
311
- )
312
- }
313
- ),
314
- /* @__PURE__ */ jsx(
315
- "button",
316
- {
317
- className: "flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50",
318
- onClick: () => handleChangeVisibility(false),
319
- "aria-label": "Close Chat",
320
- style: { color: styleOptionsMerged.suggestedActionTextColor },
321
- children: /* @__PURE__ */ jsxs(
322
- "svg",
323
- {
324
- width: "20",
325
- height: "20",
326
- viewBox: "0 0 24 24",
327
- fill: "none",
328
- stroke: "currentColor",
329
- strokeWidth: "2",
330
- strokeLinecap: "round",
331
- strokeLinejoin: "round",
332
- "aria-hidden": "true",
333
- children: [
334
- /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
335
- /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
336
- ]
337
- }
338
- )
339
- }
340
- )
341
- ] })
342
- ]
343
- }
344
- ),
345
- /* @__PURE__ */ jsx(
346
- "div",
347
- {
348
- className: "relative h-[calc(100%-56px)] bg-gray-50",
349
- role: "main",
350
- ref: webChatRef,
351
- children: isRestarting && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-gray-50/80", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 text-gray-600", children: [
352
- /* @__PURE__ */ jsx(
353
- "svg",
354
- {
355
- className: "h-8 w-8 animate-spin",
356
- viewBox: "0 0 24 24",
357
- fill: "none",
358
- stroke: "currentColor",
359
- strokeWidth: "2",
360
- children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
361
- }
362
- ),
363
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Reiniciando conversaci\xF3n..." })
364
- ] }) })
365
- },
366
- chatKey
367
- )
368
- ]
369
- }
370
- ),
371
- /* @__PURE__ */ jsx(
372
- "button",
373
- {
374
- className: `focus:outline-3 fixed bottom-24 right-8 z-[998] flex h-16 w-16 cursor-pointer items-center justify-center rounded-full border-none bg-primary shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-1 hover:shadow-xl focus:outline focus:outline-offset-2 focus:outline-indigo-500/50 ${isVisible ? "pointer-events-none translate-y-2 scale-95 opacity-0" : "scale-100 opacity-100"}`,
375
- onClick: () => handleChangeVisibility(true),
376
- "aria-label": "Open Chat Assistant",
377
- children: /* @__PURE__ */ jsx(
378
- "svg",
379
- {
380
- className: "h-7 w-7 text-white transition-transform",
381
- viewBox: "0 0 24 24",
382
- fill: "none",
383
- stroke: "currentColor",
384
- strokeWidth: "2",
385
- strokeLinecap: "round",
386
- strokeLinejoin: "round",
387
- "aria-hidden": "true",
388
- children: /* @__PURE__ */ jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
389
- }
390
- )
391
- }
392
- )
393
- ] });
394
- };
395
-
396
- // src/server/chat-server.tsx
397
- import { jsx as jsx2 } from "react/jsx-runtime";
398
- function ChatServer(props) {
399
- return /* @__PURE__ */ jsx2(Chat, { ...props });
400
- }
401
-
402
- export {
403
- getRegionalSettings,
404
- getConversationToken,
405
- getChatStoreConfig,
406
- logChatError,
407
- ChatServer,
408
- Chat
409
- };
410
- //# sourceMappingURL=chunk-MOTD6MKH.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/actions.ts","../src/client/chat.tsx","../src/client/use-chat.ts","../src/server/chat-server.tsx"],"sourcesContent":["\"use server\";\r\n\r\nimport { type LogChatErrorInput } from \"@agentcrafta/core\";\r\n\r\nconst tokenEndpoint = process.env.TOKEN_AGENTE_URL || \"\";\r\n\r\n//#region Inicializar Chat\r\nexport const getRegionalSettings = async () => {\r\n if (!tokenEndpoint || tokenEndpoint.trim() === \"\") {\r\n throw new Error(\"Token endpoint no configurado\");\r\n }\r\n const environmentEndPoint = tokenEndpoint.slice(\r\n 0,\r\n tokenEndpoint.indexOf(\"/powervirtualagents\"),\r\n );\r\n const regex = /api-version=([^&]+)/;\r\n const apiVersionMatch = regex.exec(tokenEndpoint);\r\n const apiVersion = apiVersionMatch\r\n ? apiVersionMatch[1]\r\n : \"2022-03-01-preview\";\r\n\r\n const regionalChannelSettingsURL = `${environmentEndPoint}/powervirtualagents/regionalchannelsettings?api-version=${apiVersion}`;\r\n const response = await fetch(regionalChannelSettingsURL);\r\n if (!response.ok) {\r\n throw new Error(`Error ${response.status}: ${response.statusText}`);\r\n }\r\n const data = await response.json();\r\n return data;\r\n};\r\n\r\nexport const getConversationToken = async (): Promise<string> => {\r\n if (!tokenEndpoint || tokenEndpoint.trim() === \"\") {\r\n throw new Error(\"Token endpoint no configurado\");\r\n }\r\n const conversationResponse = await fetch(tokenEndpoint);\r\n if (!conversationResponse.ok) {\r\n throw new Error(\r\n `Error al obtener token: ${conversationResponse.status} ${conversationResponse.statusText}`,\r\n );\r\n }\r\n const conversationInfo = await conversationResponse.json();\r\n if (!conversationInfo.token)\r\n throw new Error(\"Token no encontrado en la respuesta\");\r\n return conversationInfo.token;\r\n};\r\n//#endregion\r\n\r\n//#region Configuración Store Chat\r\nexport const getChatStoreConfig = async () => {\r\n const config = {\r\n initialState: {},\r\n eventConfig: {\r\n startConversation: {\r\n channelData: { postBack: true },\r\n name: \"startConversation\",\r\n type: \"event\",\r\n },\r\n },\r\n filterConfig: {\r\n enableTraceFilter: true,\r\n traceErrorMessage: \"Error de conectividad\",\r\n },\r\n };\r\n return config;\r\n};\r\n//#endregion\r\n\r\n//#region Log de errores del chat\r\nexport const logChatError = async (input: LogChatErrorInput) => {\r\n // Registrar errores en el servidor\r\n console.error(\"[Chat Error]:\", {\r\n timestamp: new Date().toISOString(),\r\n ...input,\r\n });\r\n\r\n // Aquí podrías guardar en base de datos, enviar a servicio de logging, etc.\r\n\r\n return { logged: true };\r\n};\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport { useChat } from \"./use-chat\";\r\nimport { type StyleOptions, type WebChatLib } from \"@agentcrafta/core\";\r\n\r\ndeclare global {\r\n interface Window {\r\n WebChat: WebChatLib;\r\n }\r\n}\r\n\r\ntype ChatProps = {\r\n show?: boolean;\r\n botName?: string;\r\n logoUrl?: string;\r\n styleOptions?: Partial<StyleOptions>;\r\n};\r\n\r\n/**\r\n * @description Componente de chat para interactuar con un agente virtual utilizando Bot Framework Web Chat. Permite iniciar y reiniciar conversaciones, y se adapta a la configuración de estilo definida en el hook useChat.\r\n * @param botName Nombre del bot a mostrar en el encabezado del chat\r\n * @param logoUrl URL del logo a mostrar junto al nombre del bot (opcional)\r\n * @param show Indica si el chat debe mostrarse o no (por defecto es true)\r\n * @param styleOptions: StyleOptions Opciones de estilo personalizadas para el chat (opcional)\r\n * @returns\r\n */\r\nexport const Chat = ({\r\n botName = \"Agent\",\r\n show = true,\r\n logoUrl,\r\n styleOptions,\r\n}: ChatProps) => {\r\n const {\r\n isVisible,\r\n isRestarting,\r\n chatKey,\r\n webChatRef,\r\n styleOptionsMerged,\r\n initializeChat,\r\n restartConversation,\r\n cleanup,\r\n handleChangeVisibility,\r\n } = useChat(styleOptions);\r\n\r\n const scriptLoadedRef = React.useRef(false);\r\n\r\n React.useEffect(() => {\r\n if (!show) return;\r\n // Verificar si el script ya existe en el DOM\r\n const existingScript = document.querySelector(\r\n 'script[src*=\"botframework-webchat\"]',\r\n );\r\n\r\n if (existingScript || scriptLoadedRef.current) {\r\n // Si WebChat ya está disponible, inicializar\r\n if (globalThis.window.WebChat) {\r\n initializeChat();\r\n }\r\n return;\r\n }\r\n\r\n // Cargar el script solo si no existe\r\n const script = document.createElement(\"script\");\r\n script.src =\r\n \"https://cdn.botframework.com/botframework-webchat/latest/webchat.js\";\r\n script.async = true;\r\n\r\n script.onload = () => {\r\n scriptLoadedRef.current = true;\r\n initializeChat();\r\n };\r\n\r\n script.onerror = () => {\r\n console.error(\"Error al cargar el script de WebChat\");\r\n scriptLoadedRef.current = false;\r\n };\r\n\r\n document.head.appendChild(script);\r\n\r\n return () => {\r\n cleanup();\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [chatKey]);\r\n\r\n if (!show) return null;\r\n return (\r\n <>\r\n <div\r\n className={`fixed bottom-8 right-8 z-[999] h-[520px] w-[450px] origin-bottom-right overflow-hidden rounded-2xl bg-white shadow-2xl transition-all duration-300 ease-in-out ${\r\n isVisible\r\n ? \"block scale-100 opacity-100\"\r\n : \"hidden scale-95 opacity-0\"\r\n }`}\r\n role=\"complementary\"\r\n aria-label={`Chat ${botName}`}\r\n >\r\n <div\r\n className=\"flex h-14 items-center justify-between bg-primary px-5 py-4 text-white\"\r\n style={{ color: styleOptionsMerged.suggestedActionTextColor }}\r\n >\r\n <div className=\"flex items-center gap-3 text-base font-medium\">\r\n {logoUrl && (\r\n <img\r\n src={logoUrl}\r\n alt=\"Logo\"\r\n width={24}\r\n height={24}\r\n className=\"h-7 w-7 rounded-sm\"\r\n />\r\n )}\r\n <span>{botName}</span>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <button\r\n className={`flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50 ${\r\n isRestarting ? \"cursor-not-allowed opacity-50\" : \"\"\r\n }`}\r\n onClick={restartConversation}\r\n disabled={isRestarting}\r\n aria-label={\r\n isRestarting\r\n ? \"Restarting Conversation...\"\r\n : \"Restart Conversation\"\r\n }\r\n style={{ color: styleOptionsMerged.suggestedActionTextColor }}\r\n >\r\n {isRestarting ? (\r\n <svg\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n className=\"animate-spin\"\r\n >\r\n <path d=\"M21 12a9 9 0 11-6.219-8.56\" />\r\n </svg>\r\n ) : (\r\n <svg\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\"></path>\r\n <path d=\"M3 3v5h5\"></path>\r\n </svg>\r\n )}\r\n </button>\r\n <button\r\n className=\"flex cursor-pointer items-center justify-center rounded-lg border-none bg-transparent p-2 transition-all duration-200 hover:bg-white/10 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-white/50\"\r\n onClick={() => handleChangeVisibility(false)}\r\n aria-label=\"Close Chat\"\r\n style={{ color: styleOptionsMerged.suggestedActionTextColor }}\r\n >\r\n <svg\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div\r\n key={chatKey}\r\n className=\"relative h-[calc(100%-56px)] bg-gray-50\"\r\n role=\"main\"\r\n ref={webChatRef}\r\n >\r\n {isRestarting && (\r\n <div className=\"absolute inset-0 z-10 flex items-center justify-center bg-gray-50/80\">\r\n <div className=\"flex flex-col items-center gap-3 text-gray-600\">\r\n <svg\r\n className=\"h-8 w-8 animate-spin\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n >\r\n <path d=\"M21 12a9 9 0 11-6.219-8.56\" />\r\n </svg>\r\n <span className=\"text-sm font-medium\">\r\n Reiniciando conversación...\r\n </span>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n\r\n <button\r\n className={`focus:outline-3 fixed bottom-24 right-8 z-[998] flex h-16 w-16 cursor-pointer items-center justify-center rounded-full border-none bg-primary shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-1 hover:shadow-xl focus:outline focus:outline-offset-2 focus:outline-indigo-500/50 ${isVisible ? \"pointer-events-none translate-y-2 scale-95 opacity-0\" : \"scale-100 opacity-100\"}`}\r\n onClick={() => handleChangeVisibility(true)}\r\n aria-label=\"Open Chat Assistant\"\r\n >\r\n <svg\r\n className=\"h-7 w-7 text-white transition-transform\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n aria-hidden=\"true\"\r\n >\r\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path>\r\n </svg>\r\n </button>\r\n </>\r\n );\r\n};\r\n","\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport {\r\n TypeDispatch,\r\n styleOptionsBase,\r\n type StyleOptions,\r\n type WebChatAction,\r\n type WebChatStore,\r\n} from \"@agentcrafta/core\";\r\nimport {\r\n getChatStoreConfig,\r\n getConversationToken,\r\n getRegionalSettings,\r\n logChatError,\r\n} from \"../server\";\r\n\r\nexport const useChat = (styleOptionsProps?: Partial<StyleOptions>) => {\r\n const [isVisible, setIsVisible] = React.useState(false);\r\n const [isRestarting, setIsRestarting] = React.useState(false);\r\n const [chatKey, setChatKey] = React.useState(Date.now());\r\n const webChatRef = React.useRef<HTMLDivElement>(null);\r\n const webChatInstanceRef = React.useRef<unknown>(null);\r\n const directLineUrlRef = React.useRef<string | null>(null);\r\n const isInitializedRef = React.useRef(false);\r\n\r\n const styleOptionsMerged = { ...styleOptionsBase, ...styleOptionsProps };\r\n\r\n const handleChangeVisibility = (visible: boolean) => {\r\n setIsVisible(visible);\r\n };\r\n\r\n /**\r\n * Crea una tienda personalizada para Web Chat que maneja la conexión y filtra actividades específicas.\r\n *\r\n * @returns action: WebChatAction\r\n */\r\n const createCustomStore = async () => {\r\n const configResult = await getChatStoreConfig();\r\n const { eventConfig, filterConfig, initialState } = configResult ?? {};\r\n\r\n return globalThis.window.WebChat.createStore(\r\n initialState || {},\r\n ({ dispatch }: WebChatStore) =>\r\n (next: (action: WebChatAction) => WebChatAction) =>\r\n (action: WebChatAction) => {\r\n if (action.type === TypeDispatch.CONNECTED_FULFILLED) {\r\n dispatch({\r\n type: TypeDispatch.POST_ACTIVITY,\r\n meta: { method: \"keyboard\" },\r\n payload: {\r\n activity: eventConfig?.startConversation || {\r\n channelData: { postBack: true },\r\n name: \"startConversation\",\r\n type: \"event\",\r\n },\r\n },\r\n });\r\n }\r\n\r\n // Filtrar actividades trace con configuración del servidor\r\n if (\r\n action.type === TypeDispatch.INCOMING_ACTIVITY &&\r\n action.payload?.activity?.type === \"trace\"\r\n ) {\r\n const errorMessage =\r\n filterConfig?.traceErrorMessage || \"Error de conectividad\";\r\n console.error(errorMessage);\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n logChatError({\r\n errorType: \"trace_activity\",\r\n errorMessage: \"Trace activity filtered\",\r\n actionType: action.type,\r\n });\r\n\r\n return action;\r\n }\r\n\r\n return next(action);\r\n },\r\n );\r\n };\r\n\r\n /**\r\n * Reinicia la conversación del chat usando el patrón React key para remount completo.\r\n * @returns\r\n */\r\n const restartConversation = async () => {\r\n if (isRestarting) return;\r\n\r\n try {\r\n setIsRestarting(true);\r\n isInitializedRef.current = false;\r\n webChatInstanceRef.current = null;\r\n setChatKey(Date.now());\r\n } catch (err) {\r\n const errorMessage =\r\n err instanceof Error ? err.message : \"Error desconocido\";\r\n console.error(\"Error al reiniciar conversación:\", errorMessage);\r\n logChatError({\r\n errorType: \"restart_conversation\",\r\n errorMessage,\r\n actionType: \"Error reiniciando conversación\",\r\n });\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n } finally {\r\n setIsRestarting(false);\r\n }\r\n };\r\n\r\n /**\r\n * Inicializa el chat embebido obteniendo la URL de DirectLine y el token de conversación.\r\n * @returns\r\n */\r\n const initializeChat = async () => {\r\n if (isInitializedRef.current) return;\r\n\r\n try {\r\n const data = await getRegionalSettings();\r\n directLineUrlRef.current = data.channelUrlsById.directline;\r\n\r\n if (!directLineUrlRef.current) {\r\n logChatError({\r\n errorType: \"initialize_chat\",\r\n errorMessage: \"DirectLine URL not found in regional settings\",\r\n actionType: \"Error inicializando chat\",\r\n });\r\n console.error(\"No se pudo obtener la URL de DirectLine\");\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n return;\r\n }\r\n const token = await getConversationToken();\r\n const directLine = globalThis.window.WebChat.createDirectLine({\r\n domain: `${directLineUrlRef.current}v3/directline`,\r\n token,\r\n });\r\n\r\n if (webChatRef.current && !isInitializedRef.current) {\r\n const store = await createCustomStore();\r\n webChatInstanceRef.current = globalThis.window.WebChat.renderWebChat(\r\n {\r\n directLine,\r\n styleOptions: styleOptionsMerged,\r\n store,\r\n },\r\n webChatRef.current,\r\n );\r\n isInitializedRef.current = true;\r\n }\r\n } catch (err) {\r\n const errorMessage =\r\n err instanceof Error ? err.message : \"Error desconocido\";\r\n console.error(\"Error detallado al inicializar el chat:\", err);\r\n logChatError({\r\n errorType: \"initialize_chat\",\r\n errorMessage,\r\n actionType: \"Error inicializando chat\",\r\n });\r\n // Mostrar mensaje de error al usuario con toast o similar\r\n }\r\n };\r\n\r\n /**\r\n * Limpia la instancia del chat embebido de forma simple.\r\n */\r\n const cleanup = () => {\r\n isInitializedRef.current = false;\r\n webChatInstanceRef.current = null;\r\n // No manipular DOM directamente - dejar que React maneje el ciclo de vida\r\n };\r\n\r\n return {\r\n isVisible,\r\n isRestarting,\r\n chatKey,\r\n webChatRef,\r\n styleOptionsMerged,\r\n handleChangeVisibility,\r\n initializeChat,\r\n restartConversation,\r\n cleanup,\r\n };\r\n};\r\n","import type { StyleOptions } from \"@agentcrafta/core\";\r\nimport { Chat } from \"../client\";\r\n\r\ntype ChatProps = {\r\n show?: boolean;\r\n botName?: string;\r\n logoUrl?: string;\r\n styleOptions?: Partial<StyleOptions>;\r\n};\r\n\r\n/**\r\n * @description Componente de servidor para el chat. Este componente se encarga de manejar la lógica del servidor y la comunicación con el cliente.\r\n * @param botName Nombre del bot a mostrar en el encabezado del chat\r\n * @param logoUrl URL del logo a mostrar junto al nombre del bot (opcional)\r\n * @param show Indica si el chat debe mostrarse o no (por defecto es true)\r\n * @param styleOptions: StyleOptions Opciones de estilo personalizadas para el chat (opcional)\r\n * @returns\r\n */\r\nexport function ChatServer(props: ChatProps) {\r\n return <Chat {...props} />;\r\n}\r\n"],"mappings":"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","names":["React","React","jsx"]}