wakz-chat-widget 1.1.0 → 2.2.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 (3) hide show
  1. package/README.md +51 -24
  2. package/index.js +61 -6
  3. package/package.json +13 -6
package/README.md CHANGED
@@ -1,43 +1,70 @@
1
1
  # wakz-chat-widget
2
2
 
3
- Production-grade AI chat widget by **WAKZ** — Shadow DOM isolated, zero dependencies, Intercom/Crisp quality.
3
+ **Premium AI chat widget by WAKZ** — A production-grade, self-contained chat widget using Shadow DOM.
4
+
5
+ > Competes with Intercom & Crisp in quality. **Zero external dependencies** — pure vanilla JavaScript.
6
+
7
+ ## Features
8
+
9
+ - Shadow DOM isolation (no CSS conflicts)
10
+ - Multi-language support (English, Arabic, French) with full RTL
11
+ - Device detection (model, platform, type)
12
+ - Online/offline status with animated indicators
13
+ - Message polling with deduplication
14
+ - Mobile responsive (full-screen on small devices)
15
+ - Typing indicator animations
16
+ - Welcome messages
17
+ - Human agent badge support
18
+ - Auto-resizing textarea input
19
+ - Keyboard shortcuts (Enter to send, Shift+Enter for newline, Escape to close)
20
+ - Smooth animations and transitions
21
+ - Configurable theming (colors, position)
4
22
 
5
23
  ## Installation
6
24
 
7
- No installation needed. Add this script tag to your website:
25
+ ```bash
26
+ npm install wakz-chat-widget
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ Copy `index.js` from `node_modules/wakz-chat-widget/` to your public folder and include it:
8
32
 
9
33
  ```html
10
- <!-- WAKZ Chat Widget -->
11
- <script
12
- src="https://unpkg.com/wakz-chat-widget@latest/index.js"
34
+ <script src="/wakz-widget.js"
13
35
  data-api-key="YOUR_API_KEY"
14
- data-server="https://your-wakz-server.com"
36
+ data-server="https://your-server.com"
15
37
  async>
16
38
  </script>
17
39
  ```
18
40
 
19
- Replace:
20
- - `YOUR_API_KEY` — Your WAKZ embed API key
21
- - `https://your-wakz-server.com` — Your WAKZ server URL
41
+ ## Configuration
22
42
 
23
- ## Features
43
+ The widget fetches its configuration from your server's `/api/v1/embed/config` endpoint. Configurable options include:
24
44
 
25
- - **Shadow DOM** Fully isolated from your website's CSS
26
- - **Zero Dependencies** — Pure vanilla JavaScript
27
- - **RTL Support** Full Arabic/Hebrew right-to-left support
28
- - **Dynamic Theming** Colors, position, bot name, welcome message configurable from dashboard
29
- - **Responsive** Full-screen on mobile, floating window on desktop
30
- - **Real-time Chat** AI-powered responses via WAKZ backend
31
- - **Typing Indicator** Smooth animated dots while bot is thinking
32
- - **Session Persistence** Chat history preserved across page reloads
33
- - **Online/Offline Status** Green/red dot with pulse animation
45
+ | Option | Type | Default | Description |
46
+ |--------|------|---------|-------------|
47
+ | `botName` | string | `'WAKZ'` | Bot display name |
48
+ | `welcomeMessage` | string | `''` | Initial welcome message |
49
+ | `primaryColor` | string | `'#171717'` | Primary theme color |
50
+ | `chatBg` | string | `'#f8f9fa'` | Chat area background |
51
+ | `btnColor` | string | `'#171717'` | FAB button color |
52
+ | `widgetBg` | string | `'#ffffff'` | Widget background |
53
+ | `position` | string | `'bottom-right'` | Widget position |
54
+ | `language` | string | `'en'` | Language (`en`, `ar`, `fr`) |
55
+ | `showStatus` | boolean | `true` | Show online/offline dot |
56
+ | `online` | boolean | `true` | Initial status |
34
57
 
35
- ## CDN
58
+ ## Version History
36
59
 
