@agentcrafta/chat-next 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +322 -0
- package/dist/{chunk-RI5TL55G.js → chunk-RKYHRGFI.js} +10 -2
- package/dist/chunk-RKYHRGFI.js.map +1 -0
- package/dist/index.d.ts +1 -91
- package/dist/index.js +2 -43
- package/dist/index.js.map +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-RI5TL55G.js.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# Agente Conversacional Embebido
|
|
2
|
+
|
|
3
|
+
## Descripción del Componente
|
|
4
|
+
|
|
5
|
+
El **Agente Conversacional Embebido** es un componente React que integra Microsoft Bot Framework Web Chat en una interfaz moderna y personalizable. Proporciona una experiencia de chat completa con soporte para reinicio de conversación, personalización de estilos dinámicos basados en variables CSS, y gestión automática del estado de conexión.
|
|
6
|
+
|
|
7
|
+
Este componente utiliza el Web Chat de Bot Framework para comunicarse con Power Virtual Agents (PVA) u otros bots compatibles, ofreciendo una interfaz de usuario intuitiva y responsive.
|
|
8
|
+
|
|
9
|
+
## Índice
|
|
10
|
+
|
|
11
|
+
- [Instalación y Configuración](#instalación-y-configuración)
|
|
12
|
+
- [Variables de Entorno](#variables-de-entorno)
|
|
13
|
+
- [Uso del Componente](#uso-del-componente)
|
|
14
|
+
- [Server Actions](#server-actions)
|
|
15
|
+
- [Hook useChat](#hook-usechat)
|
|
16
|
+
- [Configuración de StyleOptions](#configuración-de-styleoptions)
|
|
17
|
+
- [Tipos y Interfaces](#tipos-y-interfaces)
|
|
18
|
+
|
|
19
|
+
## Instalación y Configuración
|
|
20
|
+
|
|
21
|
+
### Variables de Entorno
|
|
22
|
+
|
|
23
|
+
Configure las siguientes variables en su archivo `.env.local` para desarrollo local:
|
|
24
|
+
|
|
25
|
+
```env
|
|
26
|
+
# URL del endpoint para obtener tokens del agente conversacional
|
|
27
|
+
TOKEN_AGENTE_URL=https://your-bot-endpoint.com/powervirtualagents/botsbyschema/...
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Para PRODUCCIÓN, asegúrese de establecer estas variables en su entorno de despliegue.
|
|
31
|
+
|
|
32
|
+
**Importante**: La variable `TOKEN_AGENTE_URL` debe apuntar al endpoint completo de Power Virtual Agents que incluye el esquema del bot y la API version.
|
|
33
|
+
|
|
34
|
+
## Uso del Componente
|
|
35
|
+
|
|
36
|
+
### Características
|
|
37
|
+
|
|
38
|
+
- **Chat flotante**: Aparece como un botón flotante en la esquina inferior derecha
|
|
39
|
+
- **Interfaz responsive**: Se adapta a diferentes tamaños de pantalla
|
|
40
|
+
- **Reinicio de conversación**: Botón para reiniciar la conversación completa
|
|
41
|
+
- **Personalización de estilos**: Utiliza variables CSS para temas dinámicos
|
|
42
|
+
- **Gestión de errores**: Manejo robusto de errores tanto en cliente como en servidor
|
|
43
|
+
|
|
44
|
+
### Props del Componente
|
|
45
|
+
|
|
46
|
+
| Prop | Tipo | Default | Descripción |
|
|
47
|
+
| -------------- | -------------- | ----------- | --------------------------------------------------------------- |
|
|
48
|
+
| `botName` | `string` | `"Agent"` | Nombre que se mostrará en la cabecera del chat |
|
|
49
|
+
| `logoUrl` | `string` | `undefined` | URL del logo que se mostrará junto al nombre del bot (opcional) |
|
|
50
|
+
| `show` | `boolean` | `true` | Indica si el chat debe mostrarse o no (por defecto es true) |
|
|
51
|
+
| `styleOptions` | `StyleOptions` | `undefined` | Opciones de estilo personalizadas para el chat (opcional) |
|
|
52
|
+
|
|
53
|
+
### Importación y Uso
|
|
54
|
+
|
|
55
|
+
#### Básico
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { Chat } from "../chat";
|
|
59
|
+
|
|
60
|
+
export default function HomePage() {
|
|
61
|
+
return (
|
|
62
|
+
<div>
|
|
63
|
+
<h1>Mi Aplicación</h1>
|
|
64
|
+
<Chat botName="Asistente Virtual" />
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### Avanzado con Personalización de Estilos
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { Chat } from "../chat";
|
|
74
|
+
|
|
75
|
+
export default function HomePage() {
|
|
76
|
+
return (
|
|
77
|
+
<div>
|
|
78
|
+
<h1>Mi Aplicación</h1>
|
|
79
|
+
<Chat
|
|
80
|
+
botName="Asistente Virtual"
|
|
81
|
+
logoUrl="logo.svg"
|
|
82
|
+
styleOptions={{
|
|
83
|
+
accent: getCssVariableAsHex("var(--primary)"),
|
|
84
|
+
backgroundColor: getCssVariableAsHex("var(--background)"),
|
|
85
|
+
//Respuestas del Bot
|
|
86
|
+
botAvatarBackgroundColor: getCssVariableAsHex("var(--background)"),
|
|
87
|
+
bubbleBackground: getCssVariableAsHex("var(--muted)"),
|
|
88
|
+
bubbleBorderRadius: 10,
|
|
89
|
+
//Mensajes del usuario
|
|
90
|
+
bubbleFromUserBackground: getCssVariableAsHex("var(--secondary)"),
|
|
91
|
+
bubbleFromUserBorderRadius: 10,
|
|
92
|
+
bubbleFromUserTextColor: getCssVariableAsHex("var(--background)"),
|
|
93
|
+
userAvatarBackgroundColor: getCssVariableAsHex("var(--primary)"),
|
|
94
|
+
//Caja de escritura
|
|
95
|
+
sendBoxHeight: 50,
|
|
96
|
+
sendBoxPlaceholderColor: getCssVariableAsHex("var(--muted)"),
|
|
97
|
+
sendBoxBackground: getCssVariableAsHex("var(--background)"),
|
|
98
|
+
sendBoxBorderTop: `solid 1px ${getCssVariableAsHex("var(--border)")}`,
|
|
99
|
+
sendBoxButtonColor: getCssVariableAsHex("var(--primary)"),
|
|
100
|
+
}}
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Server Actions
|
|
108
|
+
|
|
109
|
+
### `getRegionalSettings()`
|
|
110
|
+
|
|
111
|
+
**Propósito**: Obtiene la configuración regional del bot, incluyendo las URLs de los canales disponibles.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const data = await getRegionalSettings();
|
|
115
|
+
console.log(data.channelUrlsById.directline); // URL de DirectLine
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Retorna**: Configuración regional con URLs de canales disponibles.
|
|
119
|
+
|
|
120
|
+
### `getConversationToken()`
|
|
121
|
+
|
|
122
|
+
**Propósito**: Obtiene el token de autenticación necesario para establecer la conexión con DirectLine.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
const token = await getConversationToken();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Retorna**: Token de conversación válido para DirectLine.
|
|
129
|
+
|
|
130
|
+
### `getChatStoreConfig()`
|
|
131
|
+
|
|
132
|
+
**Propósito**: Obtiene la configuración del store de Web Chat, incluyendo eventos iniciales y filtros.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const config = await getChatStoreConfig();
|
|
136
|
+
// config.eventConfig.startConversation - Evento para iniciar conversación
|
|
137
|
+
// config.filterConfig - Configuración de filtros
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Retorna**: Configuración del store con estado inicial y eventos.
|
|
141
|
+
|
|
142
|
+
### `logChatError(input)`
|
|
143
|
+
|
|
144
|
+
**Propósito**: Registra errores del chat en el servidor para monitoreo y debugging.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
await logChatError({
|
|
148
|
+
errorType: "connection_failed",
|
|
149
|
+
errorMessage: "No se pudo conectar al bot",
|
|
150
|
+
actionType: "initialize_chat",
|
|
151
|
+
userId: "optional-user-id",
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Parámetros**:
|
|
156
|
+
|
|
157
|
+
- `errorType`: Tipo de error (string)
|
|
158
|
+
- `errorMessage`: Mensaje descriptivo del error
|
|
159
|
+
- `actionType`: Acción que causó el error (opcional)
|
|
160
|
+
- `userId`: ID del usuario (opcional)
|
|
161
|
+
|
|
162
|
+
## Hook useChat
|
|
163
|
+
|
|
164
|
+
### Funciones y Estado
|
|
165
|
+
|
|
166
|
+
#### Estado del Chat
|
|
167
|
+
|
|
168
|
+
### Props del Hook
|
|
169
|
+
|
|
170
|
+
| Prop | Tipo | Default | Descripción |
|
|
171
|
+
| -------------- | -------------- | ----------- | --------------------------------------------------------- |
|
|
172
|
+
| `styleOptions` | `StyleOptions` | `undefined` | Opciones de estilo personalizadas para el chat (opcional) |
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const {
|
|
176
|
+
isVisible, // boolean - Chat visible/oculto
|
|
177
|
+
isRestarting, // boolean - Estado de reinicio
|
|
178
|
+
chatKey, // number - Key para forzar re-render
|
|
179
|
+
webChatRef, // RefObject - Referencia al DOM del chat
|
|
180
|
+
styleOptions, // StyleOptions - Configuración de estilos
|
|
181
|
+
// ... funciones
|
|
182
|
+
} = useChat();
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### Funciones Principales
|
|
186
|
+
|
|
187
|
+
##### `handleChangeVisibility(visible: boolean)`
|
|
188
|
+
|
|
189
|
+
Controla la visibilidad del chat.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
handleChangeVisibility(true); // Mostrar chat
|
|
193
|
+
handleChangeVisibility(false); // Ocultar chat
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
##### `initializeChat()`
|
|
197
|
+
|
|
198
|
+
Inicializa el chat embebido obteniendo tokens y configuración.
|
|
199
|
+
|
|
200
|
+
- Obtiene configuración regional
|
|
201
|
+
- Solicita token de conversación
|
|
202
|
+
- Crea la instancia de DirectLine
|
|
203
|
+
- Renderiza Web Chat con estilos personalizados
|
|
204
|
+
|
|
205
|
+
##### `restartConversation()`
|
|
206
|
+
|
|
207
|
+
Reinicia completamente la conversación utilizando el patrón React key.
|
|
208
|
+
|
|
209
|
+
- Limpia referencias actuales
|
|
210
|
+
- Regenera el chatKey para forzar remount
|
|
211
|
+
- Reinicializa la conexión
|
|
212
|
+
|
|
213
|
+
##### `cleanup()`
|
|
214
|
+
|
|
215
|
+
Limpia la instancia del chat de forma segura.
|
|
216
|
+
|
|
217
|
+
## Configuración de StyleOptions
|
|
218
|
+
|
|
219
|
+
### Opciones de Color y Tema
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
interface StyleOptions {
|
|
223
|
+
// Colores principales
|
|
224
|
+
accent: string; // Color principal (#0078D4)
|
|
225
|
+
backgroundColor: string; // Fondo del chat (#e8e9eb)
|
|
226
|
+
|
|
227
|
+
// Configuración de burbujas del bot
|
|
228
|
+
bubbleBackground: string; // Fondo de mensajes del bot
|
|
229
|
+
bubbleBorderRadius: number; // Radio de borde de burbujas
|
|
230
|
+
bubbleTextColor: string; // Color del texto del bot
|
|
231
|
+
|
|
232
|
+
// Configuración de burbujas del usuario
|
|
233
|
+
bubbleFromUserBackground: string; // Fondo de mensajes del usuario
|
|
234
|
+
bubbleFromUserBorderRadius: number; // Radio de borde del usuario
|
|
235
|
+
bubbleFromUserTextColor: string; // Color del texto del usuario
|
|
236
|
+
|
|
237
|
+
// Configuración de avatares
|
|
238
|
+
botAvatarImage: string; // URL del avatar del bot
|
|
239
|
+
botAvatarInitials: string; // Iniciales del bot
|
|
240
|
+
userAvatarImage: string; // URL del avatar del usuario
|
|
241
|
+
userAvatarInitials: string; // Iniciales del usuario
|
|
242
|
+
userAvatarBackgroundColor: string; // Color de fondo del avatar
|
|
243
|
+
|
|
244
|
+
// Caja de entrada
|
|
245
|
+
sendBoxBackground: string; // Fondo de la caja de texto
|
|
246
|
+
sendBoxBorderTop: string; // Borde superior de la caja
|
|
247
|
+
sendBoxButtonColor: string; // Color del botón de enviar
|
|
248
|
+
sendBoxHeight: number; // Altura de la caja (50px)
|
|
249
|
+
|
|
250
|
+
// Animaciones
|
|
251
|
+
typingAnimationBackgroundImage: string; // GIF de animación de escritura
|
|
252
|
+
typingAnimationDuration: number; // Duración de la animación (ms)
|
|
253
|
+
typingAnimationHeight: number; // Altura de la animación
|
|
254
|
+
typingAnimationWidth: number; // Ancho de la animación
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Categorías de Configuración
|
|
259
|
+
|
|
260
|
+
#### **Diseño y Layout**
|
|
261
|
+
|
|
262
|
+
- `avatarSize`: Tamaño de avatares (31px)
|
|
263
|
+
- `bubbleMessageMaxWidth`: Ancho máximo de burbujas (480px)
|
|
264
|
+
- `paddingRegular`: Padding estándar (10px)
|
|
265
|
+
|
|
266
|
+
#### **Tipografía**
|
|
267
|
+
|
|
268
|
+
- `primaryFont`: Fuente principal del chat
|
|
269
|
+
- `monospaceFont`: Fuente para código (Consolas)
|
|
270
|
+
- `fontSizeSmall`: Tamaño de fuente pequeña (70%)
|
|
271
|
+
|
|
272
|
+
#### **Interactividad**
|
|
273
|
+
|
|
274
|
+
- `suggestedActionBackgroundColor`: Color de acciones sugeridas
|
|
275
|
+
- `suggestedActionLayout`: Layout de acciones ('flow', 'stacked', 'carousel')
|
|
276
|
+
- `hideUploadButton`: Ocultar botón de subir archivos
|
|
277
|
+
|
|
278
|
+
#### **Animaciones y Feedback**
|
|
279
|
+
|
|
280
|
+
- `spinnerAnimationHeight/Width`: Dimensiones del spinner (16px)
|
|
281
|
+
- `autoScrollSnapOnPage`: Auto-scroll en nuevos mensajes
|
|
282
|
+
|
|
283
|
+
## Tipos e Interfaces
|
|
284
|
+
|
|
285
|
+
### `StyleOptions`
|
|
286
|
+
|
|
287
|
+
Interface completa para la configuración de estilos del Web Chat.
|
|
288
|
+
|
|
289
|
+
### `WebChatAction`
|
|
290
|
+
|
|
291
|
+
Define las acciones disponibles para el store de Web Chat:
|
|
292
|
+
|
|
293
|
+
- `DIRECT_LINE/CONNECT_FULFILLED`: Conexión establecida
|
|
294
|
+
- `DIRECT_LINE/POST_ACTIVITY`: Enviar actividad/mensaje
|
|
295
|
+
- `DIRECT_LINE/INCOMING_ACTIVITY`: Recibir actividad/mensaje
|
|
296
|
+
|
|
297
|
+
### `WebChatStore`
|
|
298
|
+
|
|
299
|
+
Interface para el store personalizado con middleware para manejo de eventos y filtros.
|
|
300
|
+
|
|
301
|
+
### `WebChatLib`
|
|
302
|
+
|
|
303
|
+
Interface para la biblioteca global de Web Chat con métodos de creación y renderizado.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Notas de Implementación
|
|
308
|
+
|
|
309
|
+
1. **Seguridad**: El componente incluye validación de tokens y manejo de errores robusto
|
|
310
|
+
2. **Performance**: Utiliza el patrón React key para reinicializaciones eficientes
|
|
311
|
+
3. **Accesibilidad**: Incluye labels ARIA y soporte para navegación por teclado
|
|
312
|
+
4. **Responsive**: Diseño adaptable para diferentes dispositivos
|
|
313
|
+
5. **Temas**: Integración completa con el sistema de temas de la aplicación
|
|
314
|
+
|
|
315
|
+
## Troubleshooting
|
|
316
|
+
|
|
317
|
+
### Problemas Comunes
|
|
318
|
+
|
|
319
|
+
1. **Chat no se inicializa**: Verificar `TOKEN_AGENTE_URL` en `.env`
|
|
320
|
+
2. **Estilos no se aplican**: Verificar variables CSS disponibles
|
|
321
|
+
3. **Errores de conexión**: Revisar configuración de CORS y headers de seguridad
|
|
322
|
+
4. **Imágenes no cargan**: Verificar rutas en carpeta `public/`
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// src/server/actions.ts
|
|
2
2
|
import "@agentcrafta/core";
|
|
3
|
-
var
|
|
3
|
+
var getTokenEndpoint = () => {
|
|
4
|
+
const value = process.env.TOKEN_AGENTE_URL;
|
|
5
|
+
if (!value || value.trim() === "") {
|
|
6
|
+
throw new Error("Token endpoint no configurado");
|
|
7
|
+
}
|
|
8
|
+
return value;
|
|
9
|
+
};
|
|
4
10
|
var getRegionalSettings = async () => {
|
|
11
|
+
const tokenEndpoint = getTokenEndpoint();
|
|
5
12
|
if (!tokenEndpoint || tokenEndpoint.trim() === "") {
|
|
6
13
|
throw new Error("Token endpoint no configurado");
|
|
7
14
|
}
|
|
@@ -21,6 +28,7 @@ var getRegionalSettings = async () => {
|
|
|
21
28
|
return data;
|
|
22
29
|
};
|
|
23
30
|
var getConversationToken = async () => {
|
|
31
|
+
const tokenEndpoint = getTokenEndpoint();
|
|
24
32
|
if (!tokenEndpoint || tokenEndpoint.trim() === "") {
|
|
25
33
|
throw new Error("Token endpoint no configurado");
|
|
26
34
|
}
|
|
@@ -66,4 +74,4 @@ export {
|
|
|
66
74
|
getChatStoreConfig,
|
|
67
75
|
logChatError
|
|
68
76
|
};
|
|
69
|
-
//# sourceMappingURL=chunk-
|
|
77
|
+
//# sourceMappingURL=chunk-RKYHRGFI.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\nconst getTokenEndpoint = () => {\r\n const value = process.env.TOKEN_AGENTE_URL;\r\n if (!value || value.trim() === \"\") {\r\n throw new Error(\"Token endpoint no configurado\");\r\n }\r\n return value;\r\n};\r\n//#region Inicializar Chat\r\nexport const getRegionalSettings = async () => {\r\n const tokenEndpoint = getTokenEndpoint();\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 const tokenEndpoint = getTokenEndpoint();\r\n\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;AAEvC,IAAM,mBAAmB,MAAM;AAC7B,QAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAI,CAAC,SAAS,MAAM,KAAK,MAAM,IAAI;AACjC,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,SAAO;AACT;AAEO,IAAM,sBAAsB,YAAY;AAC7C,QAAM,gBAAgB,iBAAiB;AACvC,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,YAA6B;AAC/D,QAAM,gBAAgB,iBAAiB;AAEvC,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,7 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { WebChatLib, StyleOptions } from '@agentcrafta/core';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
export { getChatStoreConfig, getConversationToken, getRegionalSettings, logChatError } from './server/index.js';
|
|
5
3
|
|
|
6
4
|
declare global {
|
|
7
5
|
interface Window {
|
|
@@ -24,92 +22,4 @@ type ChatProps = {
|
|
|
24
22
|
*/
|
|
25
23
|
declare const Chat: ({ botName, show, logoUrl, styleOptions, }: ChatProps) => react_jsx_runtime.JSX.Element | null;
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
isVisible: boolean;
|
|
29
|
-
isRestarting: boolean;
|
|
30
|
-
chatKey: number;
|
|
31
|
-
webChatRef: React.RefObject<HTMLDivElement | null>;
|
|
32
|
-
styleOptionsMerged: {
|
|
33
|
-
accent: string;
|
|
34
|
-
autoScrollSnapOnPage: boolean;
|
|
35
|
-
autoScrollSnapOnPageOffset: number;
|
|
36
|
-
avatarBorderRadius: string;
|
|
37
|
-
avatarSize: number;
|
|
38
|
-
backgroundColor: string;
|
|
39
|
-
botAvatarBackgroundColor: string;
|
|
40
|
-
botAvatarImage: string;
|
|
41
|
-
botAvatarInitials: string;
|
|
42
|
-
bubbleAttachmentMaxWidth: number;
|
|
43
|
-
bubbleAttachmentMinWidth: number;
|
|
44
|
-
bubbleBackground: string;
|
|
45
|
-
bubbleBorderColor: string;
|
|
46
|
-
bubbleBorderRadius: number;
|
|
47
|
-
bubbleBorderStyle: string;
|
|
48
|
-
bubbleBorderWidth: number;
|
|
49
|
-
bubbleFromUserBackground: string;
|
|
50
|
-
bubbleFromUserBorderColor: string;
|
|
51
|
-
bubbleFromUserBorderRadius: number;
|
|
52
|
-
bubbleFromUserBorderStyle: string;
|
|
53
|
-
bubbleFromUserBorderWidth: number;
|
|
54
|
-
bubbleFromUserNubOffset: number;
|
|
55
|
-
bubbleFromUserNubSize: number;
|
|
56
|
-
bubbleFromUserTextColor: string;
|
|
57
|
-
bubbleImageHeight: number;
|
|
58
|
-
bubbleImageMaxHeight: number;
|
|
59
|
-
bubbleImageMinHeight: number;
|
|
60
|
-
bubbleMessageMaxWidth: number;
|
|
61
|
-
bubbleMessageMinWidth: number;
|
|
62
|
-
bubbleMinHeight: number;
|
|
63
|
-
bubbleNubOffset: number;
|
|
64
|
-
bubbleTextColor: string;
|
|
65
|
-
emojiSet: boolean;
|
|
66
|
-
fontSizeSmall: string;
|
|
67
|
-
hideUploadButton: boolean;
|
|
68
|
-
messageActivityWordBreak: string;
|
|
69
|
-
monospaceFont: string;
|
|
70
|
-
paddingRegular: number;
|
|
71
|
-
paddingWide: number;
|
|
72
|
-
primaryFont: string | null;
|
|
73
|
-
sendBoxBackground: string;
|
|
74
|
-
sendBoxBorderTop: string;
|
|
75
|
-
sendBoxButtonColor: string;
|
|
76
|
-
sendBoxButtonColorOnHover: string;
|
|
77
|
-
sendBoxButtonShadeBorderRadius: number;
|
|
78
|
-
sendBoxButtonShadeColorOnHover: string;
|
|
79
|
-
sendBoxHeight: number;
|
|
80
|
-
sendBoxPlaceholderColor: string;
|
|
81
|
-
sendBoxTextColor: string;
|
|
82
|
-
showAvatarInGroup: string;
|
|
83
|
-
spinnerAnimationHeight: number;
|
|
84
|
-
spinnerAnimationPadding: number;
|
|
85
|
-
spinnerAnimationWidth: number;
|
|
86
|
-
subtleColor: string;
|
|
87
|
-
suggestedActionBackgroundColor: string;
|
|
88
|
-
suggestedActionBackgroundColorOnHover: string;
|
|
89
|
-
suggestedActionBorderColor: string;
|
|
90
|
-
suggestedActionBorderRadius: number;
|
|
91
|
-
suggestedActionBorderWidth: number;
|
|
92
|
-
suggestedActionLayout: string;
|
|
93
|
-
suggestedActionTextColor: string;
|
|
94
|
-
typingAnimationBackgroundImage: string;
|
|
95
|
-
typingAnimationDuration: number;
|
|
96
|
-
typingAnimationHeight: number;
|
|
97
|
-
typingAnimationWidth: number;
|
|
98
|
-
userAvatarBackgroundColor: string;
|
|
99
|
-
userAvatarImage: string;
|
|
100
|
-
userAvatarInitials: string;
|
|
101
|
-
};
|
|
102
|
-
handleChangeVisibility: (visible: boolean) => void;
|
|
103
|
-
initializeChat: () => Promise<void>;
|
|
104
|
-
restartConversation: () => Promise<void>;
|
|
105
|
-
cleanup: () => void;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Convierte una variable CSS (ej: "var(--primary)") a su equivalente en formato hex
|
|
110
|
-
* @param cssVar - String en formato "var(--variable-name)"
|
|
111
|
-
* @returns Color en formato hex (ej: "#0078d4") o el valor original si no se puede convertir
|
|
112
|
-
*/
|
|
113
|
-
declare const getCssVariableAsHex: (cssVar: string) => string;
|
|
114
|
-
|
|
115
|
-
export { Chat, getCssVariableAsHex, useChat };
|
|
25
|
+
export { Chat };
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
getConversationToken,
|
|
4
4
|
getRegionalSettings,
|
|
5
5
|
logChatError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RKYHRGFI.js";
|
|
7
7
|
|
|
8
8
|
// src/client/chat.tsx
|
|
9
9
|
import React2 from "react";
|
|
@@ -337,48 +337,7 @@ var Chat = ({
|
|
|
337
337
|
)
|
|
338
338
|
] });
|
|
339
339
|
};
|
|
340
|
-
|
|
341
|
-
// src/shared/utils/utils.ts
|
|
342
|
-
var getCssVariableAsHex = (cssVar) => {
|
|
343
|
-
if (!cssVar.startsWith("var(--")) {
|
|
344
|
-
return cssVar;
|
|
345
|
-
}
|
|
346
|
-
const variableName = cssVar.slice(4, -1);
|
|
347
|
-
try {
|
|
348
|
-
const cssValue = getComputedStyle(document.documentElement).getPropertyValue(variableName).trim();
|
|
349
|
-
if (!cssValue) {
|
|
350
|
-
console.warn(`Variable CSS ${variableName} no encontrada`);
|
|
351
|
-
return cssVar;
|
|
352
|
-
}
|
|
353
|
-
const hslValue = `hsl(${cssValue})`;
|
|
354
|
-
return hslToHex(hslValue);
|
|
355
|
-
} catch (error) {
|
|
356
|
-
console.error(`Error al convertir variable CSS ${cssVar}:`, error);
|
|
357
|
-
return cssVar;
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
var hslToHex = (hsl) => {
|
|
361
|
-
const tempDiv = document.createElement("div");
|
|
362
|
-
tempDiv.style.color = hsl;
|
|
363
|
-
document.body.appendChild(tempDiv);
|
|
364
|
-
const computedColor = getComputedStyle(tempDiv).color;
|
|
365
|
-
tempDiv.remove();
|
|
366
|
-
const rgbMatch = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/.exec(computedColor);
|
|
367
|
-
if (rgbMatch) {
|
|
368
|
-
const r = rgbMatch[1] ?? "0";
|
|
369
|
-
const g = rgbMatch[2] ?? "0";
|
|
370
|
-
const b = rgbMatch[3] ?? "0";
|
|
371
|
-
return `#${((1 << 24) + (Number.parseInt(r) << 16) + (Number.parseInt(g) << 8) + Number.parseInt(b)).toString(16).slice(1)}`;
|
|
372
|
-
}
|
|
373
|
-
return hsl;
|
|
374
|
-
};
|
|
375
340
|
export {
|
|
376
|
-
Chat
|
|
377
|
-
getChatStoreConfig,
|
|
378
|
-
getConversationToken,
|
|
379
|
-
getCssVariableAsHex,
|
|
380
|
-
getRegionalSettings,
|
|
381
|
-
logChatError,
|
|
382
|
-
useChat
|
|
341
|
+
Chat
|
|
383
342
|
};
|
|
384
343
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/chat.tsx","../src/client/use-chat.ts","../src/shared/utils/utils.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};\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","/**\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":"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","names":["React","React"]}
|
|
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};\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"],"mappings":"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","names":["React","React"]}
|
package/dist/server/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/actions.ts"],"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"],"mappings":";AAEA,OAAuC;AAEvC,IAAM,gBAAgB,QAAQ,IAAI,oBAAoB;AAG/C,IAAM,sBAAsB,YAAY;AAC7C,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,YAA6B;AAC/D,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":[]}
|