@hellotext/hellotext 2.1.2 → 2.1.4

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 (56) hide show
  1. package/dist/hellotext.js +1 -1
  2. package/lib/api/forms.cjs +2 -1
  3. package/lib/api/forms.js +2 -1
  4. package/lib/api/webchat/messages.cjs +4 -3
  5. package/lib/api/webchat/messages.js +4 -2
  6. package/lib/api/webchats.cjs +2 -0
  7. package/lib/api/webchats.js +3 -1
  8. package/lib/builders/logo_builder.cjs +1 -1
  9. package/lib/builders/logo_builder.js +1 -1
  10. package/lib/channels/application_channel.cjs +9 -6
  11. package/lib/channels/application_channel.js +9 -6
  12. package/lib/channels/webchat_channel.cjs +42 -17
  13. package/lib/channels/webchat_channel.js +42 -17
  14. package/lib/controllers/webchat/emoji_picker_controller.cjs +6 -6
  15. package/lib/controllers/webchat/emoji_picker_controller.js +5 -14
  16. package/lib/controllers/webchat_controller.cjs +174 -47
  17. package/lib/controllers/webchat_controller.js +175 -48
  18. package/lib/core/configuration/locale.cjs +87 -0
  19. package/lib/core/configuration/locale.js +81 -0
  20. package/lib/core/configuration.cjs +11 -0
  21. package/lib/core/configuration.js +11 -0
  22. package/lib/core/index.cjs +15 -1
  23. package/lib/core/index.js +4 -2
  24. package/lib/locales/en.cjs +1 -1
  25. package/lib/locales/en.js +1 -1
  26. package/lib/locales/es.cjs +1 -1
  27. package/lib/locales/es.js +1 -1
  28. package/lib/models/business.cjs +11 -0
  29. package/lib/models/business.js +11 -0
  30. package/lib/models/form_collection.cjs +1 -0
  31. package/lib/models/form_collection.js +2 -1
  32. package/lib/models/index.cjs +4 -4
  33. package/lib/models/index.js +4 -4
  34. package/lib/models/query.cjs +1 -2
  35. package/lib/models/query.js +1 -2
  36. package/lib/models/session.cjs +1 -1
  37. package/lib/models/session.js +1 -1
  38. package/package.json +2 -1
  39. package/src/api/forms.js +3 -1
  40. package/src/api/webchat/messages.js +8 -6
  41. package/src/api/webchats.js +3 -1
  42. package/src/builders/logo_builder.js +1 -1
  43. package/src/channels/application_channel.js +12 -9
  44. package/src/channels/webchat_channel.js +33 -19
  45. package/src/controllers/webchat/emoji_picker_controller.js +9 -15
  46. package/src/controllers/webchat_controller.js +164 -43
  47. package/src/core/configuration/locale.js +50 -0
  48. package/src/core/configuration.js +11 -0
  49. package/src/core/index.js +3 -1
  50. package/src/locales/en.js +4 -4
  51. package/src/locales/es.js +4 -4
  52. package/src/models/business.js +12 -0
  53. package/src/models/form_collection.js +2 -1
  54. package/src/models/index.js +3 -3
  55. package/src/models/query.js +1 -3
  56. package/src/models/session.js +1 -1
@@ -22,6 +22,7 @@ import { Controller } from '@hotwired/stimulus';
22
22
  import WebchatMessagesAPI from '../api/webchat/messages';
23
23
  import WebchatChannel from '../channels/webchat_channel';
24
24
  import Hellotext from '../hellotext';
25
+ import { Locale } from '../core';
25
26
  import { Webchat as WebchatConfiguration, behaviors } from '../core/configuration/webchat';
26
27
  import { LogoBuilder } from '../builders/logo_builder';
27
28
  import { usePopover } from './mixins/usePopover';
