@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.
@@ -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
+