@agentcrafta/chat-next 0.0.11 → 0.0.13
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 +271 -39
- package/dist/index.d.ts +1 -8
- package/dist/index.js +1 -37
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -15,6 +15,8 @@ Este componente utiliza el Web Chat de Bot Framework para comunicarse con Power
|
|
|
15
15
|
- [Hook useChat](#hook-usechat)
|
|
16
16
|
- [Configuración de StyleOptions](#configuración-de-styleoptions)
|
|
17
17
|
- [Tipos y Interfaces](#tipos-y-interfaces)
|
|
18
|
+
- [Styles](#styles)
|
|
19
|
+
- [Limitaciones y Consideraciones](#limitaciones-y-consideraciones)
|
|
18
20
|
|
|
19
21
|
## Instalación y Configuración
|
|
20
22
|
|
|
@@ -24,12 +26,15 @@ Configure las siguientes variables en su archivo `.env.local` para desarrollo lo
|
|
|
24
26
|
|
|
25
27
|
```env
|
|
26
28
|
# URL del endpoint para obtener tokens del agente conversacional
|
|
29
|
+
|
|
27
30
|
TOKEN_AGENTE_URL=https://your-bot-endpoint.com/powervirtualagents/botsbyschema/...
|
|
31
|
+
# o
|
|
32
|
+
NEXT_PUBLIC_TOKEN_AGENTE_URL=https://your-bot-endpoint.com/powervirtualagents/botsbyschema/...
|
|
28
33
|
```
|
|
29
34
|
|
|
30
|
-
Para PRODUCCIÓN
|
|
35
|
+
Para **PRODUCCIÓN**, asegúrese de establecer esta variable en su entorno de despliegue.
|
|
31
36
|
|
|
32
|
-
**Importante**: La variable
|
|
37
|
+
**Importante**: La variable debe apuntar al endpoint completo de Power Virtual Agents que incluye el esquema del bot y la API version.
|
|
33
38
|
|
|
34
39
|
## Uso del Componente
|
|
35
40
|
|
|
@@ -43,25 +48,39 @@ Para PRODUCCIÓN, asegúrese de establecer estas variables en su entorno de desp
|
|
|
43
48
|
|
|
44
49
|
### Props del Componente
|
|
45
50
|
|
|
46
|
-
| Prop | Tipo
|
|
47
|
-
| -------------- |
|
|
48
|
-
| `botName` | `string`
|
|
49
|
-
| `logoUrl` | `string`
|
|
50
|
-
| `show` | `boolean`
|
|
51
|
-
| `styleOptions` | `StyleOptions`
|
|
51
|
+
| Prop | Tipo | Default | Descripción |
|
|
52
|
+
| -------------- | -------------------------------------------------------------- | ---------------- | ---------------------------------------------------------------- |
|
|
53
|
+
| `botName` | `string` | `"Agent"` | Nombre que se mostrará en la cabecera del chat |
|
|
54
|
+
| `logoUrl` | `string` | `undefined` | URL del logo que se mostrará junto al nombre del bot (opcional) |
|
|
55
|
+
| `show` | `boolean` | `true` | Indica si el chat debe mostrarse o no (por defecto es true) |
|
|
56
|
+
| `styleOptions` | `StyleOptions` | `undefined` | Opciones de estilo personalizadas para el chat (opcional) |
|
|
57
|
+
| `entryPoint` | `string` | `undefined` | Punto de entrada para la conversación (opcional) |
|
|
58
|
+
| `position` | `"bottom-right" \| "bottom-left" \| "top-right" \| "top-left"` | `"bottom-right"` | Posición del chat en la pantalla (por defecto es "bottom-right") |
|
|
59
|
+
| `chatButton` | `(props: ChatButtonProps) => React.ReactNode` | `undefined` | Elemento de botón personalizado para abrir el chat (opcional) |
|
|
52
60
|
|
|
53
61
|
### Importación y Uso
|
|
54
62
|
|
|
63
|
+
Importante: Componente de tipo Client Component, debe ser utilizado dentro de un componente con `'use client'` en Next.js.
|
|
64
|
+
|
|
65
|
+
En el archivo **layout** o en la página donde desea mostrar el chat, importe los estilos del componente
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import "@agentcrafta/chat-next/styles.css";
|
|
69
|
+
```
|
|
70
|
+
|
|
55
71
|
#### Básico
|
|
56
72
|
|
|
57
73
|
```tsx
|
|
58
|
-
import { Chat } from "
|
|
74
|
+
import { Chat } from "@agentcrafta/chat-next";
|
|
59
75
|
|
|
60
76
|
export default function HomePage() {
|
|
61
77
|
return (
|
|
62
78
|
<div>
|
|
63
79
|
<h1>Mi Aplicación</h1>
|
|
64
|
-
<Chat
|
|
80
|
+
<Chat
|
|
81
|
+
entryPoint={process.env.NEXT_PUBLIC_TOKEN_AGENTE_URL || ""}
|
|
82
|
+
botName="Asistente Virtual"
|
|
83
|
+
/>
|
|
65
84
|
</div>
|
|
66
85
|
);
|
|
67
86
|
}
|
|
@@ -70,7 +89,8 @@ export default function HomePage() {
|
|
|
70
89
|
#### Avanzado con Personalización de Estilos
|
|
71
90
|
|
|
72
91
|
```tsx
|
|
73
|
-
|
|
92
|
+
"use client";
|
|
93
|
+
import { Chat } from "@agentcrafta/chat-next";
|
|
74
94
|
|
|
75
95
|
export default function HomePage() {
|
|
76
96
|
return (
|
|
@@ -78,26 +98,14 @@ export default function HomePage() {
|
|
|
78
98
|
<h1>Mi Aplicación</h1>
|
|
79
99
|
<Chat
|
|
80
100
|
botName="Asistente Virtual"
|
|
81
|
-
logoUrl="logo.svg"
|
|
101
|
+
logoUrl="/logo.svg"
|
|
102
|
+
entryPoint={process.env.NEXT_PUBLIC_TOKEN_AGENTE_URL || ""}
|
|
82
103
|
styleOptions={{
|
|
83
|
-
|
|
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)"),
|
|
104
|
+
backgroundColor: "#7e0f0f",
|
|
100
105
|
}}
|
|
106
|
+
chatButton={({ isVisible, toggle }) => (
|
|
107
|
+
<button onClick={toggle}>{isVisible ? "Cerrar" : "Abrir"}</button>
|
|
108
|
+
)}
|
|
101
109
|
/>
|
|
102
110
|
</div>
|
|
103
111
|
);
|
|
@@ -106,23 +114,25 @@ export default function HomePage() {
|
|
|
106
114
|
|
|
107
115
|
## Server Actions
|
|
108
116
|
|
|
109
|
-
|
|
117
|
+
De manera informativa, no se expone directamente la API de Server Actions, pero el componente las utiliza internamente para obtener tokens, configuración y registrar errores. A continuación se describen las funciones disponibles:
|
|
118
|
+
|
|
119
|
+
### `getRegionalSettings(tokenEndpoint?: string)`
|
|
110
120
|
|
|
111
121
|
**Propósito**: Obtiene la configuración regional del bot, incluyendo las URLs de los canales disponibles.
|
|
112
122
|
|
|
113
123
|
```typescript
|
|
114
|
-
const data = await getRegionalSettings();
|
|
124
|
+
const data = await getRegionalSettings(tokenEndpoint?: string);
|
|
115
125
|
console.log(data.channelUrlsById.directline); // URL de DirectLine
|
|
116
126
|
```
|
|
117
127
|
|
|
118
128
|
**Retorna**: Configuración regional con URLs de canales disponibles.
|
|
119
129
|
|
|
120
|
-
### `getConversationToken()`
|
|
130
|
+
### `getConversationToken(tokenEndpoint?: string)`
|
|
121
131
|
|
|
122
132
|
**Propósito**: Obtiene el token de autenticación necesario para establecer la conexión con DirectLine.
|
|
123
133
|
|
|
124
134
|
```typescript
|
|
125
|
-
const token = await getConversationToken();
|
|
135
|
+
const token = await getConversationToken(tokenEndpoint?: string);
|
|
126
136
|
```
|
|
127
137
|
|
|
128
138
|
**Retorna**: Token de conversación válido para DirectLine.
|
|
@@ -167,9 +177,10 @@ await logChatError({
|
|
|
167
177
|
|
|
168
178
|
### Props del Hook
|
|
169
179
|
|
|
170
|
-
| Prop
|
|
171
|
-
|
|
|
172
|
-
| `
|
|
180
|
+
| Prop | Tipo | Default | Descripción |
|
|
181
|
+
| ------------------- | -------------- | ------------- | --------------------------------------------------------- |
|
|
182
|
+
| `styleOptionsProps` | `StyleOptions` | `undefined` | Opciones de estilo personalizadas para el chat (opcional) |
|
|
183
|
+
| `entryPoint` | `string` | **Requerido** | Punto de entrada para la conversación |
|
|
173
184
|
|
|
174
185
|
```typescript
|
|
175
186
|
const {
|
|
@@ -177,7 +188,7 @@ const {
|
|
|
177
188
|
isRestarting, // boolean - Estado de reinicio
|
|
178
189
|
chatKey, // number - Key para forzar re-render
|
|
179
190
|
webChatRef, // RefObject - Referencia al DOM del chat
|
|
180
|
-
|
|
191
|
+
styleOptionsMerged, // StyleOptions - Configuración de estilos
|
|
181
192
|
// ... funciones
|
|
182
193
|
} = useChat();
|
|
183
194
|
```
|
|
@@ -304,19 +315,240 @@ Interface para la biblioteca global de Web Chat con métodos de creación y rend
|
|
|
304
315
|
|
|
305
316
|
---
|
|
306
317
|
|
|
318
|
+
## Styles
|
|
319
|
+
|
|
320
|
+
El componente usa su propio css interno.
|
|
321
|
+
|
|
322
|
+
```css
|
|
323
|
+
/* Estilos base para AgentCrafta Chat */
|
|
324
|
+
.agentcrafta-chat-container {
|
|
325
|
+
position: fixed;
|
|
326
|
+
z-index: 999;
|
|
327
|
+
display: flex;
|
|
328
|
+
align-items: flex-end;
|
|
329
|
+
gap: 1rem;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/* Bottom Right: Chat a la izquierda, botón a la derecha */
|
|
333
|
+
.agentcrafta-chat-container.bottom-right {
|
|
334
|
+
bottom: 2rem;
|
|
335
|
+
right: 2rem;
|
|
336
|
+
flex-direction: row;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Bottom Left: Botón a la izquierda, chat a la derecha */
|
|
340
|
+
.agentcrafta-chat-container.bottom-left {
|
|
341
|
+
bottom: 2rem;
|
|
342
|
+
left: 2rem;
|
|
343
|
+
flex-direction: row-reverse;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Top Right: Chat a la izquierda, botón a la derecha */
|
|
347
|
+
.agentcrafta-chat-container.top-right {
|
|
348
|
+
top: 2rem;
|
|
349
|
+
right: 2rem;
|
|
350
|
+
flex-direction: row;
|
|
351
|
+
align-items: flex-start;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* Top Left: Botón a la izquierda, chat a la derecha */
|
|
355
|
+
.agentcrafta-chat-container.top-left {
|
|
356
|
+
top: 2rem;
|
|
357
|
+
left: 2rem;
|
|
358
|
+
flex-direction: row-reverse;
|
|
359
|
+
align-items: flex-start;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.agentcrafta-chat-window {
|
|
363
|
+
height: 520px;
|
|
364
|
+
width: 450px;
|
|
365
|
+
overflow: hidden;
|
|
366
|
+
border-radius: 1rem;
|
|
367
|
+
background-color: white;
|
|
368
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
369
|
+
transition: all 0.3s ease-in-out;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.agentcrafta-chat-window.bottom-right,
|
|
373
|
+
.agentcrafta-chat-window.bottom-left {
|
|
374
|
+
transform-origin: bottom;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.agentcrafta-chat-window.top-right,
|
|
378
|
+
.agentcrafta-chat-window.top-left {
|
|
379
|
+
transform-origin: top;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.agentcrafta-chat-window.visible {
|
|
383
|
+
transform: scale(1);
|
|
384
|
+
opacity: 1;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.agentcrafta-chat-window.hidden {
|
|
388
|
+
transform: scale(0.95);
|
|
389
|
+
opacity: 0;
|
|
390
|
+
pointer-events: none;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.agentcrafta-chat-header {
|
|
394
|
+
display: flex;
|
|
395
|
+
height: 3.5rem;
|
|
396
|
+
align-items: center;
|
|
397
|
+
justify-content: space-between;
|
|
398
|
+
padding: 0 1.25rem;
|
|
399
|
+
background-color: var(--primary-color, #0066cc);
|
|
400
|
+
color: white;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.agentcrafta-chat-header-content {
|
|
404
|
+
display: flex;
|
|
405
|
+
align-items: center;
|
|
406
|
+
gap: 0.75rem;
|
|
407
|
+
font-size: 1rem;
|
|
408
|
+
font-weight: 500;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.agentcrafta-chat-logo {
|
|
412
|
+
height: 1.75rem;
|
|
413
|
+
width: 1.75rem;
|
|
414
|
+
border-radius: 0.25rem;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.agentcrafta-chat-actions {
|
|
418
|
+
display: flex;
|
|
419
|
+
align-items: center;
|
|
420
|
+
gap: 0.75rem;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.agentcrafta-chat-button {
|
|
424
|
+
border-radius: 0.5rem;
|
|
425
|
+
padding: 0.5rem;
|
|
426
|
+
transition: background-color 0.2s;
|
|
427
|
+
border: none;
|
|
428
|
+
background: transparent;
|
|
429
|
+
cursor: pointer;
|
|
430
|
+
color: inherit;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.agentcrafta-chat-button:hover {
|
|
434
|
+
background-color: rgba(255, 255, 255, 0.1);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.agentcrafta-chat-button:disabled {
|
|
438
|
+
cursor: not-allowed;
|
|
439
|
+
opacity: 0.5;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.agentcrafta-chat-content {
|
|
443
|
+
position: relative;
|
|
444
|
+
height: calc(100% - 56px);
|
|
445
|
+
width: 100%;
|
|
446
|
+
background-color: #f9fafb;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.agentcrafta-chat-loading {
|
|
450
|
+
position: absolute;
|
|
451
|
+
inset: 0;
|
|
452
|
+
z-index: 10;
|
|
453
|
+
display: flex;
|
|
454
|
+
align-items: center;
|
|
455
|
+
justify-content: center;
|
|
456
|
+
background-color: rgba(249, 250, 251, 0.8);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.agentcrafta-chat-loading-content {
|
|
460
|
+
display: flex;
|
|
461
|
+
flex-direction: column;
|
|
462
|
+
align-items: center;
|
|
463
|
+
gap: 0.75rem;
|
|
464
|
+
color: #4b5563;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.agentcrafta-chat-loading-spinner {
|
|
468
|
+
height: 2rem;
|
|
469
|
+
width: 2rem;
|
|
470
|
+
animation: spin 1s linear infinite;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
@keyframes spin {
|
|
474
|
+
from {
|
|
475
|
+
transform: rotate(0deg);
|
|
476
|
+
}
|
|
477
|
+
to {
|
|
478
|
+
transform: rotate(360deg);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.agentcrafta-chat-loading-text {
|
|
483
|
+
font-size: 0.875rem;
|
|
484
|
+
font-weight: 500;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/* Estilos para el botón flotante */
|
|
488
|
+
.agentcrafta-chat-fab {
|
|
489
|
+
height: 3.5rem;
|
|
490
|
+
width: 3.5rem;
|
|
491
|
+
border-radius: 9999px;
|
|
492
|
+
background-color: var(--primary-color, #0066cc);
|
|
493
|
+
color: white;
|
|
494
|
+
border: none;
|
|
495
|
+
cursor: pointer;
|
|
496
|
+
display: flex;
|
|
497
|
+
align-items: center;
|
|
498
|
+
justify-content: center;
|
|
499
|
+
box-shadow:
|
|
500
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
|
501
|
+
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
502
|
+
transition: all 0.2s;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.agentcrafta-chat-fab:hover {
|
|
506
|
+
transform: scale(1.1);
|
|
507
|
+
box-shadow:
|
|
508
|
+
0 20px 25px -5px rgba(0, 0, 0, 0.1),
|
|
509
|
+
0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.agentcrafta-chat-fab:active {
|
|
513
|
+
transform: scale(1.05);
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Limitaciones y Consideraciones
|
|
520
|
+
|
|
521
|
+
- **Compatibilidad de Bots**: Solo funciona con bots que implementan Microsoft Bot Framework y DirectLine. No es compatible con bots de otros frameworks (e.g., Dialogflow puro, Rasa sin adaptador) a menos que se integre vía middleware personalizado. Bots no basados en Azure Bot Service o Power Virtual Agents pueden requerir ajustes adicionales.
|
|
522
|
+
- **Requisitos Técnicos**:
|
|
523
|
+
- Requiere Next.js con componentes Client ('use client').
|
|
524
|
+
- No soporta entornos sin JavaScript (e.g., bots puramente server-side).
|
|
525
|
+
- Rendimiento limitado en conexiones lentas; el chat puede fallar si el token expira (vida típica: 30 minutos).
|
|
526
|
+
- Responsive solo en navegadores modernos; no optimizado para accesibilidad avanzada (e.g., lectores de pantalla pueden necesitar ajustes).
|
|
527
|
+
|
|
528
|
+
- **Seguridad y Privacidad**:
|
|
529
|
+
- Los tokens de conversación son temporales, pero evita exponerlos en código público. El logging de errores registra datos sensibles (e.g., userId); asegúrate de cumplir con GDPR/CCPA.
|
|
530
|
+
- No incluye cifrado end-to-end; usa HTTPS obligatorio.
|
|
531
|
+
- Limitado a un chat por instancia; múltiples chats simultáneos no están soportados.
|
|
532
|
+
|
|
533
|
+
- **Mejores Prácticas**:
|
|
534
|
+
- Prueba en entornos de desarrollo antes de producción.
|
|
535
|
+
- Monitorea errores vía Server Actions; no garantiza recuperación automática de fallos críticos.
|
|
536
|
+
- Para bots personalizados, valida el endpoint manualmente para compatibilidad con DirectLine.
|
|
537
|
+
|
|
538
|
+
Si encuentras limitaciones no cubiertas, consulta la documentación de [Bot Framework](https://docs.microsoft.com/en-us/azure/bot-service/).
|
|
539
|
+
|
|
307
540
|
## Notas de Implementación
|
|
308
541
|
|
|
309
542
|
1. **Seguridad**: El componente incluye validación de tokens y manejo de errores robusto
|
|
310
543
|
2. **Performance**: Utiliza el patrón React key para reinicializaciones eficientes
|
|
311
544
|
3. **Accesibilidad**: Incluye labels ARIA y soporte para navegación por teclado
|
|
312
545
|
4. **Responsive**: Diseño adaptable para diferentes dispositivos
|
|
313
|
-
5. **Temas**: Integración completa con el sistema de temas de la aplicación
|
|
314
546
|
|
|
315
547
|
## Troubleshooting
|
|
316
548
|
|
|
317
549
|
### Problemas Comunes
|
|
318
550
|
|
|
319
551
|
1. **Chat no se inicializa**: Verificar `TOKEN_AGENTE_URL` en `.env`
|
|
320
|
-
2. **Estilos no se aplican**: Verificar variables CSS disponibles
|
|
552
|
+
2. **Estilos no se aplican**: Verificar variables CSS disponibles e importacion de estilos
|
|
321
553
|
3. **Errores de conexión**: Revisar configuración de CORS y headers de seguridad
|
|
322
554
|
4. **Imágenes no cargan**: Verificar rutas en carpeta `public/`
|
package/dist/index.d.ts
CHANGED
|
@@ -32,11 +32,4 @@ type ChatProps = {
|
|
|
32
32
|
*/
|
|
33
33
|
declare const Chat: ({ botName, show, logoUrl, chatButton, styleOptions, entryPoint, position, }: ChatProps) => React.ReactPortal | null;
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
* Convierte una variable CSS (ej: "var(--primary)") a su equivalente en formato hex
|
|
37
|
-
* @param cssVar - String en formato "var(--variable-name)"
|
|
38
|
-
* @returns Color en formato hex (ej: "#0078d4") o el valor original si no se puede convertir
|
|
39
|
-
*/
|
|
40
|
-
declare const getCssVariableAsHex: (cssVar: string) => string;
|
|
41
|
-
|
|
42
|
-
export { Chat, getCssVariableAsHex };
|
|
35
|
+
export { Chat };
|
package/dist/index.js
CHANGED
|
@@ -388,43 +388,7 @@ var Chat = ({
|
|
|
388
388
|
portalContainer
|
|
389
389
|
);
|
|
390
390
|
};
|
|
391
|
-
|
|
392
|
-
// src/shared/utils/utils.ts
|
|
393
|
-
var getCssVariableAsHex = (cssVar) => {
|
|
394
|
-
if (!cssVar.startsWith("var(--")) {
|
|
395
|
-
return cssVar;
|
|
396
|
-
}
|
|
397
|
-
const variableName = cssVar.slice(4, -1);
|
|
398
|
-
try {
|
|
399
|
-
const cssValue = getComputedStyle(document.documentElement).getPropertyValue(variableName).trim();
|
|
400
|
-
if (!cssValue) {
|
|
401
|
-
console.warn(`Variable CSS ${variableName} no encontrada`);
|
|
402
|
-
return cssVar;
|
|
403
|
-
}
|
|
404
|
-
const hslValue = `hsl(${cssValue})`;
|
|
405
|
-
return hslToHex(hslValue);
|
|
406
|
-
} catch (error) {
|
|
407
|
-
console.error(`Error al convertir variable CSS ${cssVar}:`, error);
|
|
408
|
-
return cssVar;
|
|
409
|
-
}
|
|
410
|
-
};
|
|
411
|
-
var hslToHex = (hsl) => {
|
|
412
|
-
const tempDiv = document.createElement("div");
|
|
413
|
-
tempDiv.style.color = hsl;
|
|
414
|
-
document.body.appendChild(tempDiv);
|
|
415
|
-
const computedColor = getComputedStyle(tempDiv).color;
|
|
416
|
-
tempDiv.remove();
|
|
417
|
-
const rgbMatch = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/.exec(computedColor);
|
|
418
|
-
if (rgbMatch) {
|
|
419
|
-
const r = rgbMatch[1] ?? "0";
|
|
420
|
-
const g = rgbMatch[2] ?? "0";
|
|
421
|
-
const b = rgbMatch[3] ?? "0";
|
|
422
|
-
return `#${((1 << 24) + (Number.parseInt(r) << 16) + (Number.parseInt(g) << 8) + Number.parseInt(b)).toString(16).slice(1)}`;
|
|
423
|
-
}
|
|
424
|
-
return hsl;
|
|
425
|
-
};
|
|
426
391
|
export {
|
|
427
|
-
Chat
|
|
428
|
-
getCssVariableAsHex
|
|
392
|
+
Chat
|
|
429
393
|
};
|
|
430
394
|
//# 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/client/chat-button-default.tsx","../src/shared/utils/utils.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport React from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\nimport { useChat } from \"./use-chat\";\r\nimport { type StyleOptions, type WebChatLib } from \"@agentcrafta/core\";\r\nimport { ChatButtonDefault } from \"./chat-button-default\";\r\n\r\ndeclare global {\r\n interface Window {\r\n WebChat: WebChatLib;\r\n }\r\n}\r\n\r\ntype ChatButtonProps = {\r\n isVisible: boolean;\r\n toggle: () => void;\r\n};\r\n\r\ntype ChatProps = {\r\n show?: boolean;\r\n botName?: string;\r\n logoUrl?: string;\r\n chatButton?: (props: ChatButtonProps) => React.ReactNode;\r\n styleOptions?: Partial<StyleOptions>;\r\n entryPoint: string;\r\n position?: \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\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 chatButton Elemento de botón personalizado para abrir el chat (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 * @param position Posición del chat en la pantalla (por defecto es \"bottom-right\")\r\n * @returns\r\n */\r\nexport const Chat = ({\r\n botName = \"Agent\",\r\n show = true,\r\n logoUrl,\r\n chatButton,\r\n styleOptions,\r\n entryPoint,\r\n position = \"bottom-right\",\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 const [portalContainer, setPortalContainer] =\r\n React.useState<HTMLElement | null>(null);\r\n const scriptLoadedRef = React.useRef(false);\r\n\r\n const toggle = () => handleChangeVisibility(!isVisible);\r\n\r\n const button = chatButton ? (\r\n chatButton({ isVisible, toggle })\r\n ) : (\r\n <ChatButtonDefault isVisible={isVisible} toggle={toggle} />\r\n );\r\n\r\n React.useEffect(() => {\r\n let container = document.getElementById(\"agentcrafta-chat-root\");\r\n\r\n if (!container) {\r\n container = document.createElement(\"div\");\r\n container.id = \"agentcrafta-chat-root\";\r\n document.body.appendChild(container);\r\n }\r\n\r\n setPortalContainer(container);\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n if (!show || !portalContainer) 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 }, [portalContainer, show, chatKey, initializeChat]);\r\n\r\n if (!show || !portalContainer) return null;\r\n\r\n return createPortal(\r\n <div\r\n className={`agentcrafta-chat-container ${position}`}\r\n role=\"dialog\"\r\n aria-modal=\"false\"\r\n >\r\n <div\r\n id=\"agentcrafta-chat-window\"\r\n className={`agentcrafta-chat-window ${position} ${isVisible ? \"visible\" : \"hidden\"}`}\r\n role=\"complementary\"\r\n aria-label={`Chat ${botName}`}\r\n >\r\n <div\r\n className=\"agentcrafta-chat-header\"\r\n style={{\r\n color: styleOptionsMerged.suggestedActionTextColor,\r\n }}\r\n >\r\n <div className=\"agentcrafta-chat-header-content\">\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=\"agentcrafta-chat-logo\"\r\n />\r\n )}\r\n <span>{botName}</span>\r\n </div>\r\n <div className=\"agentcrafta-chat-actions\">\r\n <button\r\n onClick={restartConversation}\r\n disabled={isRestarting}\r\n className=\"agentcrafta-chat-button\"\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=\"agentcrafta-chat-loading-spinner\"\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\r\n <button\r\n onClick={() => handleChangeVisibility(false)}\r\n className=\"agentcrafta-chat-button\"\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\r\n <div\r\n key={chatKey}\r\n ref={webChatRef}\r\n className=\"agentcrafta-chat-content\"\r\n />\r\n\r\n {isRestarting && (\r\n <div className=\"agentcrafta-chat-loading\">\r\n <div className=\"agentcrafta-chat-loading-content\">\r\n <svg\r\n className=\"agentcrafta-chat-loading-spinner\"\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=\"agentcrafta-chat-loading-text\">\r\n Reiniciando conversación...\r\n </span>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {button}\r\n </div>,\r\n portalContainer,\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","\"use client\";\r\ntype ChatButtonProps = {\r\n isVisible: boolean;\r\n toggle: () => void;\r\n};\r\n\r\nexport const ChatButtonDefault = ({ toggle, isVisible }: ChatButtonProps) => {\r\n return (\r\n <button\r\n onClick={toggle}\r\n className=\"agentcrafta-chat-fab\"\r\n aria-label={isVisible ? \"Cerrar chat\" : \"Abrir chat\"}\r\n >\r\n {isVisible ? (\r\n <svg\r\n width=\"24\"\r\n height=\"24\"\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 >\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 ) : (\r\n <svg\r\n width=\"24\"\r\n height=\"24\"\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 >\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 )}\r\n </button>\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","jsx","jsxs","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/chat.tsx","../src/client/use-chat.ts","../src/client/chat-button-default.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport React from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\nimport { useChat } from \"./use-chat\";\r\nimport { type StyleOptions, type WebChatLib } from \"@agentcrafta/core\";\r\nimport { ChatButtonDefault } from \"./chat-button-default\";\r\n\r\ndeclare global {\r\n interface Window {\r\n WebChat: WebChatLib;\r\n }\r\n}\r\n\r\ntype ChatButtonProps = {\r\n isVisible: boolean;\r\n toggle: () => void;\r\n};\r\n\r\ntype ChatProps = {\r\n show?: boolean;\r\n botName?: string;\r\n logoUrl?: string;\r\n chatButton?: (props: ChatButtonProps) => React.ReactNode;\r\n styleOptions?: Partial<StyleOptions>;\r\n entryPoint: string;\r\n position?: \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\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 chatButton Elemento de botón personalizado para abrir el chat (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 * @param position Posición del chat en la pantalla (por defecto es \"bottom-right\")\r\n * @returns\r\n */\r\nexport const Chat = ({\r\n botName = \"Agent\",\r\n show = true,\r\n logoUrl,\r\n chatButton,\r\n styleOptions,\r\n entryPoint,\r\n position = \"bottom-right\",\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 const [portalContainer, setPortalContainer] =\r\n React.useState<HTMLElement | null>(null);\r\n const scriptLoadedRef = React.useRef(false);\r\n\r\n const toggle = () => handleChangeVisibility(!isVisible);\r\n\r\n const button = chatButton ? (\r\n chatButton({ isVisible, toggle })\r\n ) : (\r\n <ChatButtonDefault isVisible={isVisible} toggle={toggle} />\r\n );\r\n\r\n React.useEffect(() => {\r\n let container = document.getElementById(\"agentcrafta-chat-root\");\r\n\r\n if (!container) {\r\n container = document.createElement(\"div\");\r\n container.id = \"agentcrafta-chat-root\";\r\n document.body.appendChild(container);\r\n }\r\n\r\n setPortalContainer(container);\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n if (!show || !portalContainer) 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 }, [portalContainer, show, chatKey, initializeChat]);\r\n\r\n if (!show || !portalContainer) return null;\r\n\r\n return createPortal(\r\n <div\r\n className={`agentcrafta-chat-container ${position}`}\r\n role=\"dialog\"\r\n aria-modal=\"false\"\r\n >\r\n <div\r\n id=\"agentcrafta-chat-window\"\r\n className={`agentcrafta-chat-window ${position} ${isVisible ? \"visible\" : \"hidden\"}`}\r\n role=\"complementary\"\r\n aria-label={`Chat ${botName}`}\r\n >\r\n <div\r\n className=\"agentcrafta-chat-header\"\r\n style={{\r\n color: styleOptionsMerged.suggestedActionTextColor,\r\n }}\r\n >\r\n <div className=\"agentcrafta-chat-header-content\">\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=\"agentcrafta-chat-logo\"\r\n />\r\n )}\r\n <span>{botName}</span>\r\n </div>\r\n <div className=\"agentcrafta-chat-actions\">\r\n <button\r\n onClick={restartConversation}\r\n disabled={isRestarting}\r\n className=\"agentcrafta-chat-button\"\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=\"agentcrafta-chat-loading-spinner\"\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\r\n <button\r\n onClick={() => handleChangeVisibility(false)}\r\n className=\"agentcrafta-chat-button\"\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\r\n <div\r\n key={chatKey}\r\n ref={webChatRef}\r\n className=\"agentcrafta-chat-content\"\r\n />\r\n\r\n {isRestarting && (\r\n <div className=\"agentcrafta-chat-loading\">\r\n <div className=\"agentcrafta-chat-loading-content\">\r\n <svg\r\n className=\"agentcrafta-chat-loading-spinner\"\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=\"agentcrafta-chat-loading-text\">\r\n Reiniciando conversación...\r\n </span>\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {button}\r\n </div>,\r\n portalContainer,\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","\"use client\";\r\ntype ChatButtonProps = {\r\n isVisible: boolean;\r\n toggle: () => void;\r\n};\r\n\r\nexport const ChatButtonDefault = ({ toggle, isVisible }: ChatButtonProps) => {\r\n return (\r\n <button\r\n onClick={toggle}\r\n className=\"agentcrafta-chat-fab\"\r\n aria-label={isVisible ? \"Cerrar chat\" : \"Abrir chat\"}\r\n >\r\n {isVisible ? (\r\n <svg\r\n width=\"24\"\r\n height=\"24\"\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 >\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 ) : (\r\n <svg\r\n width=\"24\"\r\n height=\"24\"\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 >\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 )}\r\n </button>\r\n );\r\n};\r\n"],"mappings":"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","names":["React","jsx","jsxs","React"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentcrafta/chat-next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"style": "dist/chat.style.css",
|
|
6
6
|
"sideEffects": [
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"jsdom": "^27.0.1",
|
|
47
47
|
"tsup": "^8.5.1",
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
|
-
"vitest": "^4.0.18"
|
|
49
|
+
"vitest": "^4.0.18",
|
|
50
|
+
"cpy-cli": "^5.0.0"
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {
|
|
52
53
|
"@agentcrafta/core": "^0.0.1"
|