@@ -39,9 +40,8 @@ var _default = /*#__PURE__*/function (_Controller) {
39
40
  this.webChatChannel = new WebchatChannel(this.idValue, Hellotext.session, this.conversationIdValue);
40
41
  this.files = [];
41
42
  this.onMessageReceived = this.onMessageReceived.bind(this);
42
- this.onConversationAssignment = this.onConversationAssignment.bind(this);
43
- this.onAgentOnline = this.onAgentOnline.bind(this);
44
43
  this.onMessageReaction = this.onMessageReaction.bind(this);
44
+ this.onTypingStart = this.onTypingStart.bind(this);
45
45
  this.onScroll = this.onScroll.bind(this);
46
46
  this.onOutboundMessageSent = this.onOutboundMessageSent.bind(this);
47
47
  this.broadcastChannel = new BroadcastChannel("hellotext--webchat--".concat(this.idValue));
@@ -58,14 +58,13 @@ var _default = /*#__PURE__*/function (_Controller) {
58
58
  popover: this.popoverTarget
59
59
  });
60
60
  this.webChatChannel.onMessage(this.onMessageReceived);
61
- this.webChatChannel.onConversationAssignment(this.onConversationAssignment);
62
- this.webChatChannel.onAgentOnline(this.onAgentOnline);
61
+ this.webChatChannel.onTypingStart(this.onTypingStart);
63
62
  this.webChatChannel.onReaction(this.onMessageReaction);
64
63
  this.messagesContainerTarget.addEventListener('scroll', this.onScroll);
65
64
  if (!Hellotext.business.features.white_label) {
66
65
  this.toolbarTarget.appendChild(LogoBuilder.build());
67
66
  }
