@vezlo/assistant-chat 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 +661 -0
- package/PACKAGE_README.md +255 -0
- package/README.md +241 -0
- package/lib/api/conversation.d.ts +26 -0
- package/lib/api/conversation.js +52 -0
- package/lib/api/index.d.ts +6 -0
- package/lib/api/index.js +6 -0
- package/lib/api/message.d.ts +30 -0
- package/lib/api/message.js +53 -0
- package/lib/components/Widget.d.ts +11 -0
- package/lib/components/Widget.js +283 -0
- package/lib/components/ui/VezloFooter.d.ts +5 -0
- package/lib/components/ui/VezloFooter.js +7 -0
- package/lib/config/theme.d.ts +23 -0
- package/lib/config/theme.js +31 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +6 -0
- package/lib/types/index.d.ts +54 -0
- package/lib/types/index.js +2 -0
- package/lib/utils/index.d.ts +19 -0
- package/lib/utils/index.js +47 -0
- package/package.json +102 -0
- package/public/widget.js +159 -0
package/public/widget.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vezlo Chat Widget Embed Script
|
|
3
|
+
* This script creates an iframe that loads the chat widget from the main application
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
(function() {
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates and initializes the Vezlo Chat Widget
|
|
11
|
+
* @param {string} uuid - Unique identifier for the widget instance
|
|
12
|
+
* @param {string} baseUrl - Base URL of the Vezlo application
|
|
13
|
+
* @param {object} config - Optional configuration overrides
|
|
14
|
+
*/
|
|
15
|
+
window.addVezloChatWidget = function(uuid, baseUrl, config) {
|
|
16
|
+
try {
|
|
17
|
+
// Validate inputs
|
|
18
|
+
if (!uuid || typeof uuid !== 'string') {
|
|
19
|
+
console.error('[Vezlo Widget] Invalid UUID provided');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!baseUrl || typeof baseUrl !== 'string') {
|
|
24
|
+
console.error('[Vezlo Widget] Invalid base URL provided');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Default configuration
|
|
29
|
+
const defaultConfig = {
|
|
30
|
+
theme: 'light',
|
|
31
|
+
position: 'bottom-right',
|
|
32
|
+
size: { width: 420, height: 600 },
|
|
33
|
+
title: 'AI Assistant',
|
|
34
|
+
subtitle: 'How can I help you today?',
|
|
35
|
+
placeholder: 'Type your message...',
|
|
36
|
+
welcomeMessage: "Hello! I'm your AI assistant. How can I help you today?",
|
|
37
|
+
apiUrl: baseUrl,
|
|
38
|
+
apiKey: '',
|
|
39
|
+
themeColor: '#059669'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Merge with user config
|
|
43
|
+
const mergedConfig = Object.assign({}, defaultConfig, config || {});
|
|
44
|
+
|
|
45
|
+
// Build iframe URL with config
|
|
46
|
+
const configParam = encodeURIComponent(JSON.stringify(mergedConfig));
|
|
47
|
+
const iframeUrl = `${baseUrl}/widget/${uuid}?config=${configParam}`;
|
|
48
|
+
|
|
49
|
+
// Create iframe element
|
|
50
|
+
const iframe = document.createElement('iframe');
|
|
51
|
+
iframe.src = iframeUrl;
|
|
52
|
+
iframe.id = `vezlo-chat-widget-${uuid}`;
|
|
53
|
+
iframe.setAttribute('frameborder', '0');
|
|
54
|
+
iframe.setAttribute('allow', 'clipboard-read; clipboard-write');
|
|
55
|
+
|
|
56
|
+
// Position styles based on config
|
|
57
|
+
const position = mergedConfig.position || 'bottom-right';
|
|
58
|
+
const size = mergedConfig.size || { width: 420, height: 600 };
|
|
59
|
+
const margin = 20;
|
|
60
|
+
|
|
61
|
+
let positionStyles = '';
|
|
62
|
+
let transformOrigin = 'bottom right'; // Default for bottom-right
|
|
63
|
+
|
|
64
|
+
switch (position) {
|
|
65
|
+
case 'bottom-right':
|
|
66
|
+
positionStyles = `bottom: ${margin}px; right: ${margin}px;`;
|
|
67
|
+
transformOrigin = 'bottom right';
|
|
68
|
+
break;
|
|
69
|
+
case 'bottom-left':
|
|
70
|
+
positionStyles = `bottom: ${margin}px; left: ${margin}px;`;
|
|
71
|
+
transformOrigin = 'bottom left';
|
|
72
|
+
break;
|
|
73
|
+
case 'top-right':
|
|
74
|
+
positionStyles = `top: ${margin}px; right: ${margin}px;`;
|
|
75
|
+
transformOrigin = 'top right';
|
|
76
|
+
break;
|
|
77
|
+
case 'top-left':
|
|
78
|
+
positionStyles = `top: ${margin}px; left: ${margin}px;`;
|
|
79
|
+
transformOrigin = 'top left';
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
positionStyles = `bottom: ${margin}px; right: ${margin}px;`;
|
|
83
|
+
transformOrigin = 'bottom right';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Apply initial styles (sized to match widget bubble)
|
|
87
|
+
iframe.style.cssText = `
|
|
88
|
+
position: fixed;
|
|
89
|
+
${positionStyles}
|
|
90
|
+
width: 64px;
|
|
91
|
+
height: 64px;
|
|
92
|
+
border: none;
|
|
93
|
+
background: transparent;
|
|
94
|
+
z-index: 2147483647;
|
|
95
|
+
pointer-events: none;
|
|
96
|
+
transform-origin: ${transformOrigin};
|
|
97
|
+
border-radius: 50%;
|
|
98
|
+
overflow: hidden;
|
|
99
|
+
`;
|
|
100
|
+
|
|
101
|
+
// Allow interaction with iframe content and suppress inner scrollbars
|
|
102
|
+
iframe.addEventListener('load', function() {
|
|
103
|
+
iframe.style.pointerEvents = 'auto';
|
|
104
|
+
try {
|
|
105
|
+
const doc = iframe.contentDocument;
|
|
106
|
+
if (doc) {
|
|
107
|
+
doc.documentElement.style.margin = '0';
|
|
108
|
+
doc.documentElement.style.padding = '0';
|
|
109
|
+
doc.documentElement.style.overflow = 'hidden';
|
|
110
|
+
if (doc.body) {
|
|
111
|
+
doc.body.style.margin = '0';
|
|
112
|
+
doc.body.style.padding = '0';
|
|
113
|
+
doc.body.style.overflow = 'hidden';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
} catch (e) {
|
|
117
|
+
// Cross-origin iframes won't allow access; safe to ignore
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Listen for messages from iframe to adjust size
|
|
122
|
+
window.addEventListener('message', function(event) {
|
|
123
|
+
if (event.data.type === 'vezlo-widget-opened') {
|
|
124
|
+
// Widget opened - expand iframe instantly (no animation)
|
|
125
|
+
iframe.style.width = size.width + 'px';
|
|
126
|
+
iframe.style.height = size.height + 'px';
|
|
127
|
+
iframe.style.borderRadius = '16px';
|
|
128
|
+
iframe.style.boxShadow = '0 20px 60px rgba(0, 0, 0, 0.15)';
|
|
129
|
+
} else if (event.data.type === 'vezlo-widget-closed') {
|
|
130
|
+
// Widget closed - shrink to bubble instantly (no animation)
|
|
131
|
+
iframe.style.width = '64px';
|
|
132
|
+
iframe.style.height = '64px';
|
|
133
|
+
iframe.style.borderRadius = '50%';
|
|
134
|
+
iframe.style.boxShadow = 'none';
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Append to body
|
|
139
|
+
document.body.appendChild(iframe);
|
|
140
|
+
|
|
141
|
+
console.log('[Vezlo Widget] Widget initialized successfully', { uuid, baseUrl });
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error('[Vezlo Widget] Error initializing widget:', error);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Auto-initialize if data attributes are present
|
|
148
|
+
window.addEventListener('DOMContentLoaded', function() {
|
|
149
|
+
const script = document.querySelector('script[data-vezlo-uuid]');
|
|
150
|
+
if (script) {
|
|
151
|
+
const uuid = script.getAttribute('data-vezlo-uuid');
|
|
152
|
+
const baseUrl = script.getAttribute('data-vezlo-url') || window.location.origin;
|
|
153
|
+
if (uuid) {
|
|
154
|
+
window.addVezloChatWidget(uuid, baseUrl);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
})();
|
|
159
|
+
|