@hellotext/hellotext 2.1.51 → 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.
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _stimulus = require("@hotwired/stimulus");
8
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
9
+ 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); } }
10
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
11
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
12
+ 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); }
13
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
14
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
15
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
16
+ function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
17
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
18
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
19
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
20
+ let _default = /*#__PURE__*/function (_Controller) {
21
+ _inherits(_default, _Controller);
22
+ var _super = _createSuper(_default);
23
+ function _default() {
24
+ _classCallCheck(this, _default);
25
+ return _super.apply(this, arguments);
26
+ }
27
+ _createClass(_default, [{
28
+ key: "connect",
29
+ value: function connect() {
30
+ this.updateFades();
31
+ }
32
+ }, {
33
+ key: "setId",
34
+ value: function setId({
35
+ detail: id
36
+ }) {
37
+ this.idValue = id;
38
+ this.element.id = id;
39
+ }
40
+ }, {
41
+ key: "onScroll",
42
+ value: function onScroll() {
43
+ this.updateFades();
44
+ }
45
+ }, {
46
+ key: "quickReply",
47
+ value: function quickReply({
48
+ currentTarget
49
+ }) {
50
+ const card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]');
51
+ this.dispatch('quickReply', {
52
+ detail: {
53
+ id: this.idValue,
54
+ product: card.dataset.id,
55
+ buttonId: currentTarget.dataset.id,
56
+ body: currentTarget.dataset.text,
57
+ cardElement: card
58
+ }
59
+ });
60
+ }
61
+ }, {
62
+ key: "moveToLeft",
63
+ value: function moveToLeft() {
64
+ if (!this.hasCarouselContainerTarget) return;
65
+ const scrollAmount = this.getScrollAmount();
66
+ this.carouselContainerTarget.scrollBy({
67
+ left: -scrollAmount,
68
+ behavior: 'smooth'
69
+ });
70
+ }
71
+ }, {
72
+ key: "moveToRight",
73
+ value: function moveToRight() {
74
+ if (!this.hasCarouselContainerTarget) return;
75
+ const scrollAmount = this.getScrollAmount();
76
+ this.carouselContainerTarget.scrollBy({
77
+ left: scrollAmount,
78
+ behavior: 'smooth'
79
+ });
80
+ }
81
+ }, {
82
+ key: "getScrollAmount",
83
+ value: function getScrollAmount() {
84
+ // Get the actual card width from DOM
85
+ const firstCard = this.carouselContainerTarget.querySelector('.message__carousel_card');
86
+ if (!firstCard) {
87
+ return 280; // Fallback to default desktop card width
88
+ }
89
+
90
+ const cardWidth = firstCard.offsetWidth;
91
+ const gap = 16; // gap-x-4 = 1rem = 16px
92
+
93
+ return cardWidth + gap;
94
+ }
95
+ }, {
96
+ key: "updateFades",
97
+ value: function updateFades() {
98
+ if (!this.hasCarouselContainerTarget) return;
99
+ const scrollLeft = this.carouselContainerTarget.scrollLeft;
100
+ const maxScroll = this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth;
101
+
102
+ // Show left fade if scrolled past start
103
+ if (scrollLeft > 0) {
104
+ this.leftFadeTarget.classList.remove('hidden');
105
+ } else {
106
+ this.leftFadeTarget.classList.add('hidden');
107
+ }
108
+
109
+ // Show right fade if not at end
110
+ if (scrollLeft < maxScroll - 1) {
111
+ // -1 for rounding errors
112
+ this.rightFadeTarget.classList.remove('hidden');
113
+ } else {
114
+ this.rightFadeTarget.classList.add('hidden');
115
+ }
116
+ }
117
+ }]);
118
+ return _default;
119
+ }(_stimulus.Controller);
120
+ exports.default = _default;
121
+ _default.values = {
122
+ id: String
123
+ };
124
+ _default.targets = ['carouselContainer', 'leftFade', 'rightFade', 'carouselCard'];
@@ -0,0 +1,120 @@
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 _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
7
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
8
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
9
+ function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
10
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
11
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
12
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
13
+ import { Controller } from '@hotwired/stimulus';
14
+ var _default = /*#__PURE__*/function (_Controller) {
15
+ _inherits(_default, _Controller);
16
+ var _super = _createSuper(_default);
17
+ function _default() {
18
+ _classCallCheck(this, _default);
19
+ return _super.apply(this, arguments);
20
+ }
21
+ _createClass(_default, [{
22
+ key: "connect",
23
+ value: function connect() {
24
+ this.updateFades();
25
+ }
26
+ }, {
27
+ key: "setId",
28
+ value: function setId(_ref) {
29
+ var {
30
+ detail: id
31
+ } = _ref;
32
+ this.idValue = id;
33
+ this.element.id = id;
34
+ }
35
+ }, {
36
+ key: "onScroll",
37
+ value: function onScroll() {
38
+ this.updateFades();
39
+ }
40
+ }, {
41
+ key: "quickReply",
42
+ value: function quickReply(_ref2) {
43
+ var {
44
+ currentTarget
45
+ } = _ref2;
46
+ var card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]');
47
+ this.dispatch('quickReply', {
48
+ detail: {
49
+ id: this.idValue,
50
+ product: card.dataset.id,
51
+ buttonId: currentTarget.dataset.id,
52
+ body: currentTarget.dataset.text,
53
+ cardElement: card
54
+ }
55
+ });
56
+ }
57
+ }, {
58
+ key: "moveToLeft",
59
+ value: function moveToLeft() {
60
+ if (!this.hasCarouselContainerTarget) return;
61
+ var scrollAmount = this.getScrollAmount();
62
+ this.carouselContainerTarget.scrollBy({
63
+ left: -scrollAmount,
64
+ behavior: 'smooth'
65
+ });
66
+ }
67
+ }, {
68
+ key: "moveToRight",
69
+ value: function moveToRight() {
70
+ if (!this.hasCarouselContainerTarget) return;
71
+ var scrollAmount = this.getScrollAmount();
72
+ this.carouselContainerTarget.scrollBy({
73
+ left: scrollAmount,
74
+ behavior: 'smooth'
75
+ });
76
+ }
77
+ }, {
78
+ key: "getScrollAmount",
79
+ value: function getScrollAmount() {
80
+ // Get the actual card width from DOM
81
+ var firstCard = this.carouselContainerTarget.querySelector('.message__carousel_card');
82
+ if (!firstCard) {
83
+ return 280; // Fallback to default desktop card width
84
+ }
85
+
86
+ var cardWidth = firstCard.offsetWidth;
87
+ var gap = 16; // gap-x-4 = 1rem = 16px
88
+
89
+ return cardWidth + gap;
90
+ }
91
+ }, {
92
+ key: "updateFades",
93
+ value: function updateFades() {
94
+ if (!this.hasCarouselContainerTarget) return;
95
+ var scrollLeft = this.carouselContainerTarget.scrollLeft;
96
+ var maxScroll = this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth;
97
+
98
+ // Show left fade if scrolled past start
99
+ if (scrollLeft > 0) {
100
+ this.leftFadeTarget.classList.remove('hidden');
101
+ } else {
102
+ this.leftFadeTarget.classList.add('hidden');
103
+ }
104
+
105
+ // Show right fade if not at end
106
+ if (scrollLeft < maxScroll - 1) {
107
+ // -1 for rounding errors
108
+ this.rightFadeTarget.classList.remove('hidden');
109
+ } else {
110
+ this.rightFadeTarget.classList.add('hidden');
111
+ }
112
+ }
113
+ }]);
114
+ return _default;
115
+ }(Controller);
116
+ _default.values = {
117
+ id: String
118
+ };
119
+ _default.targets = ['carouselContainer', 'leftFade', 'rightFade', 'carouselCard'];
120
+ export { _default as default };
@@ -313,6 +313,9 @@ let _default = /*#__PURE__*/function (_Controller) {
313
313
  body,
314
314
  attachments
315
315
  } = message;
