@hellotext/hellotext 2.1.6 → 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 };
@@ -255,6 +255,7 @@ let _default = /*#__PURE__*/function (_Controller) {
255
255
  }, {
256
256
  key: "onPopoverOpened",
257
257
  value: function onPopoverOpened() {
258
+ this.popoverTarget.classList.remove(...this.fadeOutClasses);
258
259
  if (!this.onMobile) {
259
260
  this.inputTarget.focus();
260
261
  }
@@ -312,6 +313,9 @@ let _default = /*#__PURE__*/function (_Controller) {
312
313
  body,
313
314
  attachments
314
315
  } = message;
316
+ if (message.carousel) {
317
+ return this.insertCarouselMessage(message);
318
+ }
315
319
  const div = document.createElement('div');
316
320
  div.innerHTML = body;
317
321
  const element = this.messageTemplateTarget.cloneNode(true);
@@ -343,6 +347,29 @@ let _default = /*#__PURE__*/function (_Controller) {
343
347
  const unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
344
348
  this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
345
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
+ }
346
373
  }, {
347
374
  key: "resizeInput",
348
375
  value: function resizeInput() {
@@ -356,6 +383,71 @@ let _default = /*#__PURE__*/function (_Controller) {
356
383
  const scrollHeight = this.inputTarget.scrollHeight;
357
384
  this.inputTarget.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
358
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
+ }
359
451
  }, {
360
452
  key: "sendMessage",
361
453
  value: async function sendMessage(e) {
@@ -380,11 +472,7 @@ let _default = /*#__PURE__*/function (_Controller) {
380
472
  });
381
473
  formData.append('session', _hellotext.default.session);
382
474
  formData.append('locale', _core.Locale.toString());
383
- const element = this.messageTemplateTarget.cloneNode(true);
384
- element.id = `hellotext--webchat--${this.idValue}--message--${Date.now()}`;
385
- element.classList.add('received');
386
- element.style.removeProperty('display');
387
- element.setAttribute('data-hellotext--webchat-target', 'message');
475
+ const element = this.buildMessageElement();
388
476
  if (this.inputTarget.value.trim().length > 0) {
389
477
  element.querySelector('[data-body]').innerText = this.inputTarget.value;
390
478
  } else {
@@ -393,7 +481,7 @@ let _default = /*#__PURE__*/function (_Controller) {
393
481
  const attachments = this.attachmentContainerTarget.querySelectorAll('img');
394
482
  if (attachments.length > 0) {
395
483
  attachments.forEach(attachment => {
396
- element.querySelector('[data-attachment-container]').appendChild(attachment);
484
+ element.querySelector('[data-attachment-container]').appendChild(attachment.cloneNode(true));
397
485
  });
398
486
  }
399
487
 
@@ -452,6 +540,17 @@ let _default = /*#__PURE__*/function (_Controller) {
452
540
  }
453
541
  this.attachmentContainerTarget.style.display = '';
454
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
+ }
455
554
  }, {
456
555
  key: "openAttachment",
457
556
  value: function openAttachment() {
@@ -259,6 +259,7 @@ var _default = /*#__PURE__*/function (_Controller) {
259
259
  }, {
260
260
  key: "onPopoverOpened",
261
261
  value: function onPopoverOpened() {
262
+ this.popoverTarget.classList.remove(...this.fadeOutClasses);
262
263
  if (!this.onMobile) {
263
264
  this.inputTarget.focus();
264
265
  }
@@ -316,6 +317,9 @@ var _default = /*#__PURE__*/function (_Controller) {
316
317
  body,
317
318
  attachments
318
319
  } = message;
320
+ if (message.carousel) {
321
+ return this.insertCarouselMessage(message);
322
+ }
319
323
  var div = document.createElement('div');
320
324
  div.innerHTML = body;
321
325
  var element = this.messageTemplateTarget.cloneNode(true);
@@ -346,6 +350,28 @@ var _default = /*#__PURE__*/function (_Controller) {
346
350
  var unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
347
351
  this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
348
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
+ }
349
375
  }, {
350
376
  key: "resizeInput",
351
377
  value: function resizeInput() {
@@ -359,6 +385,78 @@ var _default = /*#__PURE__*/function (_Controller) {
359
385
  var scrollHeight = this.inputTarget.scrollHeight;
360
386
  this.inputTarget.style.height = "".concat(Math.min(scrollHeight, maxHeight), "px");
361
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
+ }()
362
460
  }, {
363
461
  key: "sendMessage",
364
462
  value: function () {
@@ -384,11 +482,7 @@ var _default = /*#__PURE__*/function (_Controller) {
384
482
  });
385
483
  formData.append('session', Hellotext.session);
386
484
  formData.append('locale', Locale.toString());
387
- var element = this.messageTemplateTarget.cloneNode(true);
388
- element.id = "hellotext--webchat--".concat(this.idValue, "--message--").concat(Date.now());
389
- element.classList.add('received');
390
- element.style.removeProperty('display');
391
- element.setAttribute('data-hellotext--webchat-target', 'message');
485
+ var element = this.buildMessageElement();
392
486
  if (this.inputTarget.value.trim().length > 0) {
393
487
  element.querySelector('[data-body]').innerText = this.inputTarget.value;
394
488
  } else {
@@ -397,7 +491,7 @@ var _default = /*#__PURE__*/function (_Controller) {
397
491
  var attachments = this.attachmentContainerTarget.querySelectorAll('img');
398
492
  if (attachments.length > 0) {
399
493
  attachments.forEach(attachment => {
400
- element.querySelector('[data-attachment-container]').appendChild(attachment);
494
+ element.querySelector('[data-attachment-container]').appendChild(attachment.cloneNode(true));
401
495
  });
402
496
  }
403
497
 
@@ -456,11 +550,22 @@ var _default = /*#__PURE__*/function (_Controller) {
456
550
  }
457
551
  this.attachmentContainerTarget.style.display = '';
458
552
  });
459
- function sendMessage(_x) {
553
+ function sendMessage(_x2) {
460
554
  return _sendMessage.apply(this, arguments);
461
555
  }
462
556
  return sendMessage;
463
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
+ }
464
569
  }, {
465
570
  key: "openAttachment",
466
571
  value: function openAttachment() {
@@ -517,10 +622,10 @@ var _default = /*#__PURE__*/function (_Controller) {
517
622
  }
518
623
  }, {
519
624
  key: "removeAttachment",
520
- value: function removeAttachment(_ref) {
625
+ value: function removeAttachment(_ref2) {
521
626
  var {
522
627
  currentTarget
523
- } = _ref;
628
+ } = _ref2;
524
629
  var attachment = currentTarget.closest("[data-hellotext--webchat-target='attachment']");
525
630
  this.files = this.files.filter(file => file.name !== attachment.dataset.name);
526
631
  this.attachmentInputTarget.value = '';
@@ -546,10 +651,10 @@ var _default = /*#__PURE__*/function (_Controller) {
546
651
  }
547
652
  }, {
548
653
  key: "onEmojiSelect",
549
- value: function onEmojiSelect(_ref2) {
654
+ value: function onEmojiSelect(_ref3) {
550
655
  var {
551
656
  detail: emoji
552
- } = _ref2;
657
+ } = _ref3;
553
658
  var value = this.inputTarget.value;
554
659
  var start = this.inputTarget.selectionStart;
555
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.6",
3
+ "version": "2.2.0",
4
4
  "description": "Hellotext JavaScript Client",
5
5
  "source": "src/index.js",
6
6
  "main": "lib/index.cjs",