@hellotext/hellotext 1.8.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/hellotext.js +1 -1
  2. package/lib/api/businesses.cjs +37 -0
  3. package/lib/api/businesses.js +3 -9
  4. package/lib/api/events.cjs +45 -0
  5. package/lib/api/events.js +8 -14
  6. package/lib/api/forms.cjs +51 -0
  7. package/lib/api/forms.js +10 -17
  8. package/lib/api/index.cjs +51 -0
  9. package/lib/api/index.js +10 -23
  10. package/lib/api/response.cjs +76 -0
  11. package/lib/api/response.js +1 -7
  12. package/lib/api/submissions.cjs +47 -0
  13. package/lib/api/submissions.js +9 -17
  14. package/lib/api/webchat/messages.cjs +70 -0
  15. package/lib/api/webchat/messages.js +10 -18
  16. package/lib/api/webchats.cjs +44 -0
  17. package/lib/api/webchats.js +8 -16
  18. package/lib/builders/input_builder.cjs +61 -0
  19. package/lib/builders/input_builder.js +4 -11
  20. package/lib/builders/logo_builder.cjs +50 -0
  21. package/lib/builders/logo_builder.js +5 -12
  22. package/lib/channels/application_channel.cjs +67 -0
  23. package/lib/channels/application_channel.js +1 -8
  24. package/lib/channels/{web_chat_channel.js → webchat_channel.cjs} +35 -20
  25. package/lib/channels/webchat_channel.js +3 -11
  26. package/lib/controllers/form_controller.cjs +141 -0
  27. package/lib/controllers/form_controller.js +15 -22
  28. package/lib/controllers/mixins/usePopover.cjs +59 -0
  29. package/lib/controllers/mixins/usePopover.js +6 -14
  30. package/lib/controllers/{web_chat/pagination_controller.js → webchat/emoji_picker_controller.cjs} +74 -29
  31. package/lib/controllers/webchat/emoji_picker_controller.js +11 -17
  32. package/lib/controllers/webchat_controller.cjs +433 -0
  33. package/lib/controllers/webchat_controller.js +49 -51
  34. package/lib/core/configuration/forms.cjs +49 -0
  35. package/lib/core/configuration/forms.js +2 -8
  36. package/lib/core/configuration/{web_chat.js → webchat.cjs} +53 -38
  37. package/lib/core/configuration/webchat.js +2 -9
  38. package/lib/core/configuration.cjs +65 -0
  39. package/lib/core/configuration.js +8 -13
  40. package/lib/core/event.cjs +71 -0
  41. package/lib/core/event.js +5 -11
  42. package/lib/core/index.cjs +20 -0
  43. package/lib/core/index.js +2 -20
  44. package/lib/errors/index.cjs +19 -0
  45. package/lib/errors/index.js +2 -19
  46. package/lib/errors/invalid_event.cjs +34 -0
  47. package/lib/errors/invalid_event.js +1 -7
  48. package/lib/errors/not_initialized_error.cjs +34 -0
  49. package/lib/errors/not_initialized_error.js +1 -7
  50. package/lib/hellotext.cjs +152 -0
  51. package/lib/hellotext.js +18 -27
  52. package/lib/index.cjs +20 -0
  53. package/lib/index.js +12 -20
  54. package/lib/locales/en.cjs +22 -0
  55. package/lib/locales/en.js +2 -9
  56. package/lib/locales/es.cjs +22 -0
  57. package/lib/locales/es.js +2 -9
  58. package/lib/locales/index.cjs +14 -0
  59. package/lib/locales/index.js +6 -14
  60. package/lib/models/business.cjs +65 -0
  61. package/lib/models/business.js +5 -12
  62. package/lib/models/cookies.cjs +40 -0
  63. package/lib/models/cookies.js +3 -10
  64. package/lib/models/form.cjs +166 -0
  65. package/lib/models/form.js +10 -17
  66. package/lib/models/form_collection.cjs +119 -0
  67. package/lib/models/form_collection.js +15 -22
  68. package/lib/models/index.cjs +54 -0
  69. package/lib/models/index.js +7 -54
  70. package/lib/models/query.cjs +51 -0
  71. package/lib/models/query.js +3 -9
  72. package/lib/models/session.cjs +58 -0
  73. package/lib/models/session.js +12 -17
  74. package/lib/models/{web_chat.js → webchat.cjs} +14 -22
  75. package/lib/models/webchat.js +6 -13
  76. package/lib/vanilla.cjs +13 -0
  77. package/lib/vanilla.js +1 -13
  78. package/package.json +34 -7
  79. package/src/controllers/webchat_controller.js +72 -47
  80. package/src/hellotext.js +3 -4
  81. package/src/models/session.js +4 -3
  82. package/.babelrc +0 -24
  83. package/.github/workflows/ci.yml +0 -24
  84. package/.prettierignore +0 -3
  85. package/.prettierrc.json +0 -18
  86. package/MIT-LICENSE +0 -20
  87. package/__tests__/builders/input_builder_test.js +0 -117
  88. package/__tests__/core/configuration/forms_test.js +0 -30
  89. package/__tests__/core/configuration/webchat_test.js +0 -163
  90. package/__tests__/core/configuration_test.js +0 -28
  91. package/__tests__/core/event_test.js +0 -56
  92. package/__tests__/hellotext_test.js +0 -197
  93. package/__tests__/models/business_test.js +0 -26
  94. package/__tests__/models/cookies_test.js +0 -25
  95. package/__tests__/models/form_collection_test.js +0 -103
  96. package/__tests__/models/form_test.js +0 -131
  97. package/__tests__/models/query_test.js +0 -97
  98. package/docs/forms.md +0 -176
  99. package/docs/tracking.md +0 -203
  100. package/docs/webchat.md +0 -101
  101. package/jest.config.js +0 -4
  102. package/jest.setup.js +0 -16
  103. package/lib/api/web_chat/messages.js +0 -74
  104. package/lib/api/web_chats.js +0 -53
  105. package/styles/index.css +0 -38
  106. package/webpack.config.js +0 -24