316
+ if (message.carousel) {
317
+ return this.insertCarouselMessage(message);
318
+ }
316
319
  const div = document.createElement('div');
317
320
  div.innerHTML = body;
318
321
  const element = this.messageTemplateTarget.cloneNode(true);
@@ -344,6 +347,29 @@ let _default = /*#__PURE__*/function (_Controller) {
344
347
  const unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
345
348
  this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
346
349
  }
350
+ }, {
351
+ key: "insertCarouselMessage",
352
+ value: function insertCarouselMessage(message) {
353
+ var _element$querySelecto;
354
+ const html = message.html;
355
+ const element = new DOMParser().parseFromString(html, 'text/html').body.firstElementChild;
356
+ this.clearTypingIndicator();
357
+ this.messagesContainerTarget.appendChild(element);
358
+ element.scrollIntoView({
359
+ behavior: 'smooth'
360
+ });
361
+ _hellotext.default.eventEmitter.dispatch('webchat:message:received', {
362
+ ...message,
363
+ body: ((_element$querySelecto = element.querySelector('[data-body]')) === null || _element$querySelecto === void 0 ? void 0 : _element$querySelecto.innerText) || ''
364
+ });
365
+ if (this.openValue) {
366
+ this.messagesAPI.markAsSeen(message.id);
367
+ return;
368
+ }
369
+ this.unreadCounterTarget.style.display = 'flex';
370
+ const unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
371
+ this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
372
+ }
347
373
  }, {
348
374
  key: "resizeInput",
349
375
  value: function resizeInput() {
@@ -357,6 +383,71 @@ let _default = /*#__PURE__*/function (_Controller) {
357
383
  const scrollHeight = this.inputTarget.scrollHeight;
358
384
  this.inputTarget.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
359
385
  }
386
+ }, {
387
+ key: "sendQuickReplyMessage",
388
+ value: async function sendQuickReplyMessage({
389
+ detail: {
390
+ id,
391
+ product,
392
+ buttonId,
393
+ body,
394
+ cardElement
395
+ }
396
+ }) {
397
+ var _cardElement$querySel;
398
+ const formData = new FormData();
399
+ formData.append('message[body]', body);
400
+ formData.append('message[replied_to]', id);
401
+ formData.append('message[product]', product);
402
+ formData.append('message[button]', buttonId);
403
+ formData.append('session', _hellotext.default.session);
404
+ formData.append('locale', _core.Locale.toString());
405
+ const element = this.buildMessageElement();
406
+ const attachment = (_cardElement$querySel = cardElement.querySelector('img')) === null || _cardElement$querySel === void 0 ? void 0 : _cardElement$querySel.cloneNode(true);
407
+ element.querySelector('[data-body]').innerText = body;
408
+ if (attachment) {
409
+ attachment.removeAttribute('width');
410
+ attachment.removeAttribute('height');
411
+ element.querySelector('[data-attachment-container]').appendChild(attachment);
412
+ }
413
+ if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
414
+ this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
415
+ } else {
416
+ this.messagesContainerTarget.appendChild(element);
417
+ }
418
+ element.scrollIntoView({
419
+ behavior: 'smooth'
420
+ });
421
+ this.broadcastChannel.postMessage({
422
+ type: 'message:sent',
423
+ element: element.outerHTML
424
+ });
425
+ const response = await this.messagesAPI.create(formData);
426
+ if (response.failed) {
427
+ // Clear the optimistic typing indicator on failure
428
+ clearTimeout(this.optimisticTypingTimeout);
429
+ this.broadcastChannel.postMessage({
430
+ type: 'message:failed',
431
+ id: element.id
432
+ });
433
+ return element.classList.add('failed');
434
+ }
435
+ const data = await response.json();
436
+ this.dispatch('set:id', {
437
+ target: element,
438
+ detail: data.id
439
+ });
440
+ const message = {
441
+ id: data.id,
442
+ body: body,
443
+ attachments: attachment ? [attachment.src] : [],
444
+ replied_to: id,
445
+ product: product,
446
+ button: buttonId,
447
+ type: 'quick_reply'
448
+ };
449
+ _hellotext.default.eventEmitter.dispatch('webchat:message:sent', message);
450
+ }
360
451
  }, {
361
452
  key: "sendMessage",
362
453
  value: async function sendMessage(e) {
@@ -381,11 +472,7 @@ let _default = /*#__PURE__*/function (_Controller) {
381
472
  });
382
473
  formData.append('session', _hellotext.default.session);
383
474
  formData.append('locale', _core.Locale.toString());
384
- const element = this.messageTemplateTarget.cloneNode(true);
385
- element.id = `hellotext--webchat--${this.idValue}--message--${Date.now()}`;
386
- element.classList.add('received');
387
- element.style.removeProperty('display');
388
- element.setAttribute('data-hellotext--webchat-target', 'message');
475
+ const element = this.buildMessageElement();
389
476
  if (this.inputTarget.value.trim().length > 0) {
390
477
  element.querySelector('[data-body]').innerText = this.inputTarget.value;
391
478
  } else {
@@ -394,7 +481,7 @@ let _default = /*#__PURE__*/function (_Controller) {
394
481
  const attachments = this.attachmentContainerTarget.querySelectorAll('img');
395
482
  if (attachments.length > 0) {
396
483
  attachments.forEach(attachment => {
397
- element.querySelector('[data-attachment-container]').appendChild(attachment);
484
+ element.querySelector('[data-attachment-container]').appendChild(attachment.cloneNode(true));
398
485
  });
399
486
  }
400
487
 
@@ -453,6 +540,17 @@ let _default = /*#__PURE__*/function (_Controller) {
453
540
  }
454
541
  this.attachmentContainerTarget.style.display = '';
455
542
  }
543
+ }, {
544
+ key: "buildMessageElement",
545
+ value: function buildMessageElement() {
546
+ const element = this.messageTemplateTarget.cloneNode(true);
547
+ element.id = `hellotext--webchat--${this.idValue}--message--${Date.now()}`;
548
+ element.classList.add('received');
549
+ element.style.removeProperty('display');
550
+ element.setAttribute('data-controller', 'hellotext--message');
551
+ element.setAttribute('data-hellotext--webchat-target', 'message');
552
+ return element;
553
+ }
456
554
  }, {
457
555
  key: "openAttachment",
458
556
  value: function openAttachment() {
@@ -317,6 +317,9 @@ var _default = /*#__PURE__*/function (_Controller) {
317
317
  body,
318
318
  attachments
319
319
  } = message;
320
+ if (message.carousel) {
321
+ return this.insertCarouselMessage(message);
322
+ }
320
323
  var div = document.createElement('div');
321
324
  div.innerHTML = body;
322
325
  var element = this.messageTemplateTarget.cloneNode(true);
@@ -347,6 +350,28 @@ var _default = /*#__PURE__*/function (_Controller) {
347
350
  var unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
348
351
  this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
349
352
  }
353
+ }, {
354
+ key: "insertCarouselMessage",
355
+ value: function insertCarouselMessage(message) {
356
+ var _element$querySelecto;
357
+ var html = message.html;
358
+ var element = new DOMParser().parseFromString(html, 'text/html').body.firstElementChild;
359
+ this.clearTypingIndicator();
360
+ this.messagesContainerTarget.appendChild(element);
361
+ element.scrollIntoView({
362
+ behavior: 'smooth'
363
+ });
364
+ Hellotext.eventEmitter.dispatch('webchat:message:received', _objectSpread(_objectSpread({}, message), {}, {
365
+ body: ((_element$querySelecto = element.querySelector('[data-body]')) === null || _element$querySelecto === void 0 ? void 0 : _element$querySelecto.innerText) || ''
366
+ }));
367
+ if (this.openValue) {
368
+ this.messagesAPI.markAsSeen(message.id);
369
+ return;
370
+ }
371
+ this.unreadCounterTarget.style.display = 'flex';
372
+ var unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
373
+ this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
374
+ }
350
375
  }, {
351
376
  key: "resizeInput",
352
377
  value: function resizeInput() {
@@ -360,6 +385,78 @@ var _default = /*#__PURE__*/function (_Controller) {
360
385
  var scrollHeight = this.inputTarget.scrollHeight;
361
386
  this.inputTarget.style.height = "".concat(Math.min(scrollHeight, maxHeight), "px");
362
387
  }
388
+ }, {
389
+ key: "sendQuickReplyMessage",
390
+ value: function () {
391
+ var _sendQuickReplyMessage = _asyncToGenerator(function* (_ref) {
392
+ var _cardElement$querySel;
393
+ var {
394
+ detail: {
395
+ id,
396
+ product,
397
+ buttonId,
398
+ body,
399
+ cardElement
400
+ }
401
+ } = _ref;
402
+ var formData = new FormData();
403
+ formData.append('message[body]', body);
404
+ formData.append('message[replied_to]', id);
405
+ formData.append('message[product]', product);
406
+ formData.append('message[button]', buttonId);
407
+ formData.append('session', Hellotext.session);
408
+ formData.append('locale', Locale.toString());
409
+ var element = this.buildMessageElement();
410
+ var attachment = (_cardElement$querySel = cardElement.querySelector('img')) === null || _cardElement$querySel === void 0 ? void 0 : _cardElement$querySel.cloneNode(true);
411
+ element.querySelector('[data-body]').innerText = body;
412
+ if (attachment) {
413
+ attachment.removeAttribute('width');
414
+ attachment.removeAttribute('height');
415
+ element.querySelector('[data-attachment-container]').appendChild(attachment);
416
+ }
417
+ if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
418
+ this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
419
+ } else {
420
+ this.messagesContainerTarget.appendChild(element);
421
+ }
422
+ element.scrollIntoView({
423
+ behavior: 'smooth'
424
+ });
425
+ this.broadcastChannel.postMessage({
426
+ type: 'message:sent',
427
+ element: element.outerHTML
428
+ });
429
+ var response = yield this.messagesAPI.create(formData);
430
+ if (response.failed) {
431
+ // Clear the optimistic typing indicator on failure
432
+ clearTimeout(this.optimisticTypingTimeout);
433
+ this.broadcastChannel.postMessage({
434
+ type: 'message:failed',
435
+ id: element.id
436
+ });
437
+ return element.classList.add('failed');
438
+ }
439
+ var data = yield response.json();
440
+ this.dispatch('set:id', {
441
+ target: element,
442
+ detail: data.id
443
+ });
444
+ var message = {
445
+ id: data.id,
446
+ body: body,
447
+ attachments: attachment ? [attachment.src] : [],
448
+ replied_to: id,
449
+ product: product,
450
+ button: buttonId,
451
+ type: 'quick_reply'
452
+ };
453
+ Hellotext.eventEmitter.dispatch('webchat:message:sent', message);
454
+ });
455
+ function sendQuickReplyMessage(_x) {
456
+ return _sendQuickReplyMessage.apply(this, arguments);
457
+ }
458
+ return sendQuickReplyMessage;
459
+ }()
363
460
  }, {
364
461
  key: "sendMessage",
365
462
  value: function () {
@@ -385,11 +482,7 @@ var _default = /*#__PURE__*/function (_Controller) {
385
482
  });
386
483
  formData.append('session', Hellotext.session);
387
484
  formData.append('locale', Locale.toString());
388
- var element = this.messageTemplateTarget.cloneNode(true);
389
- element.id = "hellotext--webchat--".concat(this.idValue, "--message--").concat(Date.now());
390
- element.classList.add('received');
391
- element.style.removeProperty('display');
392
- element.setAttribute('data-hellotext--webchat-target', 'message');
485
+ var element = this.buildMessageElement();
393
486
  if (this.inputTarget.value.trim().length > 0) {
394
487
  element.querySelector('[data-body]').innerText = this.inputTarget.value;
395
488
  } else {
@@ -398,7 +491,7 @@ var _default = /*#__PURE__*/function (_Controller) {
398
491
  var attachments = this.attachmentContainerTarget.querySelectorAll('img');
399
492
  if (attachments.length > 0) {
400
493
  attachments.forEach(attachment => {
401
- element.querySelector('[data-attachment-container]').appendChild(attachment);
494
+ element.querySelector('[data-attachment-container]').appendChild(attachment.cloneNode(true));
402
495
  });
403
496
  }
404
497
 
@@ -457,11 +550,22 @@ var _default = /*#__PURE__*/function (_Controller) {
457
550
  }
458
551
  this.attachmentContainerTarget.style.display = '';
459
552
  });
460
- function sendMessage(_x) {
553
+ function sendMessage(_x2) {
461
554
  return _sendMessage.apply(this, arguments);
462
555
  }
463
556
  return sendMessage;
464
557
  }()
558
+ }, {
559
+ key: "buildMessageElement",
560
+ value: function buildMessageElement() {
561
+ var element = this.messageTemplateTarget.cloneNode(true);
562
+ element.id = "hellotext--webchat--".concat(this.idValue, "--message--").concat(Date.now());
563
+ element.classList.add('received');
564
+ element.style.removeProperty('display');
565
+ element.setAttribute('data-controller', 'hellotext--message');
566
+ element.setAttribute('data-hellotext--webchat-target', 'message');
567
+ return element;
568
+ }
465
569
  }, {
466
570
  key: "openAttachment",
467
571
  value: function openAttachment() {
@@ -518,10 +622,10 @@ var _default = /*#__PURE__*/function (_Controller) {
518
622
  }
519
623
  }, {
520
624
  key: "removeAttachment",
521
- value: function removeAttachment(_ref) {
625
+ value: function removeAttachment(_ref2) {
522
626
  var {
523
627
  currentTarget
524
- } = _ref;
628
+ } = _ref2;
525
629
  var attachment = currentTarget.closest("[data-hellotext--webchat-target='attachment']");
526
630
  this.files = this.files.filter(file => file.name !== attachment.dataset.name);
527
631
  this.attachmentInputTarget.value = '';
@@ -547,10 +651,10 @@ var _default = /*#__PURE__*/function (_Controller) {
547
651
  }
548
652
  }, {
549
653
  key: "onEmojiSelect",
550
- value: function onEmojiSelect(_ref2) {
654
+ value: function onEmojiSelect(_ref3) {
551
655
  var {
552
656
  detail: emoji
553
- } = _ref2;
657
+ } = _ref3;
554
658
  var value = this.inputTarget.value;
555
659
  var start = this.inputTarget.selectionStart;
556
660
  var end = this.inputTarget.selectionEnd;
package/lib/index.cjs CHANGED
@@ -7,6 +7,7 @@ exports.default = void 0;
7
7
  var _stimulus = require("@hotwired/stimulus");
8
8
  var _hellotext = _interopRequireDefault(require("./hellotext"));
9
9
  var _form_controller = _interopRequireDefault(require("./controllers/form_controller"));
10
+ var _message_controller = _interopRequireDefault(require("./controllers/message_controller"));
10
11
  var _emoji_picker_controller = _interopRequireDefault(require("./controllers/webchat/emoji_picker_controller"));
11
12
  var _webchat_controller = _interopRequireDefault(require("./controllers/webchat_controller"));
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -14,6 +15,7 @@ const application = _stimulus.Application.start();
14
15
  application.register('hellotext--form', _form_controller.default);
15
16
  application.register('hellotext--webchat', _webchat_controller.default);
16
17
  application.register('hellotext--webchat--emoji', _emoji_picker_controller.default);
18
+ application.register('hellotext--message', _message_controller.default);
17
19
  window.Hellotext = _hellotext.default;
18
20
  var _default = _hellotext.default;
19
21
  exports.default = _default;
package/lib/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { Application } from '@hotwired/stimulus';
2
2
  import Hellotext from './hellotext';
3
3
  import FormController from './controllers/form_controller';
4
+ import MessageController from './controllers/message_controller';
4
5
  import WebChatEmojiController from './controllers/webchat/emoji_picker_controller';
5
6
  import WebchatController from './controllers/webchat_controller';
6
7
  var application = Application.start();
7
8
  application.register('hellotext--form', FormController);
8
9
  application.register('hellotext--webchat', WebchatController);
9
10
  application.register('hellotext--webchat--emoji', WebChatEmojiController);
11
+ application.register('hellotext--message', MessageController);
10
12
  window.Hellotext = Hellotext;
11
13
  export default Hellotext;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hellotext/hellotext",
3
- "version": "2.1.51",
3
+ "version": "2.2.0",
4
4
  "description": "Hellotext JavaScript Client",
5
5
  "source": "src/index.js",
6
6
  "main": "lib/index.cjs",