@hellotext/hellotext 2.1.3 → 2.1.5

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.
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ var _core = require("../core");
7
8
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
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); } }
9
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; }
@@ -17,17 +18,19 @@ let ApplicationChannel = /*#__PURE__*/function () {
17
18
  key: "send",
18
19
  value: function send({
19
20
  command,
20
- identifier
21
+ identifier,
22
+ data
21
23
  }) {
22
- const data = {
24
+ const payload = {
23
25
  command,
24
- identifier: JSON.stringify(identifier)
26
+ identifier: JSON.stringify(identifier),
27
+ data: JSON.stringify(data || {})
25
28
  };
26
29
  if (this.webSocket.readyState === WebSocket.OPEN) {
27
- this.webSocket.send(JSON.stringify(data));
30
+ this.webSocket.send(JSON.stringify(payload));
28
31
  } else {
29
32
  this.webSocket.addEventListener('open', () => {
30
- this.webSocket.send(JSON.stringify(data));
33
+ this.webSocket.send(JSON.stringify(payload));
31
34
  });
32
35
  }
33
36
  }
@@ -50,7 +53,7 @@ let ApplicationChannel = /*#__PURE__*/function () {
50
53
  key: "webSocket",
51
54
  get: function () {
52
55
  if (!ApplicationChannel.webSocket) {
53
- return ApplicationChannel.webSocket = new WebSocket("wss://www.hellotext.com/cable");
56
+ return ApplicationChannel.webSocket = new WebSocket(_core.Configuration.actionCableUrl);
54
57
  }
55
58
  return ApplicationChannel.webSocket;
56
59
  }
@@ -3,6 +3,7 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
3
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
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
+ import { Configuration } from '../core';
6
7
  var ApplicationChannel = /*#__PURE__*/function () {
7
8
  function ApplicationChannel() {
8
9
  _classCallCheck(this, ApplicationChannel);
@@ -12,17 +13,19 @@ var ApplicationChannel = /*#__PURE__*/function () {
12
13
  value: function send(_ref) {
13
14
  var {
14
15
  command,
15
- identifier
16
+ identifier,
17
+ data
16
18
  } = _ref;
17
- var data = {
19
+ var payload = {
18
20
  command,
19
- identifier: JSON.stringify(identifier)
21
+ identifier: JSON.stringify(identifier),
22
+ data: JSON.stringify(data || {})
20
23
  };
21
24
  if (this.webSocket.readyState === WebSocket.OPEN) {
22
- this.webSocket.send(JSON.stringify(data));
25
+ this.webSocket.send(JSON.stringify(payload));
23
26
  } else {
24
27
  this.webSocket.addEventListener('open', () => {
25
- this.webSocket.send(JSON.stringify(data));
28
+ this.webSocket.send(JSON.stringify(payload));
26
29
  });
27
30
  }
28
31
  }
@@ -45,7 +48,7 @@ var ApplicationChannel = /*#__PURE__*/function () {
45
48
  key: "webSocket",
46
49
  get: function get() {
47
50
  if (!ApplicationChannel.webSocket) {
48
- return ApplicationChannel.webSocket = new WebSocket("wss://www.hellotext.com/cable");
51
+ return ApplicationChannel.webSocket = new WebSocket(Configuration.actionCableUrl);
49
52
  }
50
53
  return ApplicationChannel.webSocket;
51
54
  }
@@ -37,7 +37,7 @@ let WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
37
37
  key: "subscribe",
38
38
  value: function subscribe() {
39
39
  const params = {
40
- channel: "WebchatChannel",
40
+ channel: 'WebchatChannel',
41
41
  id: this.id,
42
42
  session: this.session,
43
43
  conversation: this.conversation
@@ -51,7 +51,7 @@ let WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
51
51
  key: "unsubscribe",
52
52
  value: function unsubscribe() {
53
53
  const params = {
54
- channel: "WebchatChannel",
54
+ channel: 'WebchatChannel',
55
55
  id: this.id,
56
56
  session: this.session,
57
57
  conversation: this.conversation
@@ -62,29 +62,45 @@ let WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
62
62
  });
63
63
  }
64
64
  }, {
65
- key: "onMessage",
66
- value: function onMessage(callback) {
67
- _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
68
- if (message.type !== 'message') return;
69
- callback(message);
65
+ key: "startTypingIndicator",
66
+ value: function startTypingIndicator() {
67
+ const params = {
68
+ channel: 'WebchatChannel',
69
+ id: this.id,
70
+ session: this.session,
71
+ conversation: this.conversation
72
+ };
73
+ this.send({
74
+ command: 'message',
75
+ identifier: params,
76
+ data: {
77
+ action: 'started_typing'
78
+ }
70
79
  });
71
80
  }
72
81
  }, {
73
- key: "onConversationAssignment",
74
- value: function onConversationAssignment(callback) {
75
- _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
76
- if (message.type === 'conversation.assigned') {
77
- callback(message);
82
+ key: "stopTypingIndicator",
83
+ value: function stopTypingIndicator() {
84
+ const params = {
85
+ channel: 'WebchatChannel',
86
+ id: this.id,
87
+ session: this.session,
88
+ conversation: this.conversation
89
+ };
90
+ this.send({
91
+ command: 'typing:stop',
92
+ identifier: params,
93
+ data: {
94
+ action: 'stopped_typing'
78
95
  }
79
96
  });
80
97
  }
81
98
  }, {
82
- key: "onAgentOnline",
83
- value: function onAgentOnline(callback) {
99
+ key: "onMessage",
100
+ value: function onMessage(callback) {
84
101
  _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
85
- if (message.type === 'agent_is_online') {
86
- callback(message);
87
- }
102
+ if (message.type !== 'message') return;
103
+ callback(message);
88
104
  });
89
105
  }
90
106
  }, {
@@ -96,6 +112,15 @@ let WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
96
112
  }
97
113
  });
98
114
  }
115
+ }, {
116
+ key: "onTypingStart",
117
+ value: function onTypingStart(callback) {
118
+ _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
119
+ if (message.type === 'started_typing') {
120
+ callback(message);
121
+ }
122
+ });
123
+ }
99
124
  }, {
100
125
  key: "updateSubscriptionWith",
101
126
  value: function updateSubscriptionWith(conversation) {
@@ -30,7 +30,7 @@ var WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
30
30
  key: "subscribe",
31
31
  value: function subscribe() {
32
32
  var params = {
33
- channel: "WebchatChannel",
33
+ channel: 'WebchatChannel',
34
34
  id: this.id,
35
35
  session: this.session,
36
36
  conversation: this.conversation
@@ -44,7 +44,7 @@ var WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
44
44
  key: "unsubscribe",
45
45
  value: function unsubscribe() {
46
46
  var params = {
47
- channel: "WebchatChannel",
47
+ channel: 'WebchatChannel',
48
48
  id: this.id,
49
49
  session: this.session,
50
50
  conversation: this.conversation
@@ -55,29 +55,45 @@ var WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
55
55
  });
56
56
  }
57
57
  }, {
58
- key: "onMessage",
59
- value: function onMessage(callback) {
60
- _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
61
- if (message.type !== 'message') return;
62
- callback(message);
58
+ key: "startTypingIndicator",
59
+ value: function startTypingIndicator() {
60
+ var params = {
61
+ channel: 'WebchatChannel',
62
+ id: this.id,
63
+ session: this.session,
64
+ conversation: this.conversation
65
+ };
66
+ this.send({
67
+ command: 'message',
68
+ identifier: params,
69
+ data: {
70
+ action: 'started_typing'
71
+ }
63
72
  });
64
73
  }
65
74
  }, {
66
- key: "onConversationAssignment",
67
- value: function onConversationAssignment(callback) {
68
- _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
69
- if (message.type === 'conversation.assigned') {
70
- callback(message);
75
+ key: "stopTypingIndicator",
76
+ value: function stopTypingIndicator() {
77
+ var params = {
78
+ channel: 'WebchatChannel',
79
+ id: this.id,
80
+ session: this.session,
81
+ conversation: this.conversation
82
+ };
83
+ this.send({
84
+ command: 'typing:stop',
85
+ identifier: params,
86
+ data: {
87
+ action: 'stopped_typing'
71
88
  }
72
89
  });
73
90
  }
74
91
  }, {
75
- key: "onAgentOnline",
76
- value: function onAgentOnline(callback) {
92
+ key: "onMessage",
93
+ value: function onMessage(callback) {
77
94
  _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
78
- if (message.type === 'agent_is_online') {
79
- callback(message);
80
- }
95
+ if (message.type !== 'message') return;
96
+ callback(message);
81
97
  });
82
98
  }
83
99
  }, {
@@ -89,6 +105,15 @@ var WebchatChannel = /*#__PURE__*/function (_ApplicationChannel) {
89
105
  }
90
106
  });
91
107
  }
108
+ }, {
109
+ key: "onTypingStart",
110
+ value: function onTypingStart(callback) {
111
+ _get(_getPrototypeOf(WebchatChannel.prototype), "onMessage", this).call(this, message => {
112
+ if (message.type === 'started_typing') {
113
+ callback(message);
114
+ }
115
+ });
116
+ }
92
117
  }, {
93
118
  key: "updateSubscriptionWith",
94
119
  value: function updateSubscriptionWith(conversation) {
@@ -42,9 +42,8 @@ let _default = /*#__PURE__*/function (_Controller) {
42
42
  this.webChatChannel = new _webchat_channel.default(this.idValue, _hellotext.default.session, this.conversationIdValue);
43
43
  this.files = [];
44
44
  this.onMessageReceived = this.onMessageReceived.bind(this);
45
- this.onConversationAssignment = this.onConversationAssignment.bind(this);
46
- this.onAgentOnline = this.onAgentOnline.bind(this);
47
45
  this.onMessageReaction = this.onMessageReaction.bind(this);
46
+ this.onTypingStart = this.onTypingStart.bind(this);
48
47
  this.onScroll = this.onScroll.bind(this);
49
48
  this.onOutboundMessageSent = this.onOutboundMessageSent.bind(this);
50
49
  this.broadcastChannel = new BroadcastChannel(`hellotext--webchat--${this.idValue}`);
@@ -61,8 +60,7 @@ let _default = /*#__PURE__*/function (_Controller) {
61
60
  popover: this.popoverTarget
62
61
  });
63
62
  this.webChatChannel.onMessage(this.onMessageReceived);
64
- this.webChatChannel.onConversationAssignment(this.onConversationAssignment);
65
- this.webChatChannel.onAgentOnline(this.onAgentOnline);
63
+ this.webChatChannel.onTypingStart(this.onTypingStart);
66
64
  this.webChatChannel.onReaction(this.onMessageReaction);
67
65
  this.messagesContainerTarget.addEventListener('scroll', this.onScroll);
68
66
  if (!_hellotext.default.business.features.white_label) {
@@ -80,10 +78,85 @@ let _default = /*#__PURE__*/function (_Controller) {
80
78
  value: function disconnect() {
81
79
  this.broadcastChannel.removeEventListener('message', this.onOutboundMessageSent);
82
80
  this.messagesContainerTarget.removeEventListener('scroll', this.onScroll);
81
+
82
+ // Clean up typing indicator timeouts
83
+ this.clearTypingIndicator();
83
84
  this.broadcastChannel.close();
84
85
  this.floatingUICleanup();
85
86
  _get(_getPrototypeOf(_default.prototype), "disconnect", this).call(this);
86
87
  }
88
+ }, {
89
+ key: "onTypingStart",
90
+ value: function onTypingStart() {
91
+ if (this.typingIndicatorVisible) {
92
+ return this.resetTypingIndicatorTimer();
93
+ }
94
+ this.showTypingIndicator();
95
+ }
96
+ }, {
97
+ key: "showOptimisticTypingIndicator",
98
+ value: function showOptimisticTypingIndicator() {
99
+ if (this.typingIndicatorVisible) return;
100
+ this.showTypingIndicator();
101
+ }
102
+ }, {
103
+ key: "showTypingIndicator",
104
+ value: function showTypingIndicator() {
105
+ this.clearTypingIndicator();
106
+ this.typingIndicatorVisible = true;
107
+ const indicator = this.typingIndicatorTemplateTarget.cloneNode(true);
108
+ indicator.setAttribute('data-hellotext--webchat-target', 'typingIndicator');
109
+ indicator.style.display = 'flex';
110
+ this.messagesContainerTarget.appendChild(indicator);
111
+ requestAnimationFrame(() => {
112
+ this.messagesContainerTarget.scroll({
113
+ top: this.messagesContainerTarget.scrollHeight,
114
+ behavior: 'instant'
115
+ });
116
+ });
117
+ const timeout = this.typingIndicatorKeepAliveValue;
118
+ this.incomingTypingIndicatorTimeout = setTimeout(() => {
119
+ this.clearTypingIndicator();
120
+ }, timeout);
121
+ }
122
+ }, {
123
+ key: "resetTypingIndicatorTimer",
124
+ value: function resetTypingIndicatorTimer() {
125
+ if (!this.typingIndicatorVisible) return;
126
+
127
+ // Clear existing timeout
128
+ clearTimeout(this.incomingTypingIndicatorTimeout);
129
+ clearTimeout(this.optimisticTypingTimeout);
130
+
131
+ // Use unified timeout for all typing indicators
132
+ const timeout = this.typingIndicatorKeepAliveValue;
133
+ this.incomingTypingIndicatorTimeout = setTimeout(() => {
134
+ this.clearTypingIndicator();
135
+ }, timeout);
136
+ }
137
+ }, {
138
+ key: "clearTypingIndicator",
139
+ value: function clearTypingIndicator() {
140
+ if (this.hasTypingIndicatorTarget) {
141
+ this.typingIndicatorTarget.remove();
142
+ }
143
+ this.typingIndicatorVisible = false;
144
+ clearTimeout(this.incomingTypingIndicatorTimeout);
145
+ clearTimeout(this.optimisticTypingTimeout);
146
+ }
147
+ }, {
148
+ key: "onMessageInputChange",
149
+ value: function onMessageInputChange() {
150
+ this.resizeInput();
151
+ clearTimeout(this.typingIndicatorTimeout);
152
+ if (!this.hasSentTypingIndicator) {
153
+ this.webChatChannel.startTypingIndicator();
154
+ this.hasSentTypingIndicator = true;
155
+ }
156
+ this.typingIndicatorTimeout = setTimeout(() => {
157
+ this.hasSentTypingIndicator = false;
158
+ }, 3000);
159
+ }
87
160
  }, {
88
161
  key: "onOutboundMessageSent",
89
162
  value: function onOutboundMessageSent(event) {
@@ -93,7 +166,13 @@ let _default = /*#__PURE__*/function (_Controller) {
93
166
  const callbacks = {
94
167
  'message:sent': data => {
95
168
  const element = new DOMParser().parseFromString(data.element, 'text/html').body.firstElementChild;
96
- this.messagesContainerTarget.appendChild(element);
169
+
170
+ // Insert message before typing indicator if one exists
171
+ if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
172
+ this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
173
+ } else {
174
+ this.messagesContainerTarget.appendChild(element);
175
+ }
97
176
  element.scrollIntoView({
98
177
  behavior: 'instant'
99
178
  });
@@ -247,6 +326,7 @@ let _default = /*#__PURE__*/function (_Controller) {
247
326
  element.querySelector('[data-attachment-container]').appendChild(image);
248
327
  });
249
328
  }
329
+ this.clearTypingIndicator();
250
330
  this.messagesContainerTarget.appendChild(element);
251
331
  _hellotext.default.eventEmitter.dispatch('webchat:message:received', {
252
332
  ...message,
@@ -255,7 +335,6 @@ let _default = /*#__PURE__*/function (_Controller) {
255
335
  element.scrollIntoView({
256
336
  behavior: 'smooth'
257
337
  });
258
- this.setOfflineTimeout();
259
338
  if (this.openValue) {
260
339
  this.messagesAPI.markAsSeen(id);
261
340
  return;
@@ -265,33 +344,30 @@ let _default = /*#__PURE__*/function (_Controller) {
265
344
  this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
266
345
  }
267
346
  }, {
268
- key: "onConversationAssignment",
269
- value: function onConversationAssignment(conversation) {
270
- const {
271
- to: user
272
- } = conversation;
273
- this.titleTarget.innerText = user.name;
274
- if (user.online) {
275
- this.onlineStatusTarget.style.display = 'flex';
276
- } else {
277
- this.onlineStatusTarget.style.display = 'none';
278
- }
279
- }
280
- }, {
281
- key: "onAgentOnline",
282
- value: function onAgentOnline() {
283
- this.onlineStatusTarget.style.display = 'flex';
284
- this.setOfflineTimeout();
347
+ key: "resizeInput",
348
+ value: function resizeInput() {
349
+ const maxHeight = 96;
350
+
351
+ // Temporarily reset height to its natural content size
352
+ this.inputTarget.style.height = 'auto';
353
+
354
+ // Set the height to the scrollHeight, which is the minimum height
355
+ // the element needs to fit its content without a scrollbar.
356
+ const scrollHeight = this.inputTarget.scrollHeight;
357
+ this.inputTarget.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
285
358
  }
286
359
  }, {
287
360
  key: "sendMessage",
288
- value: async function sendMessage() {
361
+ value: async function sendMessage(e) {
289
362
  const formData = new FormData();
290
363
  const message = {
291
364
  body: this.inputTarget.value,
292
365
  attachments: this.files
293
366
  };
294
367
  if (this.inputTarget.value.trim().length === 0 && this.files.length === 0) {
368
+ if (e && e.target) {
369
+ e.preventDefault();
370
+ }
295
371
  return;
296
372
  }
297
373
  if (this.inputTarget.value.trim().length > 0) {
@@ -320,7 +396,13 @@ let _default = /*#__PURE__*/function (_Controller) {
320
396
  element.querySelector('[data-attachment-container]').appendChild(attachment);
321
397
  });
322
398
  }
323
- this.messagesContainerTarget.appendChild(element);
399
+
400
+ // Insert message before typing indicator if one exists
401
+ if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
402
+ this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
403
+ } else {
404
+ this.messagesContainerTarget.appendChild(element);
405
+ }
324
406
  element.scrollIntoView({
325
407
  behavior: 'smooth'
326
408
  });
@@ -329,14 +411,26 @@ let _default = /*#__PURE__*/function (_Controller) {
329
411
  element: element.outerHTML
330
412
  });
331
413
  this.inputTarget.value = '';
414
+ this.resizeInput();
332
415
  this.files = [];
333
416
  this.attachmentInputTarget.value = '';
334
417
  this.attachmentContainerTarget.innerHTML = '';
335
418
  this.attachmentContainerTarget.style.display = 'none';
336
419
  this.errorMessageContainerTarget.style.display = 'none';
337
420
  this.inputTarget.focus();
421
+
422
+ // Set up optimistic typing indicator BEFORE making the API call
423
+ // This prevents race conditions with server responses
424
+ if (!this.typingIndicatorVisible) {
425
+ clearTimeout(this.optimisticTypingTimeout);
426
+ this.optimisticTypingTimeout = setTimeout(() => {
427
+ this.showOptimisticTypingIndicator();
428
+ }, this.optimisticTypingIndicatorWaitValue);
429
+ }
338
430
  const response = await this.messagesAPI.create(formData);
339
431
  if (response.failed) {
432
+ // Clear the optimistic typing indicator on failure
433
+ clearTimeout(this.optimisticTypingTimeout);
340
434
  this.broadcastChannel.postMessage({
341
435
  type: 'message:failed',
342
436
  id: element.id
@@ -351,6 +445,11 @@ let _default = /*#__PURE__*/function (_Controller) {
351
445
  this.conversationIdValue = data.conversation;
352
446
  this.webChatChannel.updateSubscriptionWith(this.conversationIdValue);
353
447
  }
448
+
449
+ // If there's already a typing indicator visible, reset its timer
450
+ if (this.typingIndicatorVisible) {
451
+ this.resetTypingIndicatorTimer();
452
+ }
354
453
  this.attachmentContainerTarget.style.display = '';
355
454
  }
356
455
  }, {
@@ -447,29 +546,16 @@ let _default = /*#__PURE__*/function (_Controller) {
447
546
  this.inputTarget.selectionStart = this.inputTarget.selectionEnd = start + emoji.length;
448
547
  this.inputTarget.focus();
449
548
  }
450
- }, {
451
- key: "setOfflineTimeout",
452
- value: function setOfflineTimeout() {
453
- clearTimeout(this.offlineTimeout);
454
- this.offlineTimeout = setTimeout(() => {
455
- this.onlineStatusTarget.style.display = 'none';
456
- }, this.fiveMinutes);
457
- }
458
549
  }, {
459
550
  key: "byteToMegabyte",
460
551
  value: function byteToMegabyte(bytes) {
461
552
  return Math.ceil(bytes / 1024 / 1024);
462
553
  }
463
- }, {
464
- key: "fiveMinutes",
465
- get: function () {
466
- return 300000;
467
- }
468
554
  }, {
469
555
  key: "middlewares",
470
556
  get: function () {
471
- return [(0, _dom.offset)(5), (0, _dom.shift)({
472
- padding: 24
557
+ return [(0, _dom.offset)(this.offsetValue), (0, _dom.shift)({
558
+ padding: this.paddingValue
473
559
  }), (0, _dom.flip)()];
474
560
  }
475
561
  }, {
@@ -514,7 +600,24 @@ _default.values = {
514
600
  fullScreenThreshold: {
515
601
  type: Number,
516
602
  default: 1024
517
- }
603
+ },
604
+ typingIndicatorKeepAlive: {
605
+ type: Number,
606
+ default: 30000
607
+ },
608
+ // 30 seconds
609
+ offset: {
610
+ type: Number,
611
+ default: 24
612
+ },
613
+ padding: {
614
+ type: Number,
615
+ default: 24
616
+ },
617
+ optimisticTypingIndicatorWait: {
618
+ type: Number,
619
+ default: 1000
620
+ } // 1 second
518
621
  };
519
622
  _default.classes = ['fadeOut'];
520
- _default.targets = ['trigger', 'popover', 'input', 'attachmentInput', 'attachmentButton', 'errorMessageContainer', 'attachmentTemplate', 'attachmentContainer', 'attachment', 'messageTemplate', 'messagesContainer', 'title', 'onlineStatus', 'attachmentImage', 'footer', 'toolbar', 'message', 'unreadCounter'];
623
+ _default.targets = ['trigger', 'popover', 'input', 'attachmentInput', 'attachmentButton', 'errorMessageContainer', 'attachmentTemplate', 'attachmentContainer', 'attachment', 'messageTemplate', 'messagesContainer', 'title', 'attachmentImage', 'footer', 'toolbar', 'message', 'unreadCounter', 'typingIndicator', 'typingIndicatorTemplate'];