68
- if (localStorage.getItem("hellotext--webchat--".concat(this.idValue)) === 'opened') {
67
+ if (this.shouldOpenOnMount) {
69
68
  this.openValue = true;
70
69
  }
71
70
  Hellotext.eventEmitter.dispatch('webchat:mounted');
@@ -77,10 +76,85 @@ var _default = /*#__PURE__*/function (_Controller) {
77
76
  value: function disconnect() {
78
77
  this.broadcastChannel.removeEventListener('message', this.onOutboundMessageSent);
79
78
  this.messagesContainerTarget.removeEventListener('scroll', this.onScroll);
79
+
80
+ // Clean up typing indicator timeouts
81
+ this.clearTypingIndicator();
80
82
  this.broadcastChannel.close();
81
83
  this.floatingUICleanup();
82
84
  _get(_getPrototypeOf(_default.prototype), "disconnect", this).call(this);
83
85
  }
86
+ }, {
87
+ key: "onTypingStart",
88
+ value: function onTypingStart() {
89
+ if (this.typingIndicatorVisible) {
90
+ return this.resetTypingIndicatorTimer();
91
+ }
92
+ this.showTypingIndicator();
93
+ }
94
+ }, {
95
+ key: "showOptimisticTypingIndicator",
96
+ value: function showOptimisticTypingIndicator() {
97
+ if (this.typingIndicatorVisible) return;
98
+ this.showTypingIndicator();
99
+ }
100
+ }, {
101
+ key: "showTypingIndicator",
102
+ value: function showTypingIndicator() {
103
+ this.clearTypingIndicator();
104
+ this.typingIndicatorVisible = true;
105
+ var indicator = this.typingIndicatorTemplateTarget.cloneNode(true);
106
+ indicator.setAttribute('data-hellotext--webchat-target', 'typingIndicator');
107
+ indicator.style.display = 'flex';
108
+ this.messagesContainerTarget.appendChild(indicator);
109
+ requestAnimationFrame(() => {
110
+ this.messagesContainerTarget.scroll({
111
+ top: this.messagesContainerTarget.scrollHeight,
112
+ behavior: 'instant'
113
+ });
114
+ });
115
+ var timeout = this.typingIndicatorKeepAliveValue;
116
+ this.incomingTypingIndicatorTimeout = setTimeout(() => {
117
+ this.clearTypingIndicator();
118
+ }, timeout);
119
+ }
120
+ }, {
121
+ key: "resetTypingIndicatorTimer",
122
+ value: function resetTypingIndicatorTimer() {
123
+ if (!this.typingIndicatorVisible) return;
124
+
125
+ // Clear existing timeout
126
+ clearTimeout(this.incomingTypingIndicatorTimeout);
127
+ clearTimeout(this.optimisticTypingTimeout);
128
+
129
+ // Use unified timeout for all typing indicators
130
+ var timeout = this.typingIndicatorKeepAliveValue;
131
+ this.incomingTypingIndicatorTimeout = setTimeout(() => {
132
+ this.clearTypingIndicator();
133
+ }, timeout);
134
+ }
135
+ }, {
136
+ key: "clearTypingIndicator",
137
+ value: function clearTypingIndicator() {
138
+ if (this.hasTypingIndicatorTarget) {
139
+ this.typingIndicatorTarget.remove();
140
+ }
141
+ this.typingIndicatorVisible = false;
142
+ clearTimeout(this.incomingTypingIndicatorTimeout);
143
+ clearTimeout(this.optimisticTypingTimeout);
144
+ }
145
+ }, {
146
+ key: "onMessageInputChange",
147
+ value: function onMessageInputChange() {
148
+ this.resizeInput();
149
+ clearTimeout(this.typingIndicatorTimeout);
150
+ if (!this.hasSentTypingIndicator) {
151
+ this.webChatChannel.startTypingIndicator();
152
+ this.hasSentTypingIndicator = true;
153
+ }
154
+ this.typingIndicatorTimeout = setTimeout(() => {
155
+ this.hasSentTypingIndicator = false;
156
+ }, 3000);
157
+ }
84
158
  }, {
85
159
  key: "onOutboundMessageSent",
86
160
  value: function onOutboundMessageSent(event) {
@@ -90,7 +164,13 @@ var _default = /*#__PURE__*/function (_Controller) {
90
164
  var callbacks = {
91
165
  'message:sent': data => {
92
166
  var element = new DOMParser().parseFromString(data.element, 'text/html').body.firstElementChild;
93
- this.messagesContainerTarget.appendChild(element);
167
+
168
+ // Insert message before typing indicator if one exists
169
+ if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
170
+ this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
171
+ } else {
172
+ this.messagesContainerTarget.appendChild(element);
173
+ }
94
174
  element.scrollIntoView({
95
175
  behavior: 'instant'
96
176
  });
@@ -168,10 +248,20 @@ var _default = /*#__PURE__*/function (_Controller) {
168
248
  this.openValue = false;
169
249
  }
170
250
  }
251
+ }, {
252
+ key: "closePopover",
253
+ value: function closePopover() {
254
+ this.popoverTarget.classList.add(...this.fadeOutClasses);
255
+ setTimeout(() => {
256
+ this.openValue = false;
257
+ }, 250);
258
+ }
171
259
  }, {
172
260
  key: "onPopoverOpened",
173
261
  value: function onPopoverOpened() {
174
- this.inputTarget.focus();
262
+ if (!this.onMobile) {
263
+ this.inputTarget.focus();
264
+ }
175
265
  if (!this.scrolled) {
176
266
  requestAnimationFrame(() => {
177
267
  this.messagesContainerTarget.scroll({
@@ -192,9 +282,6 @@ var _default = /*#__PURE__*/function (_Controller) {
192
282
  key: "onPopoverClosed",
193
283
  value: function onPopoverClosed() {
194
284
  Hellotext.eventEmitter.dispatch('webchat:closed');
195
- setTimeout(() => {
196
- this.inputTarget.value = '';
197
- });
198
285
  localStorage.setItem("hellotext--webchat--".concat(this.idValue), 'closed');
199
286
  }
200
287
  }, {
@@ -225,6 +312,7 @@ var _default = /*#__PURE__*/function (_Controller) {
225
312
  key: "onMessageReceived",
226
313
  value: function onMessageReceived(message) {
227
314
  var {
315
+ id,
228
316
  body,
229
317
  attachments
230
318
  } = message;
@@ -242,6 +330,11 @@ var _default = /*#__PURE__*/function (_Controller) {
242
330
  element.querySelector('[data-attachment-container]').appendChild(image);
243
331
  });
244
332
  }
333
+
334
+ // Clear any typing indicator when message is received
335
+ if (this.typingIndicatorVisible) {
336
+ this.clearTypingIndicator();
337
+ }
245
338
  this.messagesContainerTarget.appendChild(element);
246
339
  Hellotext.eventEmitter.dispatch('webchat:message:received', _objectSpread(_objectSpread({}, message), {}, {
247
340
  body: element.querySelector('[data-body]').innerText
@@ -249,41 +342,40 @@ var _default = /*#__PURE__*/function (_Controller) {
249
342
  element.scrollIntoView({
250
343
  behavior: 'smooth'
251
344
  });
252
- this.setOfflineTimeout();
253
- if (this.openValue) return;
345
+ if (this.openValue) {
346
+ this.messagesAPI.markAsSeen(id);
347
+ return;
348
+ }
254
349
  this.unreadCounterTarget.style.display = 'flex';
255
350
  var unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
256
351
  this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
257
352
  }
258
353
  }, {
259
- key: "onConversationAssignment",
260
- value: function onConversationAssignment(conversation) {
261
- var {
262
- to: user
263
- } = conversation;
264
- this.titleTarget.innerText = user.name;
265
- if (user.online) {
266
- this.onlineStatusTarget.style.display = 'flex';
267
- } else {
268
- this.onlineStatusTarget.style.display = 'none';
269
- }
270
- }
271
- }, {
272
- key: "onAgentOnline",
273
- value: function onAgentOnline() {
274
- this.onlineStatusTarget.style.display = 'flex';
275
- this.setOfflineTimeout();
354
+ key: "resizeInput",
355
+ value: function resizeInput() {
356
+ var maxHeight = 96;
357
+
358
+ // Temporarily reset height to its natural content size
359
+ this.inputTarget.style.height = 'auto';
360
+
361
+ // Set the height to the scrollHeight, which is the minimum height
362
+ // the element needs to fit its content without a scrollbar.
363
+ var scrollHeight = this.inputTarget.scrollHeight;
364
+ this.inputTarget.style.height = "".concat(Math.min(scrollHeight, maxHeight), "px");
276
365
  }
277
366
  }, {
278
367
  key: "sendMessage",
279
368
  value: function () {
280
- var _sendMessage = _asyncToGenerator(function* () {
369
+ var _sendMessage = _asyncToGenerator(function* (e) {
281
370
  var formData = new FormData();
282
371
  var message = {
283
372
  body: this.inputTarget.value,
284
373
  attachments: this.files
285
374
  };
286
375
  if (this.inputTarget.value.trim().length === 0 && this.files.length === 0) {
376
+ if (e && e.target) {
377
+ e.preventDefault();
378
+ }
287
379
  return;
288
380
  }
289
381
  if (this.inputTarget.value.trim().length > 0) {
@@ -295,6 +387,7 @@ var _default = /*#__PURE__*/function (_Controller) {
295
387
  formData.append('message[attachments][]', file);
296
388
  });
297
389
  formData.append('session', Hellotext.session);
390
+ formData.append('locale', Locale.toString());
298
391
  var element = this.messageTemplateTarget.cloneNode(true);
299
392
  element.id = "hellotext--webchat--".concat(this.idValue, "--message--").concat(Date.now());
300
393
  element.classList.add('received');
@@ -311,7 +404,13 @@ var _default = /*#__PURE__*/function (_Controller) {
311
404
  element.querySelector('[data-attachment-container]').appendChild(attachment);
312
405
  });
313
406
  }
314
- this.messagesContainerTarget.appendChild(element);
407
+
408
+ // Insert message before typing indicator if one exists
409
+ if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
410
+ this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
411
+ } else {
412
+ this.messagesContainerTarget.appendChild(element);
413
+ }
315
414
  element.scrollIntoView({
316
415
  behavior: 'smooth'
317
416
  });
@@ -320,6 +419,7 @@ var _default = /*#__PURE__*/function (_Controller) {
320
419
  element: element.outerHTML
321
420
  });
322
421
  this.inputTarget.value = '';
422
+ this.resizeInput();
323
423
  this.files = [];
324
424
  this.attachmentInputTarget.value = '';
325
425
  this.attachmentContainerTarget.innerHTML = '';
@@ -342,9 +442,17 @@ var _default = /*#__PURE__*/function (_Controller) {
342
442
  this.conversationIdValue = data.conversation;
343
443
  this.webChatChannel.updateSubscriptionWith(this.conversationIdValue);
344
444
  }
445
+ if (this.typingIndicatorVisible) {
446
+ this.resetTypingIndicatorTimer();
447
+ } else {
448
+ clearTimeout(this.optimisticTypingTimeout);
449
+ this.optimisticTypingTimeout = setTimeout(() => {
450
+ this.showOptimisticTypingIndicator();
451
+ }, this.optimisticTypingIndicatorWaitValue);
452
+ }
345
453
  this.attachmentContainerTarget.style.display = '';
346
454
  });
347
- function sendMessage() {
455
+ function sendMessage(_x) {
348
456
  return _sendMessage.apply(this, arguments);
349
457
  }
350
458
  return sendMessage;
@@ -445,30 +553,27 @@ var _default = /*#__PURE__*/function (_Controller) {
445
553
  this.inputTarget.selectionStart = this.inputTarget.selectionEnd = start + emoji.length;
446
554
  this.inputTarget.focus();
447
555
  }
448
- }, {
449
- key: "setOfflineTimeout",
450
- value: function setOfflineTimeout() {
451
- clearTimeout(this.offlineTimeout);
452
- this.offlineTimeout = setTimeout(() => {
453
- this.onlineStatusTarget.style.display = 'none';
454
- }, this.fiveMinutes);
455
- }
456
556
  }, {
457
557
  key: "byteToMegabyte",
458
558
  value: function byteToMegabyte(bytes) {
459
559
  return Math.ceil(bytes / 1024 / 1024);
460
560
  }
461
561
  }, {
462
- key: "fiveMinutes",
562
+ key: "middlewares",
563
+ get: function get() {
564
+ return [offset(this.offsetValue), shift({
565
+ padding: this.paddingValue
566
+ }), flip()];
567
+ }
568
+ }, {
569
+ key: "shouldOpenOnMount",
463
570
  get: function get() {
464
- return 300000;
571
+ return localStorage.getItem("hellotext--webchat--".concat(this.idValue)) === 'opened' && !this.onMobile;
465
572
  }
466
573
  }, {
467
- key: "middlewares",
574
+ key: "onMobile",
468
575
  get: function get() {
469
- return [offset(5), shift({
470
- padding: 24
471
- }), flip()];
576
+ return window.matchMedia("(max-width: ".concat(this.fullScreenThresholdValue, "px)")).matches;
472
577
  }
473
578
  }]);
474
579
  return _default;
@@ -497,7 +602,29 @@ _default.values = {
497
602
  nextPage: {
498
603
  type: Number,
499
604
  default: undefined
500
- }
605
+ },
606
+ fullScreenThreshold: {
607
+ type: Number,
608
+ default: 1024
609
+ },
610
+ typingIndicatorKeepAlive: {
611
+ type: Number,
612
+ default: 30000
613
+ },
614
+ // 30 seconds
615
+ offset: {
616
+ type: Number,
617
+ default: 24
618
+ },
619
+ padding: {
620
+ type: Number,
621
+ default: 24
622
+ },
623
+ optimisticTypingIndicatorWait: {
624
+ type: Number,
625
+ default: 1000
626
+ } // 1 second
501
627
  };
502
- _default.targets = ['trigger', 'popover', 'input', 'attachmentInput', 'attachmentButton', 'errorMessageContainer', 'attachmentTemplate', 'attachmentContainer', 'attachment', 'messageTemplate', 'messagesContainer', 'title', 'onlineStatus', 'attachmentImage', 'footer', 'toolbar', 'message', 'unreadCounter'];
628
+ _default.classes = ['fadeOut'];
629
+ _default.targets = ['trigger', 'popover', 'input', 'attachmentInput', 'attachmentButton', 'errorMessageContainer', 'attachmentTemplate', 'attachmentContainer', 'attachment', 'messageTemplate', 'messagesContainer', 'title', 'attachmentImage', 'footer', 'toolbar', 'message', 'unreadCounter', 'typingIndicator', 'typingIndicatorTemplate'];
503
630
  export { _default as default };
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Locale = void 0;
7
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
9
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
10
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
11
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
12
+ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
13
+ var id = 0;
14
+ function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
15
+ var _fromHtmlLangProperty = /*#__PURE__*/_classPrivateFieldLooseKey("fromHtmlLangProperty");
16
+ var _fromMetaTag = /*#__PURE__*/_classPrivateFieldLooseKey("fromMetaTag");
17
+ var _fromBrowserLanguage = /*#__PURE__*/_classPrivateFieldLooseKey("fromBrowserLanguage");
18
+ /**
19
+ * @class Locale
20
+ * @classdesc
21
+ * Handles locale detection and configuration for the Hellotext library.
22
+ * Provides automatic locale detection from HTML lang attribute, meta tags,
23
+ * and browser language with fallback to 'en'.
24
+ */
25
+ let Locale = /*#__PURE__*/function () {
26
+ function Locale() {
27
+ _classCallCheck(this, Locale);
28
+ }
29
+ _createClass(Locale, null, [{
30
+ key: "identifier",
31
+ get:
32
+ /**
33
+ * Gets the effective locale identifier.
34
+ * Falls back to auto-detection if not explicitly set.
35
+ * @returns {string} The locale identifier
36
+ */
37
+ function () {
38
+ if (this._identifier) return this._identifier;
39
+ return _classPrivateFieldLooseBase(this, _fromHtmlLangProperty)[_fromHtmlLangProperty] || _classPrivateFieldLooseBase(this, _fromMetaTag)[_fromMetaTag] || _classPrivateFieldLooseBase(this, _fromBrowserLanguage)[_fromBrowserLanguage] || 'en';
40
+ }
41
+
42
+ /**
43
+ * Returns the locale identifier as a string.
44
+ * @returns {string} The locale identifier
45
+ */,
46
+ set:
47
+ /**
48
+ * Sets the locale identifier explicitly.
49
+ * @param {string} value - The locale identifier (e.g., 'en', 'es')
50
+ */
51
+ function (value) {
52
+ this._identifier = value;
53
+ }
54
+ }, {
55
+ key: "toString",
56
+ value: function toString() {
57
+ return this.identifier;
58
+ }
59
+ }]);
60
+ return Locale;
61
+ }();
62
+ exports.Locale = Locale;
63
+ function _get_fromHtmlLangProperty() {
64
+ var _document, _document$documentEle;
65
+ return (_document = document) === null || _document === void 0 ? void 0 : (_document$documentEle = _document.documentElement) === null || _document$documentEle === void 0 ? void 0 : _document$documentEle.lang;
66
+ }
67
+ function _get_fromMetaTag() {
68
+ var _document2, _document2$querySelec;
69
+ return (_document2 = document) === null || _document2 === void 0 ? void 0 : (_document2$querySelec = _document2.querySelector('meta[name="locale"]')) === null || _document2$querySelec === void 0 ? void 0 : _document2$querySelec.content;
70
+ }
71
+ function _get_fromBrowserLanguage() {
72
+ var _navigator, _navigator$language;
73
+ return (_navigator = navigator) === null || _navigator === void 0 ? void 0 : (_navigator$language = _navigator.language) === null || _navigator$language === void 0 ? void 0 : _navigator$language.split('-')[0]; // Extract primary language
74
+ }
75
+ Object.defineProperty(Locale, _fromBrowserLanguage, {
76
+ get: _get_fromBrowserLanguage,
77
+ set: void 0
78
+ });
79
+ Object.defineProperty(Locale, _fromMetaTag, {
80
+ get: _get_fromMetaTag,
81
+ set: void 0
82
+ });
83
+ Object.defineProperty(Locale, _fromHtmlLangProperty, {
84
+ get: _get_fromHtmlLangProperty,
85
+ set: void 0
86
+ });
87
+ Locale._identifier = void 0;
@@ -0,0 +1,81 @@
1
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
3
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
4
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
5
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
6
+ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
7
+ var id = 0;
8
+ function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
9
+ var _fromHtmlLangProperty = /*#__PURE__*/_classPrivateFieldLooseKey("fromHtmlLangProperty");
10
+ var _fromMetaTag = /*#__PURE__*/_classPrivateFieldLooseKey("fromMetaTag");
11
+ var _fromBrowserLanguage = /*#__PURE__*/_classPrivateFieldLooseKey("fromBrowserLanguage");
12
+ /**
13
+ * @class Locale
14
+ * @classdesc
15
+ * Handles locale detection and configuration for the Hellotext library.
16
+ * Provides automatic locale detection from HTML lang attribute, meta tags,
17
+ * and browser language with fallback to 'en'.
18
+ */
19
+ var Locale = /*#__PURE__*/function () {
20
+ function Locale() {
21
+ _classCallCheck(this, Locale);
22
+ }
23
+ _createClass(Locale, null, [{
24
+ key: "identifier",
25
+ get:
26
+ /**
27
+ * Gets the effective locale identifier.
28
+ * Falls back to auto-detection if not explicitly set.
29
+ * @returns {string} The locale identifier
30
+ */
31
+ function get() {
32
+ if (this._identifier) return this._identifier;
33
+ return _classPrivateFieldLooseBase(this, _fromHtmlLangProperty)[_fromHtmlLangProperty] || _classPrivateFieldLooseBase(this, _fromMetaTag)[_fromMetaTag] || _classPrivateFieldLooseBase(this, _fromBrowserLanguage)[_fromBrowserLanguage] || 'en';
34
+ }
35
+
36
+ /**
37
+ * Returns the locale identifier as a string.
38
+ * @returns {string} The locale identifier
39
+ */,
40
+ set:
41
+ /**
42
+ * Sets the locale identifier explicitly.
43
+ * @param {string} value - The locale identifier (e.g., 'en', 'es')
44
+ */
45
+ function set(value) {
46
+ this._identifier = value;
47
+ }
48
+ }, {
49
+ key: "toString",
50
+ value: function toString() {
51
+ return this.identifier;
52
+ }
53
+ }]);
54
+ return Locale;
55
+ }();
56
+ function _get_fromHtmlLangProperty() {
57
+ var _document, _document$documentEle;
58
+ return (_document = document) === null || _document === void 0 ? void 0 : (_document$documentEle = _document.documentElement) === null || _document$documentEle === void 0 ? void 0 : _document$documentEle.lang;
59
+ }
60
+ function _get_fromMetaTag() {
61
+ var _document2, _document2$querySelec;
62
+ return (_document2 = document) === null || _document2 === void 0 ? void 0 : (_document2$querySelec = _document2.querySelector('meta[name="locale"]')) === null || _document2$querySelec === void 0 ? void 0 : _document2$querySelec.content;
63
+ }
64
+ function _get_fromBrowserLanguage() {
65
+ var _navigator, _navigator$language;
66
+ return (_navigator = navigator) === null || _navigator === void 0 ? void 0 : (_navigator$language = _navigator.language) === null || _navigator$language === void 0 ? void 0 : _navigator$language.split('-')[0]; // Extract primary language
67
+ }
68
+ Object.defineProperty(Locale, _fromBrowserLanguage, {
69
+ get: _get_fromBrowserLanguage,
70
+ set: void 0
71
+ });
72
+ Object.defineProperty(Locale, _fromMetaTag, {
73
+ get: _get_fromMetaTag,
74
+ set: void 0
75
+ });
76
+ Object.defineProperty(Locale, _fromHtmlLangProperty, {
77
+ get: _get_fromHtmlLangProperty,
78
+ set: void 0
79
+ });
80
+ Locale._identifier = void 0;
81
+ export { Locale };
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.Configuration = void 0;
7
7
  var _forms = require("./configuration/forms");
8
+ var _locale = require("./configuration/locale");
8
9
  var _webchat = require("./configuration/webchat");
9
10
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
10
11
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
@@ -19,6 +20,7 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
19
20
  * @property {String} [session] - session id
20
21
  * @property {Forms} [forms] - form configuration
21
22
  * @property {Webchat} [webchat] - webchat configuration
23
+ * @property {Locale} [locale] - locale configuration
22
24
  */
23
25
  let Configuration = /*#__PURE__*/function () {
24
26
  function Configuration() {
@@ -49,6 +51,14 @@ let Configuration = /*#__PURE__*/function () {
49
51
  }
50
52
  return this;
51
53
  }
54
+ }, {
55
+ key: "locale",
56
+ get: function () {
57
+ return _locale.Locale.toString();
58
+ },
59
+ set: function (locale) {
60
+ _locale.Locale.identifier = locale;
61
+ }
52
62
  }, {
53
63
  key: "endpoint",
54
64
  value: function endpoint(path) {
@@ -59,6 +69,7 @@ let Configuration = /*#__PURE__*/function () {
59
69
  }();
60
70
  exports.Configuration = Configuration;
61
71
  Configuration.apiRoot = 'https://api.hellotext.com/v1';
72
+ Configuration.actionCableUrl = 'wss://www.hellotext.com/cable';
62
73
  Configuration.autoGenerateSession = true;
63
74
  Configuration.session = null;
64
75
  Configuration.forms = _forms.Forms;
@@ -4,6 +4,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
4
4
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
5
5
  function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
6
6
  import { Forms } from './configuration/forms';
7
+ import { Locale } from './configuration/locale';
7
8
  import { Webchat } from './configuration/webchat';
8
9
 
9
10
  /**
@@ -14,6 +15,7 @@ import { Webchat } from './configuration/webchat';
14
15
  * @property {String} [session] - session id
15
16
  * @property {Forms} [forms] - form configuration
16
17
  * @property {Webchat} [webchat] - webchat configuration
18
+ * @property {Locale} [locale] - locale configuration
17
19
  */
18
20
  var Configuration = /*#__PURE__*/function () {
19
21
  function Configuration() {
@@ -45,6 +47,14 @@ var Configuration = /*#__PURE__*/function () {
45
47
  }
46
48
  return this;
47
49
  }
50
+ }, {
51
+ key: "locale",
52
+ get: function get() {
53
+ return Locale.toString();
54
+ },
55
+ set: function set(locale) {
56
+ Locale.identifier = locale;
57
+ }
48
58
  }, {
49
59
  key: "endpoint",
50
60
  value: function endpoint(path) {
@@ -54,6 +64,7 @@ var Configuration = /*#__PURE__*/function () {
54
64
  return Configuration;
55
65
  }();
56
66
  Configuration.apiRoot = 'https://api.hellotext.com/v1';
67
+ Configuration.actionCableUrl = 'wss://www.hellotext.com/cable';
57
68
  Configuration.autoGenerateSession = true;
58
69
  Configuration.session = null;
59
70
  Configuration.forms = Forms;
@@ -15,6 +15,20 @@ Object.defineProperty(exports, "Event", {
15
15
  return _event.default;
16
16
  }
17
17
  });
18
- var _event = _interopRequireDefault(require("./event"));
18
+ Object.defineProperty(exports, "Locale", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _locale.Locale;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "Webchat", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _webchat.Webchat;
28
+ }
29
+ });
19
30
  var _configuration = require("./configuration");
31
+ var _locale = require("./configuration/locale");
32
+ var _webchat = require("./configuration/webchat");
33
+ var _event = _interopRequireDefault(require("./event"));
20
34
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
package/lib/core/index.js CHANGED
@@ -1,2 +1,4 @@
1
- export { default as Event } from './event';
2
- export { Configuration } from './configuration';
1
+ export { Configuration } from './configuration';
2
+ export { Locale } from './configuration/locale';
3
+ export { Webchat } from './configuration/webchat';
4
+ export { default as Event } from './event';
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _default = {
8
8
  white_label: {
9
- powered_by: 'Powered by'
9
+ powered_by: 'By'
10
10
  },
11
11
  errors: {
12
12
  parameter_not_unique: 'This value is taken.',
package/lib/locales/en.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  white_label: {
3
- powered_by: 'Powered by'
3
+ powered_by: 'By'
4
4
  },
5
5
  errors: {
6
6
  parameter_not_unique: 'This value is taken.',
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _default = {
8
8
  white_label: {
9
- powered_by: 'Desarrollado por'
9
+ powered_by: 'Por'
10
10
  },
11
11
  errors: {
12
12
  parameter_not_unique: 'Este valor ya está en uso.',