37
- ```html
38
- https://unpkg.com/wakz-chat-widget@latest/index.js
39
- https://cdn.jsdelivr.net/npm/wakz-chat-widget@latest/index.js
40
- ```
60
+ ### v2.2.0
61
+ - Added device model, platform, and type detection (User-Agent Client Hints API + UA fallback)
62
+ - Device info sent with session data for dashboard analytics
63
+
64
+ ### v2.0.0
65
+ - Complete rewrite with Shadow DOM architecture
66
+ - Multi-language support (EN/AR/FR) with RTL
67
+ - Production-grade UI with animations
41
68
 
42
69
  ## License
43
70
 
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * WAKZ Chat Widget v2.1.0
2
+ * WAKZ Chat Widget v2.2.0
3
3
  * ─────────────────────────────────────────────────────────────────
4
4
  * A production-grade, self-contained chat widget using Shadow DOM.
5
5
  * Competes with Intercom & Crisp in quality.
@@ -79,6 +79,46 @@
79
79
  return el;
80
80
  }
81
81
 
82
+ /** Detect device model, platform, and type using userAgentData API (Chrome 90+) with UA fallback */
83
+ function _getDeviceInfo() {
84
+ var info = {
85
+ device_model: '',
86
+ device_platform: '',
87
+ device_type: 'desktop'
88
+ };
89
+
90
+ // Try userAgentData API (Chrome 90+, Edge, Samsung Browser — NOT Safari/Firefox)
91
+ if (navigator.userAgentData) {
92
+ info.device_model = navigator.userAgentData.model || '';
93
+ info.device_platform = navigator.userAgentData.platform || '';
94
+ if (navigator.userAgentData.mobile === true) {
95
+ info.device_type = 'mobile';
96
+ } else if (navigator.userAgentData.mobile === false && info.device_platform === 'Android') {
97
+ info.device_type = 'tablet';
98
+ } else {
99
+ info.device_type = 'desktop';
100
+ }
101
+ }
102
+
103
+ // Fallback: parse from user agent string
104
+ var ua = navigator.userAgent || '';
105
+ if (!info.device_platform) {
106
+ if (/iPhone|iPad|iPod/i.test(ua)) info.device_platform = 'iOS';
107
+ else if (/Android/i.test(ua)) info.device_platform = 'Android';
108
+ else if (/Windows/i.test(ua)) info.device_platform = 'Windows';
109
+ else if (/Mac OS X/i.test(ua)) info.device_platform = 'macOS';
110
+ else if (/CrOS/i.test(ua)) info.device_platform = 'Chrome OS';
111
+ else if (/Linux/i.test(ua)) info.device_platform = 'Linux';
112
+ }
113
+ if (info.device_type === 'desktop') {
114
+ if (/iPad/i.test(ua)) info.device_type = 'tablet';
115
+ else if (/Mobile|iPhone|iPod/i.test(ua)) info.device_type = 'mobile';
116
+ else if (/Android(?!.*Mobile)/i.test(ua)) info.device_type = 'tablet';
117
+ else if (/Android/i.test(ua)) info.device_type = 'mobile';
118
+ }
119
+ return info;
120
+ }
121
+
82
122
  /** Fetch with an AbortController timeout (default 30s) */
