@product7/product7-js 0.1.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.
Files changed (58) hide show
  1. package/README.md +1025 -0
  2. package/dist/README.md +1025 -0
  3. package/dist/product7-js.js +14658 -0
  4. package/dist/product7-js.js.map +1 -0
  5. package/dist/product7-js.min.js +2 -0
  6. package/dist/product7-js.min.js.map +1 -0
  7. package/package.json +114 -0
  8. package/src/api/mock-data/index.js +360 -0
  9. package/src/api/services/ChangelogService.js +28 -0
  10. package/src/api/services/FeedbackService.js +44 -0
  11. package/src/api/services/HelpService.js +50 -0
  12. package/src/api/services/MessengerService.js +279 -0
  13. package/src/api/services/SurveyService.js +127 -0
  14. package/src/api/utils/helpers.js +30 -0
  15. package/src/core/APIService.js +303 -0
  16. package/src/core/BaseAPIService.js +298 -0
  17. package/src/core/EventBus.js +54 -0
  18. package/src/core/Product7.js +812 -0
  19. package/src/core/WebSocketService.js +275 -0
  20. package/src/docs/api.md +226 -0
  21. package/src/docs/example.md +461 -0
  22. package/src/docs/framework-integrations.md +714 -0
  23. package/src/docs/installation.md +281 -0
  24. package/src/index.js +894 -0
  25. package/src/styles/base.js +50 -0
  26. package/src/styles/changelog.js +665 -0
  27. package/src/styles/components.js +553 -0
  28. package/src/styles/design-tokens.js +124 -0
  29. package/src/styles/feedback.js +325 -0
  30. package/src/styles/messenger-components.js +632 -0
  31. package/src/styles/messenger-core.js +233 -0
  32. package/src/styles/messenger-features.js +169 -0
  33. package/src/styles/messenger-views.js +877 -0
  34. package/src/styles/messenger.js +17 -0
  35. package/src/styles/messengerCustomStyles.js +114 -0
  36. package/src/styles/styles.js +26 -0
  37. package/src/styles/survey.js +894 -0
  38. package/src/utils/errors.js +142 -0
  39. package/src/utils/helpers.js +219 -0
  40. package/src/widgets/BaseWidget.js +548 -0
  41. package/src/widgets/ButtonWidget.js +104 -0
  42. package/src/widgets/ChangelogWidget.js +615 -0
  43. package/src/widgets/InlineWidget.js +148 -0
  44. package/src/widgets/MessengerWidget.js +979 -0
  45. package/src/widgets/SurveyWidget.js +1325 -0
  46. package/src/widgets/TabWidget.js +45 -0
  47. package/src/widgets/WidgetFactory.js +70 -0
  48. package/src/widgets/messenger/MessengerState.js +323 -0
  49. package/src/widgets/messenger/components/MessengerLauncher.js +124 -0
  50. package/src/widgets/messenger/components/MessengerPanel.js +111 -0
  51. package/src/widgets/messenger/components/NavigationTabs.js +130 -0
  52. package/src/widgets/messenger/views/ChangelogView.js +167 -0
  53. package/src/widgets/messenger/views/ChatView.js +592 -0
  54. package/src/widgets/messenger/views/ConversationsView.js +244 -0
  55. package/src/widgets/messenger/views/HelpView.js +239 -0
  56. package/src/widgets/messenger/views/HomeView.js +300 -0
  57. package/src/widgets/messenger/views/PreChatFormView.js +109 -0
  58. package/types/index.d.ts +341 -0
