@botuyo/chat-widget-standalone 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +438 -0
- package/dist/ChatWidget-B6W68bT_.js +33 -0
- package/dist/ChatWidget-B6W68bT_.js.map +1 -0
- package/dist/botuyo-chat.css +1 -0
- package/dist/botuyo-chat.js +2 -0
- package/dist/botuyo-chat.js.map +1 -0
- package/dist/browser-image-compression-CsxM8KJN.js +2 -0
- package/dist/browser-image-compression-CsxM8KJN.js.map +1 -0
- package/dist/chunk-audio-CgduwQLl.js +10 -0
- package/dist/chunk-audio-CgduwQLl.js.map +1 -0
- package/dist/chunk-chat-ui-EAAXXtnK.js +89 -0
- package/dist/chunk-chat-ui-EAAXXtnK.js.map +1 -0
- package/dist/chunk-gallery-B9sBFYYc.js +24 -0
- package/dist/chunk-gallery-B9sBFYYc.js.map +1 -0
- package/dist/chunk-markdown-xGy7kpWU.js +2 -0
- package/dist/chunk-markdown-xGy7kpWU.js.map +1 -0
- package/dist/stats.html +4949 -0
- package/dist/vendor-react-CtfcjTlq.js +2 -0
- package/dist/vendor-react-CtfcjTlq.js.map +1 -0
- package/dist/vendor-socket-DMqyM-90.js +2 -0
- package/dist/vendor-socket-DMqyM-90.js.map +1 -0
- package/examples/cdn-example.html +226 -0
- package/examples/nextjs-example.js +188 -0
- package/examples/nextjs-example.tsx +229 -0
- package/examples/react-example.js +168 -0
- package/examples/react-example.tsx +221 -0
- package/package.json +147 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="es">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Ejemplo CDN - BotUyo Chat Widget</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
16
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
padding: 20px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.container {
|
|
25
|
+
background: white;
|
|
26
|
+
padding: 40px;
|
|
27
|
+
border-radius: 20px;
|
|
28
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
29
|
+
max-width: 600px;
|
|
30
|
+
width: 100%;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h1 {
|
|
34
|
+
color: #333;
|
|
35
|
+
margin-bottom: 10px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
p {
|
|
39
|
+
color: #666;
|
|
40
|
+
margin-bottom: 30px;
|
|
41
|
+
line-height: 1.6;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.button-group {
|
|
45
|
+
display: flex;
|
|
46
|
+
gap: 10px;
|
|
47
|
+
flex-wrap: wrap;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
button {
|
|
51
|
+
background: #10b981;
|
|
52
|
+
color: white;
|
|
53
|
+
border: none;
|
|
54
|
+
padding: 12px 24px;
|
|
55
|
+
border-radius: 8px;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
font-size: 14px;
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
transition: all 0.3s ease;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
button:hover {
|
|
63
|
+
background: #059669;
|
|
64
|
+
transform: translateY(-2px);
|
|
65
|
+
box-shadow: 0 5px 15px rgba(16, 185, 129, 0.4);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
button:active {
|
|
69
|
+
transform: translateY(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.status {
|
|
73
|
+
margin-top: 20px;
|
|
74
|
+
padding: 15px;
|
|
75
|
+
background: #f3f4f6;
|
|
76
|
+
border-radius: 8px;
|
|
77
|
+
font-size: 14px;
|
|
78
|
+
color: #666;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.status strong {
|
|
82
|
+
color: #10b981;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
code {
|
|
86
|
+
background: #f3f4f6;
|
|
87
|
+
padding: 2px 6px;
|
|
88
|
+
border-radius: 4px;
|
|
89
|
+
font-family: 'Courier New', monospace;
|
|
90
|
+
font-size: 13px;
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
93
|
+
</head>
|
|
94
|
+
<body>
|
|
95
|
+
<div class="container">
|
|
96
|
+
<h1>🎉 Ejemplo CDN del Chat Widget</h1>
|
|
97
|
+
<p>
|
|
98
|
+
Este es un ejemplo de integración del <strong>BotUyo Chat Widget</strong> usando CDN.
|
|
99
|
+
No requiere React, Next.js ni ningún framework - solo JavaScript vanilla.
|
|
100
|
+
</p>
|
|
101
|
+
|
|
102
|
+
<div class="button-group">
|
|
103
|
+
<button onclick="if(widget) widget.open()">🚀 Abrir Chat</button>
|
|
104
|
+
<button onclick="if(widget) widget.close()">❌ Cerrar Chat</button>
|
|
105
|
+
<button onclick="if(widget) widget.toggle()">🔄 Toggle Chat</button>
|
|
106
|
+
<button onclick="sendTestMessage()">💬 Enviar Mensaje</button>
|
|
107
|
+
<button onclick="showState()">📊 Ver Estado</button>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="status" id="status">
|
|
111
|
+
<strong>Estado:</strong> Inicializando widget...
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<div style="margin-top: 30px; padding-top: 30px; border-top: 1px solid #e5e7eb;">
|
|
115
|
+
<h3 style="color: #666; margin-bottom: 10px;">Código de integración:</h3>
|
|
116
|
+
<pre style="background: #1f2937; color: #10b981; padding: 15px; border-radius: 8px; overflow-x: auto; font-size: 12px;"><code><script src="https://cdn.botuyo.com/chat-widget.js"></script>
|
|
117
|
+
<script>
|
|
118
|
+
const widget = BotUyoChat.init({
|
|
119
|
+
apiKey: 'demo-api-key',
|
|
120
|
+
apiBaseUrl: 'https://api.botuyo.com',
|
|
121
|
+
theme: {
|
|
122
|
+
primaryColor: '#10b981',
|
|
123
|
+
botName: 'Demo Bot',
|
|
124
|
+
position: 'bottom-right'
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
</script></code></pre>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<!-- IMPORTANTE: Cargar el script del widget -->
|
|
132
|
+
<!-- En producción, usar: https://cdn.botuyo.com/chat-widget.js -->
|
|
133
|
+
<script src="../dist/botuyo-chat.js"></script>
|
|
134
|
+
|
|
135
|
+
<script>
|
|
136
|
+
// Esperar a que el script esté cargado
|
|
137
|
+
let widget;
|
|
138
|
+
|
|
139
|
+
// Inicializar el widget cuando BotUyoChat esté disponible
|
|
140
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
141
|
+
if (window.BotUyoChat) {
|
|
142
|
+
widget = window.BotUyoChat.init({
|
|
143
|
+
apiKey: 'demo-api-key-12345',
|
|
144
|
+
apiBaseUrl: 'https://api.botuyo.com', // Cambiar por tu API real
|
|
145
|
+
|
|
146
|
+
theme: {
|
|
147
|
+
primaryColor: '#10b981',
|
|
148
|
+
botName: 'Demo Assistant',
|
|
149
|
+
position: 'bottom-right',
|
|
150
|
+
welcomeMessage: '¡Hola! 👋 Soy el asistente de demo. ¿En qué puedo ayudarte?',
|
|
151
|
+
inputPlaceholder: 'Escribe tu mensaje aquí...',
|
|
152
|
+
starterPrompt: '¿Necesitas ayuda? 💬',
|
|
153
|
+
borderRadius: '1rem',
|
|
154
|
+
launcherBorderRadius: '50%'
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
pageContext: {
|
|
158
|
+
page: 'Demo CDN',
|
|
159
|
+
url: window.location.href,
|
|
160
|
+
title: document.title,
|
|
161
|
+
demo: true
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
onStateChange: (isOpen) => {
|
|
165
|
+
updateStatus(`Chat ${isOpen ? 'abierto' : 'cerrado'}`);
|
|
166
|
+
console.log('Estado del chat:', isOpen);
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
onNavigate: (url) => {
|
|
170
|
+
console.log('Navegación solicitada a:', url);
|
|
171
|
+
alert(`El bot solicita navegar a: ${url}`);
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
onLogin: (userData) => {
|
|
175
|
+
console.log('Usuario autenticado:', userData);
|
|
176
|
+
updateStatus('Usuario autenticado correctamente');
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
onEvent: (eventName, data) => {
|
|
180
|
+
console.log('Evento:', eventName, data);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Actualizar estado inicial cuando el widget esté listo
|
|
185
|
+
setTimeout(() => {
|
|
186
|
+
updateStatus('Widget listo para usar ✅');
|
|
187
|
+
}, 1000);
|
|
188
|
+
} else {
|
|
189
|
+
updateStatus('❌ Error: BotUyoChat no está disponible. Verifica que el script esté cargado.');
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
// Funciones auxiliares
|
|
193
|
+
function updateStatus(message) {
|
|
194
|
+
const statusEl = document.getElementById('status');
|
|
195
|
+
statusEl.innerHTML = `<strong>Estado:</strong> ${message}`;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function sendTestMessage() {
|
|
199
|
+
if (!widget) {
|
|
200
|
+
alert('Widget no está inicializado');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
widget.sendMessage('Este es un mensaje de prueba enviado programáticamente 🎯');
|
|
204
|
+
widget.open();
|
|
205
|
+
updateStatus('Mensaje enviado programáticamente');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function showState() {
|
|
209
|
+
if (!widget) {
|
|
210
|
+
alert('Widget no está inicializado');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const state = widget.getState();
|
|
214
|
+
alert(JSON.stringify(state, null, 2));
|
|
215
|
+
updateStatus('Estado mostrado en consola');
|
|
216
|
+
console.log('Estado del widget:', state);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Ejemplo de actualización dinámica del tema
|
|
220
|
+
setTimeout(() => {
|
|
221
|
+
console.log('💡 Tip: Puedes actualizar el tema en cualquier momento:');
|
|
222
|
+
console.log('widget.update({ theme: { primaryColor: "#8b5cf6" } })');
|
|
223
|
+
}, 3000);
|
|
224
|
+
</script>
|
|
225
|
+
</body>
|
|
226
|
+
</html>
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
/**
|
|
4
|
+
* Ejemplo de uso del Chat Widget en Next.js 13+ (App Router)
|
|
5
|
+
* Con TypeScript, Server Components y Client Components
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ NOTA: Este archivo contiene MÚLTIPLES EJEMPLOS de código en secciones separadas.
|
|
8
|
+
* NO está diseñado para ejecutarse directamente - es un archivo de REFERENCIA.
|
|
9
|
+
* Copia las secciones individuales que necesites a tus propios archivos.
|
|
10
|
+
*
|
|
11
|
+
* Los errores de "Duplicate identifier" son esperados porque hay múltiples
|
|
12
|
+
* ejemplos de imports en diferentes secciones del mismo archivo.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.metadata = void 0;
|
|
16
|
+
exports.default = RootLayout;
|
|
17
|
+
exports.default = HomePage;
|
|
18
|
+
exports.ChatButton = ChatButton;
|
|
19
|
+
exports.default = ProductPage;
|
|
20
|
+
// ========== app/layout.tsx (Root Layout) ==========
|
|
21
|
+
var chat_widget_standalone_1 = require("@botuyo/chat-widget-standalone");
|
|
22
|
+
require("./globals.css");
|
|
23
|
+
exports.metadata = {
|
|
24
|
+
title: 'Mi App con Chat Widget',
|
|
25
|
+
description: 'Ejemplo de integración del Chat Widget en Next.js',
|
|
26
|
+
};
|
|
27
|
+
function RootLayout(_a) {
|
|
28
|
+
var children = _a.children;
|
|
29
|
+
return (<html lang="es">
|
|
30
|
+
<body>
|
|
31
|
+
<chat_widget_standalone_1.ChatWidgetProvider apiKey={process.env.NEXT_PUBLIC_CHAT_API_KEY} apiBaseUrl={process.env.NEXT_PUBLIC_CHAT_API_URL} theme={{
|
|
32
|
+
primaryColor: '#10b981',
|
|
33
|
+
botName: 'Asistente BotUyo',
|
|
34
|
+
position: 'bottom-right',
|
|
35
|
+
welcomeMessage: '¡Hola! 👋 ¿Cómo puedo ayudarte?',
|
|
36
|
+
bubbleStyles: {
|
|
37
|
+
launcher: {
|
|
38
|
+
pulse: true
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}} includeSEOMetadata={true} onNavigate={function (url) {
|
|
42
|
+
// Next.js navigation
|
|
43
|
+
window.location.href = url;
|
|
44
|
+
}}>
|
|
45
|
+
{children}
|
|
46
|
+
</chat_widget_standalone_1.ChatWidgetProvider>
|
|
47
|
+
</body>
|
|
48
|
+
</html>);
|
|
49
|
+
}
|
|
50
|
+
// ========== app/page.tsx (Homepage - Server Component) ==========
|
|
51
|
+
var ChatButton_1 = require("@/components/ChatButton");
|
|
52
|
+
function HomePage() {
|
|
53
|
+
return (<main className="min-h-screen bg-gradient-to-br from-blue-50 to-green-50">
|
|
54
|
+
<div className="container mx-auto px-4 py-12">
|
|
55
|
+
<h1 className="text-4xl font-bold text-center mb-8">
|
|
56
|
+
Next.js + Chat Widget
|
|
57
|
+
</h1>
|
|
58
|
+
|
|
59
|
+
<div className="max-w-2xl mx-auto bg-white p-8 rounded-lg shadow-lg">
|
|
60
|
+
<h2 className="text-2xl font-semibold mb-4">Bienvenido</h2>
|
|
61
|
+
<p className="text-gray-600 mb-6">
|
|
62
|
+
Este es un ejemplo de integración del Chat Widget en Next.js 13+
|
|
63
|
+
usando el App Router y Server/Client Components.
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
{/* Client Component con control del chat */}
|
|
67
|
+
<ChatButton_1.ChatButton />
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</main>);
|
|
71
|
+
}
|
|
72
|
+
// ========== components/ChatButton.tsx (Client Component) ==========
|
|
73
|
+
'use client';
|
|
74
|
+
var chat_widget_standalone_2 = require("@botuyo/chat-widget-standalone");
|
|
75
|
+
function ChatButton() {
|
|
76
|
+
var chat = (0, chat_widget_standalone_2.useChatWidget)();
|
|
77
|
+
return (<div className="space-y-4">
|
|
78
|
+
<div className="flex gap-3">
|
|
79
|
+
<button onClick={chat.open} className="flex-1 bg-green-500 hover:bg-green-600 text-white px-6 py-3 rounded-lg font-semibold transition">
|
|
80
|
+
Abrir Chat
|
|
81
|
+
</button>
|
|
82
|
+
|
|
83
|
+
<button onClick={function () { return chat.sendMessage('Hola, necesito información'); }} className="flex-1 bg-blue-500 hover:bg-blue-600 text-white px-6 py-3 rounded-lg font-semibold transition">
|
|
84
|
+
Mensaje Rápido
|
|
85
|
+
</button>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
{chat.unreadCount > 0 && (<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
|
89
|
+
<p className="text-yellow-800">
|
|
90
|
+
Tienes {chat.unreadCount} mensaje(s) nuevo(s)
|
|
91
|
+
</p>
|
|
92
|
+
</div>)}
|
|
93
|
+
</div>);
|
|
94
|
+
}
|
|
95
|
+
// ========== app/products/[id]/page.tsx (Dynamic Route con Context) ==========
|
|
96
|
+
'use client';
|
|
97
|
+
function ProductPage(_a) {
|
|
98
|
+
var params = _a.params;
|
|
99
|
+
return (<chat_widget_standalone_1.ChatWidgetProvider apiKey={process.env.NEXT_PUBLIC_CHAT_API_KEY} apiBaseUrl={process.env.NEXT_PUBLIC_CHAT_API_URL} pageContext={{
|
|
100
|
+
page: 'Product',
|
|
101
|
+
productId: params.id,
|
|
102
|
+
url: window.location.href,
|
|
103
|
+
// Cualquier información relevante del producto
|
|
104
|
+
}} theme={{
|
|
105
|
+
primaryColor: '#10b981',
|
|
106
|
+
welcomeMessage: "\u00BFTienes preguntas sobre este producto? \uD83D\uDECD\uFE0F",
|
|
107
|
+
}}>
|
|
108
|
+
<div>
|
|
109
|
+
<h1>Producto {params.id}</h1>
|
|
110
|
+
{/* Contenido del producto */}
|
|
111
|
+
</div>
|
|
112
|
+
</chat_widget_standalone_1.ChatWidgetProvider>);
|
|
113
|
+
}
|
|
114
|
+
// ========== .env.local ==========
|
|
115
|
+
/*
|
|
116
|
+
NEXT_PUBLIC_CHAT_API_KEY=your-api-key-here
|
|
117
|
+
NEXT_PUBLIC_CHAT_API_URL=https://api.botuyo.com
|
|
118
|
+
*/
|
|
119
|
+
// ========== next.config.js ==========
|
|
120
|
+
/*
|
|
121
|
+
/** @type {import('next').NextConfig} *\/
|
|
122
|
+
const nextConfig = {
|
|
123
|
+
reactStrictMode: true,
|
|
124
|
+
transpilePackages: ['@botuyo/chat-widget-standalone'],
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = nextConfig
|
|
128
|
+
*/
|
|
129
|
+
// ========== tsconfig.json ==========
|
|
130
|
+
/*
|
|
131
|
+
{
|
|
132
|
+
"compilerOptions": {
|
|
133
|
+
"target": "ES2020",
|
|
134
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
135
|
+
"allowJs": true,
|
|
136
|
+
"skipLibCheck": true,
|
|
137
|
+
"strict": true,
|
|
138
|
+
"forceConsistentCasingInFileNames": true,
|
|
139
|
+
"noEmit": true,
|
|
140
|
+
"esModuleInterop": true,
|
|
141
|
+
"module": "esnext",
|
|
142
|
+
"moduleResolution": "bundler",
|
|
143
|
+
"resolveJsonModule": true,
|
|
144
|
+
"isolatedModules": true,
|
|
145
|
+
"jsx": "preserve",
|
|
146
|
+
"incremental": true,
|
|
147
|
+
"plugins": [
|
|
148
|
+
{
|
|
149
|
+
"name": "next"
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"paths": {
|
|
153
|
+
"@/*": ["./src/*"]
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"include": ["next-env.d.ts", "**\/*.ts", "**\/*.tsx", ".next/types/**\/*.ts"],
|
|
157
|
+
"exclude": ["node_modules"]
|
|
158
|
+
}
|
|
159
|
+
*/
|
|
160
|
+
// ========== package.json ==========
|
|
161
|
+
/*
|
|
162
|
+
{
|
|
163
|
+
"name": "nextjs-chat-widget-example",
|
|
164
|
+
"version": "0.1.0",
|
|
165
|
+
"private": true,
|
|
166
|
+
"scripts": {
|
|
167
|
+
"dev": "next dev",
|
|
168
|
+
"build": "next build",
|
|
169
|
+
"start": "next start",
|
|
170
|
+
"lint": "next lint"
|
|
171
|
+
},
|
|
172
|
+
"dependencies": {
|
|
173
|
+
"@botuyo/chat-widget-standalone": "^1.0.0",
|
|
174
|
+
"next": "^14.0.0",
|
|
175
|
+
"react": "^18.2.0",
|
|
176
|
+
"react-dom": "^18.2.0"
|
|
177
|
+
},
|
|
178
|
+
"devDependencies": {
|
|
179
|
+
"@types/node": "^20",
|
|
180
|
+
"@types/react": "^18",
|
|
181
|
+
"@types/react-dom": "^18",
|
|
182
|
+
"autoprefixer": "^10.0.1",
|
|
183
|
+
"postcss": "^8",
|
|
184
|
+
"tailwindcss": "^3.3.0",
|
|
185
|
+
"typescript": "^5"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
*/
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Ejemplo de uso del Chat Widget en Next.js 13+ (App Router)
|
|
4
|
+
* Con TypeScript, Server Components y Client Components
|
|
5
|
+
*
|
|
6
|
+
* ⚠️ NOTA: Este archivo contiene MÚLTIPLES EJEMPLOS de código en secciones separadas.
|
|
7
|
+
* NO está diseñado para ejecutarse directamente - es un archivo de REFERENCIA.
|
|
8
|
+
* Copia las secciones individuales que necesites a tus propios archivos.
|
|
9
|
+
*
|
|
10
|
+
* Los errores de "Duplicate identifier" son esperados porque hay múltiples
|
|
11
|
+
* ejemplos de imports en diferentes secciones del mismo archivo.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// ========== app/layout.tsx (Root Layout) ==========
|
|
15
|
+
import { ChatWidgetProvider } from '@botuyo/chat-widget-standalone';
|
|
16
|
+
import type { Metadata } from 'next';
|
|
17
|
+
import './globals.css';
|
|
18
|
+
|
|
19
|
+
export const metadata: Metadata = {
|
|
20
|
+
title: 'Mi App con Chat Widget',
|
|
21
|
+
description: 'Ejemplo de integración del Chat Widget en Next.js',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default function RootLayout({
|
|
25
|
+
children,
|
|
26
|
+
}: {
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
}) {
|
|
29
|
+
return (
|
|
30
|
+
<html lang="es">
|
|
31
|
+
<body>
|
|
32
|
+
<ChatWidgetProvider
|
|
33
|
+
apiKey={process.env.NEXT_PUBLIC_CHAT_API_KEY!}
|
|
34
|
+
apiBaseUrl={process.env.NEXT_PUBLIC_CHAT_API_URL!}
|
|
35
|
+
theme={{
|
|
36
|
+
primaryColor: '#10b981',
|
|
37
|
+
botName: 'Asistente BotUyo',
|
|
38
|
+
position: 'bottom-right',
|
|
39
|
+
welcomeMessage: '¡Hola! 👋 ¿Cómo puedo ayudarte?',
|
|
40
|
+
bubbleStyles: {
|
|
41
|
+
launcher: {
|
|
42
|
+
pulse: true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}}
|
|
46
|
+
includeSEOMetadata={true}
|
|
47
|
+
onNavigate={(url) => {
|
|
48
|
+
// Next.js navigation
|
|
49
|
+
window.location.href = url;
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</ChatWidgetProvider>
|
|
54
|
+
</body>
|
|
55
|
+
</html>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ========== app/page.tsx (Homepage - Server Component) ==========
|
|
60
|
+
import { ChatButton } from '@/components/ChatButton';
|
|
61
|
+
|
|
62
|
+
export default function HomePage() {
|
|
63
|
+
return (
|
|
64
|
+
<main className="min-h-screen bg-gradient-to-br from-blue-50 to-green-50">
|
|
65
|
+
<div className="container mx-auto px-4 py-12">
|
|
66
|
+
<h1 className="text-4xl font-bold text-center mb-8">
|
|
67
|
+
Next.js + Chat Widget
|
|
68
|
+
</h1>
|
|
69
|
+
|
|
70
|
+
<div className="max-w-2xl mx-auto bg-white p-8 rounded-lg shadow-lg">
|
|
71
|
+
<h2 className="text-2xl font-semibold mb-4">Bienvenido</h2>
|
|
72
|
+
<p className="text-gray-600 mb-6">
|
|
73
|
+
Este es un ejemplo de integración del Chat Widget en Next.js 13+
|
|
74
|
+
usando el App Router y Server/Client Components.
|
|
75
|
+
</p>
|
|
76
|
+
|
|
77
|
+
{/* Client Component con control del chat */}
|
|
78
|
+
<ChatButton />
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</main>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ========== components/ChatButton.tsx (Client Component) ==========
|
|
86
|
+
'use client';
|
|
87
|
+
|
|
88
|
+
import { useChatWidget } from '@botuyo/chat-widget-standalone';
|
|
89
|
+
|
|
90
|
+
export function ChatButton() {
|
|
91
|
+
const chat = useChatWidget();
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div className="space-y-4">
|
|
95
|
+
<div className="flex gap-3">
|
|
96
|
+
<button
|
|
97
|
+
onClick={chat.open}
|
|
98
|
+
className="flex-1 bg-green-500 hover:bg-green-600 text-white px-6 py-3 rounded-lg font-semibold transition"
|
|
99
|
+
>
|
|
100
|
+
Abrir Chat
|
|
101
|
+
</button>
|
|
102
|
+
|
|
103
|
+
<button
|
|
104
|
+
onClick={() => chat.sendMessage('Hola, necesito información')}
|
|
105
|
+
className="flex-1 bg-blue-500 hover:bg-blue-600 text-white px-6 py-3 rounded-lg font-semibold transition"
|
|
106
|
+
>
|
|
107
|
+
Mensaje Rápido
|
|
108
|
+
</button>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{chat.unreadCount > 0 && (
|
|
112
|
+
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
|
|
113
|
+
<p className="text-yellow-800">
|
|
114
|
+
Tienes {chat.unreadCount} mensaje(s) nuevo(s)
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ========== app/products/[id]/page.tsx (Dynamic Route con Context) ==========
|
|
123
|
+
'use client';
|
|
124
|
+
|
|
125
|
+
import { useEffect as _useEffect } from 'react';
|
|
126
|
+
import { ChatWidgetProvider } from '@botuyo/chat-widget-standalone';
|
|
127
|
+
|
|
128
|
+
export default function ProductPage({ params }: { params: { id: string } }) {
|
|
129
|
+
return (
|
|
130
|
+
<ChatWidgetProvider
|
|
131
|
+
apiKey={process.env.NEXT_PUBLIC_CHAT_API_KEY!}
|
|
132
|
+
apiBaseUrl={process.env.NEXT_PUBLIC_CHAT_API_URL!}
|
|
133
|
+
pageContext={{
|
|
134
|
+
page: 'Product',
|
|
135
|
+
productId: params.id,
|
|
136
|
+
url: window.location.href,
|
|
137
|
+
// Cualquier información relevante del producto
|
|
138
|
+
}}
|
|
139
|
+
theme={{
|
|
140
|
+
primaryColor: '#10b981',
|
|
141
|
+
welcomeMessage: `¿Tienes preguntas sobre este producto? 🛍️`,
|
|
142
|
+
}}
|
|
143
|
+
>
|
|
144
|
+
<div>
|
|
145
|
+
<h1>Producto {params.id}</h1>
|
|
146
|
+
{/* Contenido del producto */}
|
|
147
|
+
</div>
|
|
148
|
+
</ChatWidgetProvider>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ========== .env.local ==========
|
|
153
|
+
/*
|
|
154
|
+
NEXT_PUBLIC_CHAT_API_KEY=your-api-key-here
|
|
155
|
+
NEXT_PUBLIC_CHAT_API_URL=https://api.botuyo.com
|
|
156
|
+
*/
|
|
157
|
+
|
|
158
|
+
// ========== next.config.js ==========
|
|
159
|
+
/*
|
|
160
|
+
/** @type {import('next').NextConfig} *\/
|
|
161
|
+
const nextConfig = {
|
|
162
|
+
reactStrictMode: true,
|
|
163
|
+
transpilePackages: ['@botuyo/chat-widget-standalone'],
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = nextConfig
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
// ========== tsconfig.json ==========
|
|
170
|
+
/*
|
|
171
|
+
{
|
|
172
|
+
"compilerOptions": {
|
|
173
|
+
"target": "ES2020",
|
|
174
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
175
|
+
"allowJs": true,
|
|
176
|
+
"skipLibCheck": true,
|
|
177
|
+
"strict": true,
|
|
178
|
+
"forceConsistentCasingInFileNames": true,
|
|
179
|
+
"noEmit": true,
|
|
180
|
+
"esModuleInterop": true,
|
|
181
|
+
"module": "esnext",
|
|
182
|
+
"moduleResolution": "bundler",
|
|
183
|
+
"resolveJsonModule": true,
|
|
184
|
+
"isolatedModules": true,
|
|
185
|
+
"jsx": "preserve",
|
|
186
|
+
"incremental": true,
|
|
187
|
+
"plugins": [
|
|
188
|
+
{
|
|
189
|
+
"name": "next"
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
"paths": {
|
|
193
|
+
"@/*": ["./src/*"]
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"include": ["next-env.d.ts", "**\/*.ts", "**\/*.tsx", ".next/types/**\/*.ts"],
|
|
197
|
+
"exclude": ["node_modules"]
|
|
198
|
+
}
|
|
199
|
+
*/
|
|
200
|
+
|
|
201
|
+
// ========== package.json ==========
|
|
202
|
+
/*
|
|
203
|
+
{
|
|
204
|
+
"name": "nextjs-chat-widget-example",
|
|
205
|
+
"version": "0.1.0",
|
|
206
|
+
"private": true,
|
|
207
|
+
"scripts": {
|
|
208
|
+
"dev": "next dev",
|
|
209
|
+
"build": "next build",
|
|
210
|
+
"start": "next start",
|
|
211
|
+
"lint": "next lint"
|
|
212
|
+
},
|
|
213
|
+
"dependencies": {
|
|
214
|
+
"@botuyo/chat-widget-standalone": "^1.0.0",
|
|
215
|
+
"next": "^14.0.0",
|
|
216
|
+
"react": "^18.2.0",
|
|
217
|
+
"react-dom": "^18.2.0"
|
|
218
|
+
},
|
|
219
|
+
"devDependencies": {
|
|
220
|
+
"@types/node": "^20",
|
|
221
|
+
"@types/react": "^18",
|
|
222
|
+
"@types/react-dom": "^18",
|
|
223
|
+
"autoprefixer": "^10.0.1",
|
|
224
|
+
"postcss": "^8",
|
|
225
|
+
"tailwindcss": "^3.3.0",
|
|
226
|
+
"typescript": "^5"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
*/
|