83
123
  function _fetchWithTimeout(url, options, timeoutMs) {
84
124
  var controller = new AbortController();
@@ -182,6 +222,7 @@
182
222
  self.apiKey = attrs.apiKey;
183
223
  self.server = attrs.server;
184
224
  self.visitorId = _getVisitorId();
225
+ self._deviceInfo = _getDeviceInfo(); // Device model, platform, type — collected once
185
226
 
186
227
  /* ── Runtime state ── */
187
228
  self.config = Object.assign({}, _DEFAULTS);
@@ -196,6 +237,7 @@
196
237
  self._lastPollTime = null;
197
238
  self._POLL_INTERVAL = 4000; /* Poll every 4 seconds */
198
239
  self._knownMessageIds = {}; /* Deduplication set for message IDs */
240
+ self._pendingReply = false; /* True while waiting for API response — pauses polling */
199
241
 
200
242
  /* ── DOM refs (populated after mount) ── */
201
243
  self._host = null;
@@ -1105,6 +1147,8 @@
1105
1147
  WAKZWidget.prototype._pollForNewMessages = function () {
1106
1148
  var self = this;
1107
1149
  if (!self.server || !self.apiKey || !self._lastPollTime) return;
1150
+ /* Skip polling while waiting for our own reply — prevents race condition duplicates */
1151
+ if (self._pendingReply) return;
1108
1152
 
1109
1153
  var url = self.server + '/api/v1/embed/chat?api_key=' +
1110
1154
  encodeURIComponent(self.apiKey) +
@@ -1328,6 +1372,10 @@
1328
1372
  self._sendBtn.disabled = true;
1329
1373
  self._showTyping();
1330
1374
 
1375
+ /* Freeze poll time BEFORE sending — prevents polling from fetching our own messages */
1376
+ self._lastPollTime = new Date().toISOString();
1377
+ self._pendingReply = true;
1378
+
1331
1379
  var payload = {
1332
1380
  api_key: self.apiKey,
1333
1381
  visitor_id: self.visitorId,
@@ -1336,7 +1384,10 @@
1336
1384
  domain: window.location.hostname || '',
1337
1385
  page_url: window.location.href || '',
1338
1386
  user_agent: navigator.userAgent || '',
1339
- language: navigator.language || ''
1387
+ language: navigator.language || '',
1388
+ device_model: self._deviceInfo.device_model || '',
1389
+ device_platform: self._deviceInfo.device_platform || '',
1390
+ device_type: self._deviceInfo.device_type || 'desktop'
1340
1391
  }
1341
1392
  };
1342
1393
 
@@ -1351,19 +1402,23 @@
1351
1402
  .then(function (res) { return res.json(); })
1352
1403
  .then(function (data) {
1353
1404
  self._hideTyping();
1405
+ self._pendingReply = false;
1354
1406
  if (data && data.success && data.reply) {
1355
1407
  self._appendMessage('bot', data.reply);
1356
1408
  } else {
1357
1409
  self._appendMessage('bot', _strings(self.config.language).errorMsg, true);
1358
1410
  }
1359
- /* Update poll time to prevent re-fetching messages we already displayed */
1360
- self._lastPollTime = new Date().toISOString();
1411
+ /* Advance poll time past any messages created during this request */
1412
+ self._lastPollTime = (data && data.timestamp)
1413
+ ? new Date(new Date(data.timestamp).getTime() + 1000).toISOString()
1414
+ : new Date(Date.now() + 1000).toISOString();
1361
1415
  })
1362
1416
  .catch(function () {
1363
1417
  self._hideTyping();
1418
+ self._pendingReply = false;
1364
1419
  self._appendMessage('bot', _strings(self.config.language).errorMsg, true);
1365
- /* Update poll time even on error to prevent re-fetching */
1366
- self._lastPollTime = new Date().toISOString();
1420
+ /* Advance poll time even on error */
1421
+ self._lastPollTime = new Date(Date.now() + 1000).toISOString();
1367
1422
  })
1368
1423
  .finally(function () {
1369
1424
  self.isLoading = false;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "wakz-chat-widget",
3
- "version": "1.1.0",
4
- "description": "Production-grade AI chat widget by WAKZ — Shadow DOM isolated, zero dependencies, Intercom/Crisp quality.",
3
+ "version": "2.2.0",
4
+ "description": "Premium AI chat widget by WAKZ — Production-grade, Shadow DOM, zero dependencies, multi-language support, device detection, RTL support.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "prepublishOnly": "echo 'Ready to publish wakz-chat-widget'"
7
+ "prepublishOnly": "echo 'Ready to publish wakz-chat-widget v2.2.0'"
8
8
  },
9
9
  "keywords": [
10
10
  "chat",
@@ -16,9 +16,13 @@
16
16
  "shadow-dom",
17
17
  "customer-support",
18
18
  "live-chat",
19
- "saas"
19
+ "saas",
20
+ "rtl",
21
+ "arabic",
22
+ "device-detection",
23
+ "zero-dependencies"
20
24
  ],
21
- "author": "WAKZ",
25
+ "author": "mohamed64 <mohamed01140251843sayed@gmail.com>",
22
26
  "license": "MIT",
23
27
  "repository": {
24
28
  "type": "git",
@@ -27,5 +31,8 @@
27
31
  "files": [
28
32
  "index.js",
29
33
  "README.md"
30
- ]
34
+ ],
35
+ "engines": {
36
+ "node": ">=12.0.0"
37
+ }
31
38
  }