@@ -0,0 +1,275 @@
1
+ /**
2
+ * WebSocketService - Real-time communication for messenger widget
3
+ */
4
+
5
+ export class WebSocketService {
6
+ constructor(config = {}) {
7
+ this.baseURL = config.baseURL || '';
8
+ this.workspace = config.workspace || '';
9
+ this.sessionToken = config.sessionToken || null;
10
+ this.mock = config.mock || false;
11
+
12
+ this.ws = null;
13
+ this.reconnectAttempts = 0;
14
+ this.maxReconnectAttempts = 5;
15
+ this.reconnectDelay = 1000;
16
+ this.pingInterval = null;
17
+ this.isConnected = false;
18
+
19
+ // Event listeners
20
+ this._listeners = new Map();
21
+
22
+ // Bind methods
23
+ this._onOpen = this._onOpen.bind(this);
24
+ this._onMessage = this._onMessage.bind(this);
25
+ this._onClose = this._onClose.bind(this);
26
+ this._onError = this._onError.bind(this);
27
+ }
28
+
29
+ /**
30
+ * Connect to WebSocket server
31
+ */
32
+ connect(sessionToken = null) {
33
+ if (sessionToken) {
34
+ this.sessionToken = sessionToken;
35
+ }
36
+
37
+ if (!this.sessionToken) {
38
+ console.warn('[WebSocket] No session token provided');
39
+ return;
40
+ }
41
+
42
+ // Mock mode - simulate connection
43
+ if (this.mock) {
44
+ this.isConnected = true;
45
+ this._emit('connected', {});
46
+ this._startMockResponses();
47
+ return;
48
+ }
49
+
50
+ // Build WebSocket URL
51
+ const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
52
+ let wsURL = this.baseURL.replace(/^https?:/, wsProtocol);
53
+ wsURL = wsURL.replace('/api/v1', '');
54
+ wsURL = `${wsURL}/api/v1/widget/messenger/ws?token=${encodeURIComponent(this.sessionToken)}`;
55
+
56
+ try {
57
+ this.ws = new WebSocket(wsURL);
58
+ this.ws.onopen = this._onOpen;
59
+ this.ws.onmessage = this._onMessage;
60
+ this.ws.onclose = this._onClose;
61
+ this.ws.onerror = this._onError;
62
+ } catch (error) {
63
+ console.error('[WebSocket] Connection error:', error);
64
+ this._scheduleReconnect();
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Disconnect from WebSocket server
70
+ */
71
+ disconnect() {
72
+ this.isConnected = false;
73
+ this.reconnectAttempts = this.maxReconnectAttempts; // Prevent reconnection
74
+
75
+ if (this.pingInterval) {
76
+ clearInterval(this.pingInterval);
77
+ this.pingInterval = null;
78
+ }
79
+
80
+ if (this.ws) {
81
+ this.ws.close();
82
+ this.ws = null;
83
+ }
84
+
85
+ if (this._mockInterval) {
86
+ clearInterval(this._mockInterval);
87
+ this._mockInterval = null;
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Subscribe to events
93
+ * @param {string} event - Event name
94
+ * @param {Function} callback - Event handler
95
+ * @returns {Function} Unsubscribe function
96
+ */
97
+ on(event, callback) {
98
+ if (!this._listeners.has(event)) {
99
+ this._listeners.set(event, new Set());
100
+ }
101
+ this._listeners.get(event).add(callback);
102
+ return () => this._listeners.get(event).delete(callback);
103
+ }
104
+
105
+ /**
106
+ * Remove event listener
107
+ */
108
+ off(event, callback) {
109
+ if (this._listeners.has(event)) {
110
+ this._listeners.get(event).delete(callback);
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Send message through WebSocket
116
+ */
117
+ send(type, payload = {}) {
118
+ if (!this.isConnected) {
119
+ console.warn('[WebSocket] Not connected, cannot send message');
120
+ return;
121
+ }
122
+
123
+ if (this.mock) {
124
+ // Mock mode - just log
125
+ console.log('[WebSocket Mock] Sending:', type, payload);
126
+ return;
127
+ }
128
+
129
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
130
+ this.ws.send(JSON.stringify({ type, payload }));
131
+ }
132
+ }
133
+
134
+ // Private methods
135
+
136
+ _onOpen() {
137
+ console.log('[WebSocket] Connected');
138
+ this.isConnected = true;
139
+ this.reconnectAttempts = 0;
140
+ this._emit('connected', {});
141
+
142
+ // Start ping interval to keep connection alive
143
+ this.pingInterval = setInterval(() => {
144
+ this.send('ping', {});
145
+ }, 30000);
146
+ }
147
+
148
+ _onMessage(event) {
149
+ try {
150
+ const data = JSON.parse(event.data);
151
+ const { type, payload } = data;
152
+
153
+ // Handle different event types
154
+ switch (type) {
155
+ case 'message:new':
156
+ this._emit('message', payload);
157
+ break;
158
+ case 'typing:started':
159
+ this._emit('typing_started', payload);
160
+ break;
161
+ case 'typing:stopped':
162
+ this._emit('typing_stopped', payload);
163
+ break;
164
+ case 'conversation:updated':
165
+ this._emit('conversation_updated', payload);
166
+ break;
167
+ case 'conversation:closed':
168
+ this._emit('conversation_closed', payload);
169
+ break;
170
+ case 'availability:changed':
171
+ this._emit('availability_changed', payload);
172
+ break;
173
+ case 'pong':
174
+ // Ping response, ignore
175
+ break;
176
+ default:
177
+ console.log('[WebSocket] Unknown event:', type, payload);
178
+ }
179
+ } catch (error) {
180
+ console.error('[WebSocket] Failed to parse message:', error);
181
+ }
182
+ }
183
+
184
+ _onClose(event) {
185
+ console.log('[WebSocket] Disconnected:', event.code, event.reason);
186
+ this.isConnected = false;
187
+
188
+ if (this.pingInterval) {
189
+ clearInterval(this.pingInterval);
190
+ this.pingInterval = null;
191
+ }
192
+
193
+ this._emit('disconnected', { code: event.code, reason: event.reason });
194
+ this._scheduleReconnect();
195
+ }
196
+
197
+ _onError(error) {
198
+ console.error('[WebSocket] Error:', error);
199
+ this._emit('error', { error });
200
+ }
201
+
202
+ _scheduleReconnect() {
203
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
204
+ console.log('[WebSocket] Max reconnect attempts reached');
205
+ this._emit('reconnect_failed', {});
206
+ return;
207
+ }
208
+
209
+ this.reconnectAttempts++;
210
+ const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
211
+ console.log(
212
+ `[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`
213
+ );
214
+
215
+ setTimeout(() => {
216
+ this.connect();
217
+ }, delay);
218
+ }
219
+
220
+ _emit(event, data) {
221
+ if (this._listeners.has(event)) {
222
+ this._listeners.get(event).forEach((callback) => {
223
+ try {
224
+ callback(data);
225
+ } catch (error) {
226
+ console.error(`[WebSocket] Error in ${event} handler:`, error);
227
+ }
228
+ });
229
+ }
230
+ }
231
+
232
+ // Mock support for development
233
+ _startMockResponses() {
234
+ // Simulate agent typing and responses
235
+ this._mockInterval = setInterval(() => {
236
+ // Randomly emit typing or message events for demo
237
+ const random = Math.random();
238
+ if (random < 0.1) {
239
+ this._emit('typing_started', {
240
+ conversation_id: 'conv_1',
241
+ user_id: 'agent_1',
242
+ user_name: 'Sarah',
243
+ is_agent: true,
244
+ });
245
+
246
+ // Stop typing after 2 seconds
247
+ setTimeout(() => {
248
+ this._emit('typing_stopped', {
249
+ conversation_id: 'conv_1',
250
+ user_id: 'agent_1',
251
+ });
252
+ }, 2000);
253
+ }
254
+ }, 10000);
255
+ }
256
+
257
+ /**
258
+ * Simulate receiving a message (for mock mode)
259
+ */
260
+ simulateMessage(conversationId, message) {
261
+ if (this.mock) {
262
+ this._emit('message', {
263
+ conversation_id: conversationId,
264
+ message: {
265
+ id: 'msg_' + Date.now(),
266
+ content: message.content,
267
+ sender_type: message.sender_type || 'agent',
268
+ sender_name: message.sender_name || 'Support',
269
+ sender_avatar: message.sender_avatar || null,
270
+ created_at: new Date().toISOString(),
271
+ },
272
+ });
273
+ }
274
+ }
275
+ }
@@ -0,0 +1,226 @@
1
+ # API Reference
2
+
3
+ ## Product7
4
+
5
+ ### Constructor
6
+
7
+ ```javascript
8
+ new Product7(config);
9
+ ```
10
+
11
+ **Config Options:**
12
+
13
+ | Option | Type | Required | Default | Description |
14
+ | -------------- | ------- | -------- | ---------------- | --------------------- |
15
+ | `workspace` | String | Yes | - | Workspace identifier |
16
+ | `metadata` | Object | Yes | - | User identification |
17
+ | `apiUrl` | String | No | Auto | Custom API endpoint |
18
+ | `boardName` | String | No | `'general'` | Default board |
19
+ | `theme` | String | No | `'light'` | `'light'` or `'dark'` |
20
+ | `position` | String | No | `'bottom-right'` | Widget position |
21
+ | `showBackdrop` | Boolean | No | `true` | Show panel backdrop |
22
+ | `debug` | Boolean | No | `false` | Debug logging |
23
+
24
+ ### Methods
25
+
26
+ #### `async init(): Promise<Object>`
27
+
28
+ Initialize SDK and create session.
29
+
30
+ #### `createWidget(type, options?): Widget`
31
+
32
+ Create widget. Type: `'button'`.
33
+
34
+ #### `getWidget(id): Widget | undefined`
35
+
36
+ Get widget by ID.
37
+
38
+ #### `getAllWidgets(): Array<Widget>`
39
+
40
+ Get all widgets.
41
+
42
+ #### `destroyWidget(id): Boolean`
43
+
44
+ Destroy widget by ID.
45
+
46
+ #### `destroyAllWidgets(): void`
47
+
48
+ Destroy all widgets.
49
+
50
+ #### `updateConfig(config): void`
51
+
52
+ Update configuration.
53
+
54
+ #### `setMetadata(metadata): void`
55
+
56
+ Update user context.
57
+
58
+ #### `getMetadata(): Object | null`
59
+
60
+ Get current user context.
61
+
62
+ #### `async reinitialize(metadata?): Promise<Object>`
63
+
64
+ Reinitialize with new user.
65
+
66
+ #### `on(event, callback): Product7`
67
+
68
+ Subscribe to event.
69
+
70
+ #### `off(event, callback): Product7`
71
+
72
+ Unsubscribe from event.
73
+
74
+ #### `once(event, callback): Product7`
75
+
76
+ Subscribe once.
77
+
78
+ #### `destroy(): void`
79
+
80
+ Destroy SDK.
81
+
82
+ ### Static Methods
83
+
84
+ #### `Product7.create(config): Product7`
85
+
86
+ Create SDK instance.
87
+
88
+ #### `async Product7.createAndInit(config): Promise<Product7>`
89
+
90
+ Create and initialize.
91
+
92
+ #### `Product7.extractMetadataFromAuth(authData): Object`
93
+
94
+ Extract user context from auth.
95
+
96
+ ---
97
+
98
+ ## Widget
99
+
100
+ ### ButtonWidget
101
+
102
+ #### Methods
103
+
104
+ ##### `mount(container?): Widget`
105
+
106
+ Mount to DOM.
107
+
108
+ ##### `show(): Widget`
109
+
110
+ Show widget.
111
+
112
+ ##### `hide(): Widget`
113
+
114
+ Hide widget.
115
+
116
+ ##### `openPanel(): void`
117
+
118
+ Open feedback panel.
119
+
120
+ ##### `closePanel(): void`
121
+
122
+ Close panel.
123
+
124
+ ##### `updateText(text): void`
125
+
126
+ Update button text.
127
+
128
+ ##### `updatePosition(position): void`
129
+
130
+ Update position.
131
+
132
+ ##### `destroy(): void`
133
+
134
+ Destroy widget.
135
+
136
+ #### Properties
137
+
138
+ - `id: String` - Widget ID
139
+ - `type: String` - Widget type
140
+ - `mounted: Boolean` - Mount status
141
+ - `state: Object` - Widget state
142
+
143
+ ---
144
+
145
+ ## Events
146
+
147
+ ### SDK Events
148
+
149
+ - `sdk:initialized` - SDK ready
150
+ - `sdk:error` - Error occurred
151
+ - `sdk:destroyed` - SDK destroyed
152
+ - `config:updated` - Config changed
153
+ - `user:updated` - User changed
154
+
155
+ ### Widget Events
156
+
157
+ - `widget:created` - Widget created
158
+ - `widget:mounted` - Widget mounted
159
+ - `widget:destroyed` - Widget destroyed
160
+ - `widgets:cleared` - All cleared
161
+
162
+ ### Feedback Events
163
+
164
+ - `feedback:submitted` - Feedback sent
165
+ - `feedback:error` - Submission failed
166
+
167
+ ---
168
+
169
+ ## APIService
170
+
171
+ Access via `sdk.apiService`.
172
+
173
+ ### Methods
174
+
175
+ #### `async init(metadata?): Promise<Object>`
176
+
177
+ Initialize session.
178
+
179
+ #### `async submitFeedback(data): Promise<Object>`
180
+
181
+ Submit feedback.
182
+
183
+ #### `isSessionValid(): Boolean`
184
+
185
+ Check session validity.
186
+
187
+ #### `clearSession(): void`
188
+
189
+ Clear session.
190
+
191
+ ---
192
+
193
+ ## Error Classes
194
+
195
+ ### SDKError
196
+
197
+ General SDK errors.
198
+
199
+ ### APIError
200
+
201
+ API errors with methods:
202
+
203
+ - `isNetworkError()`
204
+ - `isClientError()`
205
+ - `isServerError()`
206
+
207
+ ### ConfigError
208
+
209
+ Configuration errors.
210
+
211
+ ### WidgetError
212
+
213
+ Widget errors.
214
+
215
+ ---
216
+
217
+ ## Utilities
218
+
219
+ - `generateId(prefix?)`
220
+ - `deepMerge(target, source)`
221
+ - `debounce(func, wait)`
222
+ - `throttle(func, limit)`
223
+ - `isValidEmail(email)`
224
+ - `isMobile()`
225
+ - `formatFileSize(bytes)`
226
+ - `delay(ms)`