@@ -1,13 +1,3 @@
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
- var _dom = require("@floating-ui/dom");
9
- var _emojiMart = require("emoji-mart");
10
- var _usePopover = require("../mixins/usePopover");
11
1
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
12
2
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
13
3
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -24,6 +14,10 @@ function _possibleConstructorReturn(self, call) { if (call && (typeof call === "
24
14
  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
25
15
  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; } }
26
16
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
17
+ import { Controller } from '@hotwired/stimulus';
18
+ import { computePosition, autoUpdate, shift, autoPlacement, offset } from '@floating-ui/dom';
19
+ import { Picker } from 'emoji-mart';
20
+ import { usePopover } from '../mixins/usePopover';
27
21
  var _default = /*#__PURE__*/function (_Controller) {
28
22
  _inherits(_default, _Controller);
29
23
  var _super = _createSuper(_default);
@@ -40,7 +34,7 @@ var _default = /*#__PURE__*/function (_Controller) {
40
34
  }, {
41
35
  key: "connect",
42
36
  value: function connect() {
43
- (0, _usePopover.usePopover)(this);
37
+ usePopover(this);
44
38
  this.setupFloatingUI({
45
39
  trigger: this.buttonTarget,
46
40
  popover: this.popoverTarget
@@ -72,7 +66,7 @@ var _default = /*#__PURE__*/function (_Controller) {
72
66
  }, {
73
67
  key: "pickerObject",
74
68
  get: function get() {
75
- return new _emojiMart.Picker({
69
+ return new Picker({
76
70
  onEmojiSelect: this.onEmojiSelect,
77
71
  theme: 'light',
78
72
  dynamicWidth: true,
@@ -95,16 +89,15 @@ var _default = /*#__PURE__*/function (_Controller) {
95
89
  }, {
96
90
  key: "middlewares",
97
91
  get: function get() {
98
- return [(0, _dom.offset)(5), (0, _dom.shift)({
92
+ return [offset(5), shift({
99
93
  padding: 24
100
- }), (0, _dom.autoPlacement)({
94
+ }), autoPlacement({
101
95
  allowedPlacements: ['top', 'bottom']
102
96
  })];
103
97
  }
104
98
  }]);
105
99
  return _default;
106
- }(_stimulus.Controller);
107
- exports.default = _default;
100
+ }(Controller);
108
101
  _default.targets = ['button', 'popover'];
109
102
  _default.values = {
110
103
  placement: {
@@ -131,4 +124,5 @@ _default.values = {
131
124
  type: Number,
132
125
  default: 9
133
126
  }
134
- };
127
+ };
128
+ export { _default as default };
@@ -0,0 +1,433 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _dom = require("@floating-ui/dom");
8
+ var _stimulus = require("@hotwired/stimulus");
9
+ var _messages = _interopRequireDefault(require("../api/webchat/messages"));
10
+ var _webchat_channel = _interopRequireDefault(require("../channels/webchat_channel"));
11
+ var _hellotext = _interopRequireDefault(require("../hellotext"));
12
+ var _webchat = require("../core/configuration/webchat");
13
+ var _logo_builder = require("../builders/logo_builder");
14
+ var _usePopover = require("./mixins/usePopover");
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
17
+ 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); } }
18
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
19
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
20
+ 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); }
21
+ function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }
22
+ function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
23
+ 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); }
24
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
25
+ 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); }; }
26
+ 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); }
27
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
28
+ 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; } }
29
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
30
+ let _default = /*#__PURE__*/function (_Controller) {
31
+ _inherits(_default, _Controller);
32
+ var _super = _createSuper(_default);
33
+ function _default() {
34
+ _classCallCheck(this, _default);
35
+ return _super.apply(this, arguments);
36
+ }
37
+ _createClass(_default, [{
38
+ key: "initialize",
39
+ value: function initialize() {
40
+ this.messagesAPI = new _messages.default(this.idValue);
41
+ this.webChatChannel = new _webchat_channel.default(this.idValue, _hellotext.default.session, this.conversationIdValue);
42
+ this.files = [];
43
+ this.onMessageReceived = this.onMessageReceived.bind(this);
44
+ this.onConversationAssignment = this.onConversationAssignment.bind(this);
45
+ this.onAgentOnline = this.onAgentOnline.bind(this);
46
+ this.onMessageReaction = this.onMessageReaction.bind(this);
47
+ this.onScroll = this.onScroll.bind(this);
48
+ _get(_getPrototypeOf(_default.prototype), "initialize", this).call(this);
49
+ }
50
+ }, {
51
+ key: "connect",
52
+ value: function connect() {
53
+ (0, _usePopover.usePopover)(this);
54
+ this.popoverTarget.classList.add(..._webchat.Webchat.classes);
55
+ this.triggerTarget.classList.add(..._webchat.Webchat.triggerClasses);
56
+ this.setupFloatingUI({
57
+ trigger: this.triggerTarget,
58
+ popover: this.popoverTarget
59
+ });
60
+ this.webChatChannel.onMessage(this.onMessageReceived);
61
+ this.webChatChannel.onConversationAssignment(this.onConversationAssignment);
62
+ this.webChatChannel.onAgentOnline(this.onAgentOnline);
63
+ this.webChatChannel.onReaction(this.onMessageReaction);
64
+ this.messagesContainerTarget.addEventListener('scroll', this.onScroll);
65
+ if (!_hellotext.default.business.features.white_label) {
66
+ this.toolbarTarget.appendChild(_logo_builder.LogoBuilder.build());
67
+ }
68
+ if (localStorage.getItem(`hellotext--webchat--${this.idValue}`) === 'opened') {
69
+ this.openValue = true;
70
+ }
71
+ _hellotext.default.eventEmitter.dispatch('webchat:mounted');
72
+ _get(_getPrototypeOf(_default.prototype), "connect", this).call(this);
73
+ }
74
+ }, {
75
+ key: "disconnect",
76
+ value: function disconnect() {
77
+ this.messagesContainerTarget.removeEventListener('scroll', this.onScroll);
78
+ this.floatingUICleanup();
79
+ _get(_getPrototypeOf(_default.prototype), "disconnect", this).call(this);
80
+ }
81
+ }, {
82
+ key: "onScroll",
83
+ value: async function onScroll() {
84
+ if (this.messagesContainerTarget.scrollTop > 300 || !this.nextPageValue || this.fetchingNextPage) return;
85
+ this.fetchingNextPage = true;
86
+ const response = await this.messagesAPI.index({
87
+ page: this.nextPageValue,
88
+ session: _hellotext.default.session
89
+ });
90
+ const {
91
+ next: nextPage,
92
+ messages
93
+ } = await response.json();
94
+ this.nextPageValue = nextPage;
95
+ this.oldScrollHeight = this.messagesContainerTarget.scrollHeight;
96
+ messages.forEach(message => {
97
+ const {
98
+ body,
99
+ attachments
100
+ } = message;
101
+ const div = document.createElement('div');
102
+ div.innerHTML = body;
103
+ const element = this.messageTemplateTarget.cloneNode(true);
104
+ element.setAttribute('data-hellotext--webchat-target', 'message');
105
+ element.style.removeProperty('display');
106
+ element.querySelector('[data-body]').innerHTML = div.innerHTML;
107
+ if (message.state === 'received') {
108
+ element.classList.add('received');
109
+ } else {
110
+ element.classList.remove('received');
111
+ }
112
+ if (attachments) {
113
+ attachments.forEach(attachmentUrl => {
114
+ const image = this.attachmentImageTarget.cloneNode(true);
115
+ image.removeAttribute('data-hellotext--webchat-target');
116
+ image.src = attachmentUrl;
117
+ image.style.display = 'block';
118
+ element.querySelector('[data-attachment-container]').appendChild(image);
119
+ });
120
+ }
121
+ element.setAttribute('data-body', body);
122
+ this.messagesContainerTarget.prepend(element);
123
+ });
124
+ this.messagesContainerTarget.scroll({
125
+ top: this.messagesContainerTarget.scrollHeight - this.oldScrollHeight,
126
+ behavior: 'instant'
127
+ });
128
+ this.fetchingNextPage = false;
129
+ }
130
+ }, {
131
+ key: "onClickOutside",
132
+ value: function onClickOutside(event) {
133
+ if (_webchat.Webchat.behaviour === _webchat.behaviors.POPOVER && this.openValue && event.target.nodeType && this.element.contains(event.target) === false) {
134
+ this.openValue = false;
135
+ }
136
+ }
137
+ }, {
138
+ key: "onPopoverOpened",
139
+ value: function onPopoverOpened() {
140
+ this.inputTarget.focus();
141
+ if (!this.scrolled) {
142
+ this.messagesContainerTarget.scroll({
143
+ top: this.messagesContainerTarget.scrollHeight,
144
+ behavior: 'instant'
145
+ });
146
+ this.scrolled = true;
147
+ }
148
+ _hellotext.default.eventEmitter.dispatch('webchat:opened');
149
+ localStorage.setItem(`hellotext--webchat--${this.idValue}`, 'opened');
150
+ if (this.unreadCounterTarget.style.display === 'none') return;
151
+ this.unreadCounterTarget.style.display = 'none';
152
+ this.unreadCounterTarget.innerText = '0';
153
+ this.messagesAPI.markAsSeen();
154
+ }
155
+ }, {
156
+ key: "onPopoverClosed",
157
+ value: function onPopoverClosed() {
158
+ _hellotext.default.eventEmitter.dispatch('webchat:closed');
159
+ setTimeout(() => {
160
+ this.inputTarget.value = '';
161
+ });
162
+ localStorage.setItem(`hellotext--webchat--${this.idValue}`, 'closed');
163
+ }
164
+ }, {
165
+ key: "onMessageReaction",
166
+ value: function onMessageReaction(message) {
167
+ const {
168
+ message: messageId,
169
+ reaction,
170
+ type
171
+ } = message;
172
+ const messageElement = this.messageTargets.find(element => element.dataset.id === messageId);
173
+ const reactionsContainer = messageElement.querySelector('[data-reactions]');
174
+ if (type === 'reaction.destroy') {
175
+ const reactionElement = reactionsContainer.querySelector(`[data-id="${reaction.id}"]`);
176
+ return reactionElement.remove();
177
+ }
178
+ if (reactionsContainer.querySelector(`[data-id="${reaction.id}"]`)) {
179
+ const reactionElement = reactionsContainer.querySelector(`[data-id="${reaction.id}"]`);
180
+ reactionElement.innerText = reaction.emoji;
181
+ } else {
182
+ const reactionElement = document.createElement('span');
183
+ reactionElement.innerText = reaction.emoji;
184
+ reactionElement.setAttribute('data-id', reaction.id);
185
+ reactionsContainer.appendChild(reactionElement);
186
+ }
187
+ }
188
+ }, {
189
+ key: "onMessageReceived",
190
+ value: function onMessageReceived(message) {
191
+ const {
192
+ body,
193
+ attachments
194
+ } = message;
195
+ const div = document.createElement('div');
196
+ div.innerHTML = body;
197
+ const element = this.messageTemplateTarget.cloneNode(true);
198
+ element.style.display = 'flex';
199
+ element.querySelector('[data-body]').innerHTML = div.innerHTML;
200
+ element.setAttribute('data-hellotext--webchat-target', 'message');
201
+ if (attachments) {
202
+ attachments.forEach(attachmentUrl => {
203
+ const image = this.attachmentImageTarget.cloneNode(true);
204
+ image.src = attachmentUrl;
205
+ image.style.display = 'block';
206
+ element.querySelector('[data-attachment-container]').appendChild(image);
207
+ });
208
+ }
209
+ this.messagesContainerTarget.appendChild(element);
210
+ _hellotext.default.eventEmitter.dispatch('webchat:message:received', {
211
+ ...message,
212
+ body: element.querySelector('[data-body]').innerText
213
+ });
214
+ element.scrollIntoView({
215
+ behavior: 'smooth'
216
+ });
217
+ this.setOfflineTimeout();
218
+ if (this.openValue) return;
219
+ this.unreadCounterTarget.style.display = 'flex';
220
+ const unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
221
+ this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
222
+ }
223
+ }, {
224
+ key: "onConversationAssignment",
225
+ value: function onConversationAssignment(conversation) {
226
+ const {
227
+ to: user
228
+ } = conversation;
229
+ this.titleTarget.innerText = user.name;
230
+ if (user.online) {
231
+ this.onlineStatusTarget.style.display = 'flex';
232
+ } else {
233
+ this.onlineStatusTarget.style.display = 'none';
234
+ }
235
+ }
236
+ }, {
237
+ key: "onAgentOnline",
238
+ value: function onAgentOnline() {
239
+ this.onlineStatusTarget.style.display = 'flex';
240
+ this.setOfflineTimeout();
241
+ }
242
+ }, {
243
+ key: "sendMessage",
244
+ value: async function sendMessage() {
245
+ const formData = new FormData();
246
+ const message = {
247
+ body: this.inputTarget.value,
248
+ attachments: this.files
249
+ };
250
+ formData.append('message[body]', this.inputTarget.value);
251
+ this.files.forEach(file => {
252
+ formData.append('message[attachments][]', file);
253
+ });
254
+ formData.append('session', _hellotext.default.session);
255
+ const element = this.messageTemplateTarget.cloneNode(true);
256
+ element.classList.add('received');
257
+ element.style.removeProperty('display');
258
+ element.setAttribute('data-hellotext--webchat-target', 'message');
259
+ element.querySelector('[data-body]').innerText = this.inputTarget.value;
260
+ const attachments = this.attachmentContainerTarget.querySelectorAll('img');
261
+ if (attachments.length > 0) {
262
+ attachments.forEach(attachment => {
263
+ element.querySelector('[data-attachment-container]').appendChild(attachment);
264
+ });
265
+ }
266
+ this.messagesContainerTarget.appendChild(element);
267
+ element.scrollIntoView({
268
+ behavior: 'smooth'
269
+ });
270
+ this.inputTarget.value = '';
271
+ this.files = [];
272
+ this.attachmentContainerTarget.style.display = 'none';
273
+ this.errorMessageContainerTarget.style.display = 'none';
274
+ this.inputTarget.focus();
275
+ const response = await this.messagesAPI.create(formData);
276
+ if (response.failed) {
277
+ return element.classList.add('failed');
278
+ }
279
+ const data = await response.json();
280
+ element.setAttribute('data-id', data.id);
281
+ message.id = data.id;
282
+ _hellotext.default.eventEmitter.dispatch('webchat:message:sent', message);
283
+ if (data.conversation !== this.conversationIdValue) {
284
+ this.conversationIdValue = data.conversation;
285
+ this.webChatChannel.updateSubscriptionWith(this.conversationIdValue);
286
+ }
287
+ this.attachmentContainerTarget.style.display = '';
288
+ }
289
+ }, {
290
+ key: "openAttachment",
291
+ value: function openAttachment() {
292
+ this.attachmentInputTarget.click();
293
+ }
294
+ }, {
295
+ key: "onFileInputChange",
296
+ value: function onFileInputChange() {
297
+ this.errorMessageContainerTarget.style.display = 'none';
298
+ this.files = Array.from(this.attachmentInputTarget.files);
299
+ const fileMaxSizeTooMuch = this.files.find(file => {
300
+ const type = file.type.split('/')[0];
301
+ if (['image', 'video', 'audio'].includes(type)) {
302
+ return this.mediaValue[type].max_size < file.size;
303
+ } else {
304
+ return this.mediaValue.document.max_size < file.size;
305
+ }
306
+ });
307
+ if (fileMaxSizeTooMuch) {
308
+ const type = fileMaxSizeTooMuch.type.split('/')[0];
309
+ const mediaType = ['image', 'audio', 'video'].includes(type) ? type : 'document';
310
+ this.errorMessageContainerTarget.innerText = this.fileSizeErrorMessageValue.replace('%{limit}', this.byteToMegabyte(this.mediaValue[mediaType].max_size));
311
+ return;
312
+ }
313
+ this.errorMessageContainerTarget.innerText = '';
314
+ this.files.forEach(file => this.createAttachmentElement(file));
315
+ this.inputTarget.focus();
316
+ }
317
+ }, {
318
+ key: "createAttachmentElement",
319
+ value: function createAttachmentElement(file) {
320
+ const element = this.attachmentElement();
321
+ this.attachmentContainerTarget.style.display = '';
322
+ element.setAttribute('data-name', file.name);
323
+ if (file.type.startsWith('image/')) {
324
+ const thumbnail = this.attachmentImageTarget.cloneNode(true);
325
+ thumbnail.src = URL.createObjectURL(file);
326
+ thumbnail.style.display = 'block';
327
+ element.appendChild(thumbnail);
328
+ this.attachmentContainerTarget.appendChild(element);
329
+ this.attachmentContainerTarget.style.display = 'flex';
330
+ } else {
331
+ const main = element.querySelector('main');
332
+ main.style.height = '5rem';
333
+ main.style.borderRadius = '0.375rem';
334
+ main.style.backgroundColor = '#e5e7eb';
335
+ main.style.padding = '0.25rem';
336
+ element.querySelector('p[data-attachment-name]').innerText = file.name;
337
+ }
338
+ }
339
+ }, {
340
+ key: "removeAttachment",
341
+ value: function removeAttachment({
342
+ currentTarget
343
+ }) {
344
+ const attachment = currentTarget.closest("[data-hellotext--webchat-target='attachment']");
345
+ this.files = this.files.filter(file => file.name !== attachment.dataset.name);
346
+ attachment.remove();
347
+ this.inputTarget.focus();
348
+ }
349
+ }, {
350
+ key: "attachmentTargetDisconnected",
351
+ value: function attachmentTargetDisconnected() {
352
+ if (this.attachmentTargets.length === 0) {
353
+ this.attachmentContainerTarget.innerHTML = '';
354
+ this.attachmentContainerTarget.style.display = 'none';
355
+ }
356
+ }
357
+ }, {
358
+ key: "attachmentElement",
359
+ value: function attachmentElement() {
360
+ const element = this.attachmentTemplateTarget.cloneNode(true);
361
+ element.removeAttribute('hidden');
362
+ element.style.display = 'flex';
363
+ element.setAttribute('data-hellotext--webchat-target', 'attachment');
364
+ return element;
365
+ }
366
+ }, {
367
+ key: "onEmojiSelect",
368
+ value: function onEmojiSelect({
369
+ detail: emoji
370
+ }) {
371
+ const value = this.inputTarget.value;
372
+ const start = this.inputTarget.selectionStart;
373
+ const end = this.inputTarget.selectionEnd;
374
+ this.inputTarget.value = value.slice(0, start) + emoji + value.slice(end);
375
+ this.inputTarget.selectionStart = this.inputTarget.selectionEnd = start + emoji.length;
376
+ this.inputTarget.focus();
377
+ }
378
+ }, {
379
+ key: "setOfflineTimeout",
380
+ value: function setOfflineTimeout() {
381
+ clearTimeout(this.offlineTimeout);
382
+ this.offlineTimeout = setTimeout(() => {
383
+ this.onlineStatusTarget.style.display = 'none';
384
+ }, this.fiveMinutes);
385
+ }
386
+ }, {
387
+ key: "byteToMegabyte",
388
+ value: function byteToMegabyte(bytes) {
389
+ return Math.ceil(bytes / 1024 / 1024);
390
+ }
391
+ }, {
392
+ key: "fiveMinutes",
393
+ get: function () {
394
+ return 300000;
395
+ }
396
+ }, {
397
+ key: "middlewares",
398
+ get: function () {
399
+ return [(0, _dom.offset)(5), (0, _dom.shift)({
400
+ padding: 24
401
+ }), (0, _dom.flip)()];
402
+ }
403
+ }]);
404
+ return _default;
405
+ }(_stimulus.Controller);
406
+ exports.default = _default;
407
+ _default.values = {
408
+ id: String,
409
+ conversationId: String,
410
+ media: Object,
411
+ fileSizeErrorMessage: String,
412
+ placement: {
413
+ type: String,
414
+ default: 'bottom-end'
415
+ },
416
+ open: {
417
+ type: Boolean,
418
+ default: false
419
+ },
420
+ autoPlacement: {
421
+ type: Boolean,
422
+ default: false
423
+ },
424
+ disabled: {
425
+ type: Boolean,
426
+ default: false
427
+ },
428
+ nextPage: {
429
+ type: Number,
430
+ default: undefined
431
+ }
432
+ };
433
+ _default.targets = ['trigger', 'popover', 'input', 'attachmentInput', 'attachmentButton', 'errorMessageContainer', 'attachmentTemplate', 'attachmentContainer', 'attachment', 'messageTemplate', 'messagesContainer', 'title', 'onlineStatus', 'attachmentImage', 'footer', 'toolbar', 'message', 'unreadCounter'];