@hellotext/hellotext 2.3.9 → 2.4.1
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.
- package/dist/hellotext.js +1 -1
- package/dist/webchat-emoji-en.js +1 -0
- package/dist/webchat-emoji-es.js +1 -0
- package/dist/webchat-emoji.js +1 -0
- package/index.d.ts +30 -4
- package/lib/api/webchats.cjs +20 -0
- package/lib/api/webchats.js +20 -0
- package/lib/controllers/mixins/usePopover.cjs +7 -2
- package/lib/controllers/mixins/usePopover.js +7 -2
- package/lib/controllers/webchat/emoji_picker_controller.cjs +49 -10
- package/lib/controllers/webchat/emoji_picker_controller.js +66 -8
- package/lib/controllers/webchat/useBehaviour.cjs +74 -0
- package/lib/controllers/webchat/useBehaviour.js +67 -0
- package/lib/controllers/webchat/useOpeningSequence.cjs +103 -0
- package/lib/controllers/webchat/useOpeningSequence.js +96 -0
- package/lib/controllers/webchat/useTeaser.cjs +163 -0
- package/lib/controllers/webchat/useTeaser.js +156 -0
- package/lib/controllers/webchat_controller.cjs +168 -22
- package/lib/controllers/webchat_controller.js +176 -24
- package/lib/core/configuration/webchat.cjs +117 -42
- package/lib/core/configuration/webchat.js +121 -43
- package/lib/hellotext.cjs +28 -4
- package/lib/hellotext.js +28 -1
- package/lib/models/business.cjs +2 -0
- package/lib/models/business.js +2 -0
- package/lib/models/webchat.cjs +25 -0
- package/lib/models/webchat.js +25 -0
- package/package.json +1 -1
- package/src/api/webchats.js +17 -0
- package/src/controllers/mixins/usePopover.js +4 -2
- package/src/controllers/webchat/emoji_picker_controller.js +51 -9
- package/src/controllers/webchat/useBehaviour.js +81 -0
- package/src/controllers/webchat/useOpeningSequence.js +127 -0
- package/src/controllers/webchat/useTeaser.js +192 -0
- package/src/controllers/webchat_controller.js +200 -23
- package/src/core/configuration/webchat.js +127 -43
- package/src/hellotext.js +32 -4
- package/src/models/business.js +2 -0
- package/src/models/webchat.js +28 -0
|
@@ -23,9 +23,11 @@ import WebchatMessagesAPI from '../api/webchat/messages';
|
|
|
23
23
|
import WebchatChannel from '../channels/webchat_channel';
|
|
24
24
|
import Hellotext from '../hellotext';
|
|
25
25
|
import { Locale } from '../core';
|
|
26
|
-
import { Webchat as WebchatConfiguration,
|
|
27
|
-
import { LogoBuilder } from '../builders/logo_builder';
|
|
26
|
+
import { Webchat as WebchatConfiguration, modes } from '../core/configuration/webchat';
|
|
28
27
|
import { usePopover } from './mixins/usePopover';
|
|
28
|
+
import { useBehaviour } from './webchat/useBehaviour';
|
|
29
|
+
import { useOpeningSequence } from './webchat/useOpeningSequence';
|
|
30
|
+
import { useTeaser } from './webchat/useTeaser';
|
|
29
31
|
var _default = /*#__PURE__*/function (_Controller) {
|
|
30
32
|
_inherits(_default, _Controller);
|
|
31
33
|
var _super = _createSuper(_default);
|
|
@@ -39,6 +41,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
39
41
|
this.messagesAPI = new WebchatMessagesAPI(this.idValue);
|
|
40
42
|
this.webChatChannel = new WebchatChannel(this.idValue, Hellotext.session, this.conversationIdValue);
|
|
41
43
|
this.files = [];
|
|
44
|
+
this.messageIds = new Set();
|
|
42
45
|
this.onMessageReceived = this.onMessageReceived.bind(this);
|
|
43
46
|
this.onMessageReaction = this.onMessageReaction.bind(this);
|
|
44
47
|
this.onTypingStart = this.onTypingStart.bind(this);
|
|
@@ -50,30 +53,41 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
50
53
|
}, {
|
|
51
54
|
key: "connect",
|
|
52
55
|
value: function connect() {
|
|
56
|
+
useBehaviour(this);
|
|
53
57
|
usePopover(this);
|
|
54
|
-
this
|
|
55
|
-
this
|
|
58
|
+
useOpeningSequence(this);
|
|
59
|
+
useTeaser(this);
|
|
56
60
|
this.setupFloatingUI({
|
|
57
61
|
trigger: this.triggerTarget,
|
|
58
62
|
popover: this.popoverTarget
|
|
59
63
|
});
|
|
64
|
+
if (this.hasTeaserTarget) {
|
|
65
|
+
this.setupFloatingUI({
|
|
66
|
+
trigger: this.triggerTarget,
|
|
67
|
+
popover: this.teaserTarget,
|
|
68
|
+
strategy: 'absolute'
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
this.setupTeaser();
|
|
72
|
+
this.setupOpeningSequence();
|
|
60
73
|
this.webChatChannel.onMessage(this.onMessageReceived);
|
|
61
74
|
this.webChatChannel.onTypingStart(this.onTypingStart);
|
|
62
75
|
this.webChatChannel.onReaction(this.onMessageReaction);
|
|
63
76
|
this.messagesContainerTarget.addEventListener('scroll', this.onScroll);
|
|
64
|
-
if (!Hellotext.business.features.white_label) {
|
|
65
|
-
this.toolbarTarget.appendChild(LogoBuilder.build());
|
|
66
|
-
}
|
|
67
77
|
if (this.shouldOpenOnMount) {
|
|
68
78
|
this.openValue = true;
|
|
69
79
|
}
|
|
70
80
|
Hellotext.eventEmitter.dispatch('webchat:mounted');
|
|
71
81
|
this.broadcastChannel.addEventListener('message', this.onOutboundMessageSent);
|
|
82
|
+
this.scheduleBehaviourOpen();
|
|
72
83
|
_get(_getPrototypeOf(_default.prototype), "connect", this).call(this);
|
|
73
84
|
}
|
|
74
85
|
}, {
|
|
75
86
|
key: "disconnect",
|
|
76
87
|
value: function disconnect() {
|
|
88
|
+
this.cancelBehaviourOpen();
|
|
89
|
+
this.teardownTeaser();
|
|
90
|
+
this.teardownOpeningSequence();
|
|
77
91
|
this.broadcastChannel.removeEventListener('message', this.onOutboundMessageSent);
|
|
78
92
|
this.messagesContainerTarget.removeEventListener('scroll', this.onScroll);
|
|
79
93
|
|
|
@@ -220,11 +234,12 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
220
234
|
}
|
|
221
235
|
if (attachments) {
|
|
222
236
|
attachments.forEach(attachmentUrl => {
|
|
237
|
+
var _this$messageAttachme;
|
|
223
238
|
var image = this.attachmentImageTarget.cloneNode(true);
|
|
224
239
|
image.removeAttribute('data-hellotext--webchat-target');
|
|
225
240
|
image.src = attachmentUrl;
|
|
226
241
|
image.style.display = 'block';
|
|
227
|
-
|
|
242
|
+
(_this$messageAttachme = this.messageAttachmentsContainer(element)) === null || _this$messageAttachme === void 0 ? void 0 : _this$messageAttachme.appendChild(image);
|
|
228
243
|
});
|
|
229
244
|
}
|
|
230
245
|
element.setAttribute('data-body', body);
|
|
@@ -244,7 +259,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
244
259
|
}, {
|
|
245
260
|
key: "onClickOutside",
|
|
246
261
|
value: function onClickOutside(event) {
|
|
247
|
-
if (WebchatConfiguration.
|
|
262
|
+
if (WebchatConfiguration.mode === modes.POPOVER && this.openValue && event.target.nodeType && this.element.contains(event.target) === false) {
|
|
248
263
|
this.openValue = false;
|
|
249
264
|
}
|
|
250
265
|
}
|
|
@@ -259,7 +274,9 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
259
274
|
}, {
|
|
260
275
|
key: "onPopoverOpened",
|
|
261
276
|
value: function onPopoverOpened() {
|
|
277
|
+
var _this$dismissTeaserFo;
|
|
262
278
|
this.popoverTarget.classList.remove(...this.fadeOutClasses);
|
|
279
|
+
(_this$dismissTeaserFo = this.dismissTeaserForSession) === null || _this$dismissTeaserFo === void 0 ? void 0 : _this$dismissTeaserFo.call(this);
|
|
263
280
|
if (!this.onMobile) {
|
|
264
281
|
this.inputTarget.focus();
|
|
265
282
|
}
|
|
@@ -274,6 +291,10 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
274
291
|
}
|
|
275
292
|
Hellotext.eventEmitter.dispatch('webchat:opened');
|
|
276
293
|
localStorage.setItem("hellotext--webchat--".concat(this.idValue), 'opened');
|
|
294
|
+
if (this.messageTeaserValue) {
|
|
295
|
+
this.messageTeaserValue = null;
|
|
296
|
+
}
|
|
297
|
+
this.startOpeningSequence();
|
|
277
298
|
if (this.unreadCounterTarget.style.display === 'none') return;
|
|
278
299
|
this.unreadCounterTarget.style.display = 'none';
|
|
279
300
|
this.unreadCounterTarget.innerText = '0';
|
|
@@ -312,11 +333,15 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
312
333
|
}, {
|
|
313
334
|
key: "onMessageReceived",
|
|
314
335
|
value: function onMessageReceived(message) {
|
|
336
|
+
var _this$hideTeaser;
|
|
315
337
|
var {
|
|
316
338
|
id,
|
|
317
339
|
body,
|
|
318
|
-
attachments
|
|
340
|
+
attachments,
|
|
341
|
+
teaser
|
|
319
342
|
} = message;
|
|
343
|
+
if (!this.claimMessageId(id)) return;
|
|
344
|
+
(_this$hideTeaser = this.hideTeaser) === null || _this$hideTeaser === void 0 ? void 0 : _this$hideTeaser.call(this);
|
|
320
345
|
if (message.carousel) {
|
|
321
346
|
return this.insertCarouselMessage(message);
|
|
322
347
|
}
|
|
@@ -325,13 +350,15 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
325
350
|
var element = this.messageTemplateTarget.cloneNode(true);
|
|
326
351
|
element.style.display = 'flex';
|
|
327
352
|
element.querySelector('[data-body]').innerHTML = div.innerHTML;
|
|
353
|
+
element.setAttribute('data-id', id);
|
|
328
354
|
element.setAttribute('data-hellotext--webchat-target', 'message');
|
|
329
355
|
if (attachments) {
|
|
330
356
|
attachments.forEach(attachmentUrl => {
|
|
357
|
+
var _this$messageAttachme2;
|
|
331
358
|
var image = this.attachmentImageTarget.cloneNode(true);
|
|
332
359
|
image.src = attachmentUrl;
|
|
333
360
|
image.style.display = 'block';
|
|
334
|
-
|
|
361
|
+
(_this$messageAttachme2 = this.messageAttachmentsContainer(element)) === null || _this$messageAttachme2 === void 0 ? void 0 : _this$messageAttachme2.appendChild(image);
|
|
335
362
|
});
|
|
336
363
|
}
|
|
337
364
|
this.clearTypingIndicator();
|
|
@@ -342,13 +369,36 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
342
369
|
element.scrollIntoView({
|
|
343
370
|
behavior: 'smooth'
|
|
344
371
|
});
|
|
372
|
+
this.updateMessageTeaser(teaser);
|
|
345
373
|
if (this.openValue) {
|
|
346
374
|
this.messagesAPI.markAsSeen(id);
|
|
347
375
|
return;
|
|
348
376
|
}
|
|
349
|
-
this.
|
|
350
|
-
|
|
351
|
-
|
|
377
|
+
this.incrementUnreadCounter();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// TCP broadcasts may deliver the same incoming message twice before Stimulus
|
|
381
|
+
// has connected the appended message target. Claiming the id in memory closes
|
|
382
|
+
// that window, while the target check still drops messages rendered earlier.
|
|
383
|
+
}, {
|
|
384
|
+
key: "claimMessageId",
|
|
385
|
+
value: function claimMessageId(id) {
|
|
386
|
+
var messageTargets = this.messageTargets || [];
|
|
387
|
+
if (this.messageIds.has(id)) return false;
|
|
388
|
+
this.messageIds.add(id);
|
|
389
|
+
return !messageTargets.some(element => element.dataset.id === id);
|
|
390
|
+
}
|
|
391
|
+
}, {
|
|
392
|
+
key: "updateMessageTeaser",
|
|
393
|
+
value: function updateMessageTeaser(teaser) {
|
|
394
|
+
this.messageTeaserValue = teaser;
|
|
395
|
+
if (!this.messageTeaserValue || !this.hasTeaserTarget || !this.hasInboundMessageTeaserTarget || !this.hasInboundMessageTeaserBodyTarget) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
this.teaserMessageTargets.forEach(teaserMessage => teaserMessage.classList.add('hidden'));
|
|
399
|
+
this.inboundMessageTeaserBodyTarget.innerHTML = this.messageTeaserValue;
|
|
400
|
+
this.inboundMessageTeaserTarget.classList.remove('hidden');
|
|
401
|
+
this.teaserTarget.classList.toggle('invisible', this.openValue);
|
|
352
402
|
}
|
|
353
403
|
}, {
|
|
354
404
|
key: "insertCarouselMessage",
|
|
@@ -356,6 +406,8 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
356
406
|
var _element$querySelecto;
|
|
357
407
|
var html = message.html;
|
|
358
408
|
var element = new DOMParser().parseFromString(html, 'text/html').body.firstElementChild;
|
|
409
|
+
element.setAttribute('data-id', message.id);
|
|
410
|
+
element.setAttribute('data-hellotext--webchat-target', 'message');
|
|
359
411
|
this.clearTypingIndicator();
|
|
360
412
|
this.messagesContainerTarget.appendChild(element);
|
|
361
413
|
element.scrollIntoView({
|
|
@@ -364,13 +416,12 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
364
416
|
Hellotext.eventEmitter.dispatch('webchat:message:received', _objectSpread(_objectSpread({}, message), {}, {
|
|
365
417
|
body: ((_element$querySelecto = element.querySelector('[data-body]')) === null || _element$querySelecto === void 0 ? void 0 : _element$querySelecto.innerText) || ''
|
|
366
418
|
}));
|
|
419
|
+
this.updateMessageTeaser(message.teaser);
|
|
367
420
|
if (this.openValue) {
|
|
368
421
|
this.messagesAPI.markAsSeen(message.id);
|
|
369
422
|
return;
|
|
370
423
|
}
|
|
371
|
-
this.
|
|
372
|
-
var unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
|
|
373
|
-
this.unreadCounterTarget.innerText = unreadCount > 99 ? '99+' : unreadCount;
|
|
424
|
+
this.incrementUnreadCounter();
|
|
374
425
|
}
|
|
375
426
|
}, {
|
|
376
427
|
key: "resizeInput",
|
|
@@ -389,7 +440,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
389
440
|
key: "sendQuickReplyMessage",
|
|
390
441
|
value: function () {
|
|
391
442
|
var _sendQuickReplyMessage = _asyncToGenerator(function* (_ref) {
|
|
392
|
-
var _cardElement$querySel;
|
|
443
|
+
var _this$dismissTeaserFo2, _cardElement$querySel;
|
|
393
444
|
var {
|
|
394
445
|
detail: {
|
|
395
446
|
id,
|
|
@@ -399,6 +450,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
399
450
|
cardElement
|
|
400
451
|
}
|
|
401
452
|
} = _ref;
|
|
453
|
+
(_this$dismissTeaserFo2 = this.dismissTeaserForSession) === null || _this$dismissTeaserFo2 === void 0 ? void 0 : _this$dismissTeaserFo2.call(this);
|
|
402
454
|
var formData = new FormData();
|
|
403
455
|
formData.append('message[body]', body);
|
|
404
456
|
formData.append('message[replied_to]', id);
|
|
@@ -406,13 +458,15 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
406
458
|
formData.append('message[button]', buttonId);
|
|
407
459
|
formData.append('session', Hellotext.session);
|
|
408
460
|
formData.append('locale', Locale.toString());
|
|
461
|
+
this.appendOpeningSequenceMessageIds(formData);
|
|
409
462
|
var element = this.buildMessageElement();
|
|
410
463
|
var attachment = (_cardElement$querySel = cardElement.querySelector('img')) === null || _cardElement$querySel === void 0 ? void 0 : _cardElement$querySel.cloneNode(true);
|
|
411
464
|
element.querySelector('[data-body]').innerText = body;
|
|
412
465
|
if (attachment) {
|
|
466
|
+
var _this$messageAttachme3;
|
|
413
467
|
attachment.removeAttribute('width');
|
|
414
468
|
attachment.removeAttribute('height');
|
|
415
|
-
|
|
469
|
+
(_this$messageAttachme3 = this.messageAttachmentsContainer(element)) === null || _this$messageAttachme3 === void 0 ? void 0 : _this$messageAttachme3.appendChild(attachment);
|
|
416
470
|
}
|
|
417
471
|
if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
|
|
418
472
|
this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
|
|
@@ -441,6 +495,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
441
495
|
target: element,
|
|
442
496
|
detail: data.id
|
|
443
497
|
});
|
|
498
|
+
this.clearRevealedOpeningSequenceMessageIds();
|
|
444
499
|
var message = {
|
|
445
500
|
id: data.id,
|
|
446
501
|
body: body,
|
|
@@ -457,11 +512,87 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
457
512
|
}
|
|
458
513
|
return sendQuickReplyMessage;
|
|
459
514
|
}()
|
|
515
|
+
}, {
|
|
516
|
+
key: "sendTeaserQuickReply",
|
|
517
|
+
value: function () {
|
|
518
|
+
var _sendTeaserQuickReply = _asyncToGenerator(function* (event) {
|
|
519
|
+
var _this$dismissTeaserFo3;
|
|
520
|
+
event.preventDefault();
|
|
521
|
+
event.stopPropagation();
|
|
522
|
+
var button = event.currentTarget;
|
|
523
|
+
var value = (button.dataset.value || '').trim();
|
|
524
|
+
var label = [button.dataset.text, button.textContent].map(text => (text || '').trim()).find(text => text.length > 0);
|
|
525
|
+
var text = value || label;
|
|
526
|
+
if (!text) return;
|
|
527
|
+
(_this$dismissTeaserFo3 = this.dismissTeaserForSession) === null || _this$dismissTeaserFo3 === void 0 ? void 0 : _this$dismissTeaserFo3.call(this);
|
|
528
|
+
this.show();
|
|
529
|
+
var buttonType = (button.dataset.type || '').trim() || 'quick_reply';
|
|
530
|
+
var formData = new FormData();
|
|
531
|
+
formData.append('message[body]', text);
|
|
532
|
+
formData.append('session', Hellotext.session);
|
|
533
|
+
formData.append('locale', Locale.toString());
|
|
534
|
+
this.appendOpeningSequenceMessageIds(formData);
|
|
535
|
+
var element = this.buildMessageElement();
|
|
536
|
+
element.querySelector('[data-body]').innerText = text;
|
|
537
|
+
if (this.typingIndicatorVisible && this.hasTypingIndicatorTarget) {
|
|
538
|
+
this.messagesContainerTarget.insertBefore(element, this.typingIndicatorTarget);
|
|
539
|
+
} else {
|
|
540
|
+
this.messagesContainerTarget.appendChild(element);
|
|
541
|
+
}
|
|
542
|
+
element.scrollIntoView({
|
|
543
|
+
behavior: 'smooth'
|
|
544
|
+
});
|
|
545
|
+
this.broadcastChannel.postMessage({
|
|
546
|
+
type: 'message:sent',
|
|
547
|
+
element: element.outerHTML
|
|
548
|
+
});
|
|
549
|
+
if (!this.typingIndicatorVisible) {
|
|
550
|
+
clearTimeout(this.optimisticTypingTimeout);
|
|
551
|
+
this.optimisticTypingTimeout = setTimeout(() => {
|
|
552
|
+
this.showOptimisticTypingIndicator();
|
|
553
|
+
}, this.optimisticTypingIndicatorWaitValue);
|
|
554
|
+
}
|
|
555
|
+
var response = yield this.messagesAPI.create(formData);
|
|
556
|
+
if (response.failed) {
|
|
557
|
+
clearTimeout(this.optimisticTypingTimeout);
|
|
558
|
+
this.broadcastChannel.postMessage({
|
|
559
|
+
type: 'message:failed',
|
|
560
|
+
id: element.id
|
|
561
|
+
});
|
|
562
|
+
return element.classList.add('failed');
|
|
563
|
+
}
|
|
564
|
+
var data = yield response.json();
|
|
565
|
+
element.setAttribute('data-id', data.id);
|
|
566
|
+
this.clearRevealedOpeningSequenceMessageIds();
|
|
567
|
+
Hellotext.eventEmitter.dispatch('webchat:message:sent', {
|
|
568
|
+
id: data.id,
|
|
569
|
+
body: text,
|
|
570
|
+
attachments: [],
|
|
571
|
+
type: 'quick_reply',
|
|
572
|
+
teaser: {
|
|
573
|
+
text: label || text,
|
|
574
|
+
value: value || text,
|
|
575
|
+
type: buttonType
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
if (data.conversation && data.conversation !== this.conversationIdValue) {
|
|
579
|
+
this.conversationIdValue = data.conversation;
|
|
580
|
+
this.webChatChannel.updateSubscriptionWith(this.conversationIdValue);
|
|
581
|
+
}
|
|
582
|
+
if (this.typingIndicatorVisible) {
|
|
583
|
+
this.resetTypingIndicatorTimer();
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
function sendTeaserQuickReply(_x2) {
|
|
587
|
+
return _sendTeaserQuickReply.apply(this, arguments);
|
|
588
|
+
}
|
|
589
|
+
return sendTeaserQuickReply;
|
|
590
|
+
}()
|
|
460
591
|
}, {
|
|
461
592
|
key: "sendMessage",
|
|
462
593
|
value: function () {
|
|
463
594
|
var _sendMessage = _asyncToGenerator(function* (e) {
|
|
464
|
-
var
|
|
595
|
+
var _this$dismissTeaserFo4;
|
|
465
596
|
var message = {
|
|
466
597
|
body: this.inputTarget.value,
|
|
467
598
|
attachments: this.files
|
|
@@ -472,6 +603,8 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
472
603
|
}
|
|
473
604
|
return;
|
|
474
605
|
}
|
|
606
|
+
(_this$dismissTeaserFo4 = this.dismissTeaserForSession) === null || _this$dismissTeaserFo4 === void 0 ? void 0 : _this$dismissTeaserFo4.call(this);
|
|
607
|
+
var formData = new FormData();
|
|
475
608
|
if (this.inputTarget.value.trim().length > 0) {
|
|
476
609
|
formData.append('message[body]', this.inputTarget.value);
|
|
477
610
|
} else {
|
|
@@ -482,6 +615,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
482
615
|
});
|
|
483
616
|
formData.append('session', Hellotext.session);
|
|
484
617
|
formData.append('locale', Locale.toString());
|
|
618
|
+
this.appendOpeningSequenceMessageIds(formData);
|
|
485
619
|
var element = this.buildMessageElement();
|
|
486
620
|
if (this.inputTarget.value.trim().length > 0) {
|
|
487
621
|
element.querySelector('[data-body]').innerText = this.inputTarget.value;
|
|
@@ -491,7 +625,8 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
491
625
|
var attachments = this.attachmentContainerTarget.querySelectorAll('img');
|
|
492
626
|
if (attachments.length > 0) {
|
|
493
627
|
attachments.forEach(attachment => {
|
|
494
|
-
|
|
628
|
+
var _this$messageAttachme4;
|
|
629
|
+
(_this$messageAttachme4 = this.messageAttachmentsContainer(element)) === null || _this$messageAttachme4 === void 0 ? void 0 : _this$messageAttachme4.appendChild(attachment.cloneNode(true));
|
|
495
630
|
});
|
|
496
631
|
}
|
|
497
632
|
|
|
@@ -538,6 +673,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
538
673
|
var data = yield response.json();
|
|
539
674
|
element.setAttribute('data-id', data.id);
|
|
540
675
|
message.id = data.id;
|
|
676
|
+
this.clearRevealedOpeningSequenceMessageIds();
|
|
541
677
|
Hellotext.eventEmitter.dispatch('webchat:message:sent', message);
|
|
542
678
|
if (data.conversation !== this.conversationIdValue) {
|
|
543
679
|
this.conversationIdValue = data.conversation;
|
|
@@ -550,7 +686,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
550
686
|
}
|
|
551
687
|
this.attachmentContainerTarget.style.display = '';
|
|
552
688
|
});
|
|
553
|
-
function sendMessage(
|
|
689
|
+
function sendMessage(_x3) {
|
|
554
690
|
return _sendMessage.apply(this, arguments);
|
|
555
691
|
}
|
|
556
692
|
return sendMessage;
|
|
@@ -566,6 +702,18 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
566
702
|
element.setAttribute('data-hellotext--webchat-target', 'message');
|
|
567
703
|
return element;
|
|
568
704
|
}
|
|
705
|
+
}, {
|
|
706
|
+
key: "messageAttachmentsContainer",
|
|
707
|
+
value: function messageAttachmentsContainer(element) {
|
|
708
|
+
return element.querySelector('[data-attachments-container], [data-attachment-container]');
|
|
709
|
+
}
|
|
710
|
+
}, {
|
|
711
|
+
key: "incrementUnreadCounter",
|
|
712
|
+
value: function incrementUnreadCounter() {
|
|
713
|
+
this.unreadCounterTarget.style.display = 'flex';
|
|
714
|
+
var unreadCount = (parseInt(this.unreadCounterTarget.innerText) || 0) + 1;
|
|
715
|
+
this.unreadCounterTarget.innerText = Math.min(unreadCount, 9);
|
|
716
|
+
}
|
|
569
717
|
}, {
|
|
570
718
|
key: "openAttachment",
|
|
571
719
|
value: function openAttachment() {
|
|
@@ -732,8 +880,12 @@ _default.values = {
|
|
|
732
880
|
optimisticTypingIndicatorWait: {
|
|
733
881
|
type: Number,
|
|
734
882
|
default: 1000
|
|
735
|
-
}
|
|
883
|
+
},
|
|
884
|
+
// 1 second,
|
|
885
|
+
teaser: Object,
|
|
886
|
+
messageTeaser: String,
|
|
887
|
+
behaviour: Object
|
|
736
888
|
};
|
|
737
889
|
_default.classes = ['fadeOut'];
|
|
738
|
-
_default.targets = ['trigger', 'popover', 'input', 'attachmentInput', 'attachmentButton', 'errorMessageContainer', 'attachmentTemplate', 'attachmentContainer', 'attachment', 'messageTemplate', 'messagesContainer', 'title', 'attachmentImage', 'footer', 'toolbar', 'message', 'unreadCounter', 'typingIndicator', 'typingIndicatorTemplate'];
|
|
890
|
+
_default.targets = ['trigger', 'popover', 'input', 'attachmentInput', 'attachmentButton', 'errorMessageContainer', 'attachmentTemplate', 'attachmentContainer', 'attachment', 'messageTemplate', 'messagesContainer', 'title', 'attachmentImage', 'footer', 'toolbar', 'message', 'unreadCounter', 'typingIndicator', 'typingIndicatorTemplate', 'teaser', 'teaserMessage', 'inboundMessageTeaser', 'inboundMessageTeaserBody', 'openingSequence', 'openingSequenceMessage'];
|
|
739
891
|
export { _default as default };
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.modes = exports.Webchat = void 0;
|
|
7
7
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
8
8
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
9
9
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
@@ -39,13 +39,13 @@ const strategies = {
|
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
* @typedef {'modal' | 'popover'}
|
|
42
|
+
* @typedef {'modal' | 'popover'} Mode
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
* @enum {
|
|
46
|
+
* @enum {Mode}
|
|
47
47
|
*/
|
|
48
|
-
const
|
|
48
|
+
const modes = {
|
|
49
49
|
MODAL: 'modal',
|
|
50
50
|
POPOVER: 'popover'
|
|
51
51
|
};
|
|
@@ -57,6 +57,20 @@ const behaviors = {
|
|
|
57
57
|
* @property {string} typography - The typography style (e.g., font family).
|
|
58
58
|
*/
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* @typedef {Object} Appearance
|
|
62
|
+
* @property {Object} [header] - Header appearance overrides.
|
|
63
|
+
* @property {string} [header.name] - Business name shown in the webchat header.
|
|
64
|
+
* @property {Object} [launcher] - Launcher appearance overrides.
|
|
65
|
+
* @property {string} [launcher.iconUrl] - Image URL used for the launcher icon.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @typedef {Object} WhatsApp
|
|
70
|
+
* @property {string} [number] - WhatsApp number used by the handoff configuration.
|
|
71
|
+
* @property {boolean} [restrictToChannel] - Whether handoff should be restricted to the configured channel.
|
|
72
|
+
*/
|
|
73
|
+
|
|
60
74
|
/**
|
|
61
75
|
* @class Webchat
|
|
62
76
|
* @classdesc
|
|
@@ -64,13 +78,14 @@ const behaviors = {
|
|
|
64
78
|
* @property {String} id - the id of the webchat.
|
|
65
79
|
* @property {String} container - the container to append the webchat to, defaults to 'body'
|
|
66
80
|
* @property {Placement} placement - the placement of the webchat within the container, defaults to "bottom-right".
|
|
67
|
-
* @property {
|
|
68
|
-
* @property {
|
|
69
|
-
* @property {Behaviour} behaviour - the behaviour of the webchat, defaults to 'popover'.
|
|
81
|
+
* @property {Mode} mode - how the webchat behaves while open, defaults to 'popover'.
|
|
82
|
+
* @property {Object} behaviour - runtime opening behaviour for the webchat.
|
|
70
83
|
* @property {Style} style - the style of the webchat.
|
|
84
|
+
* @property {Appearance} appearance - appearance overrides.
|
|
85
|
+
* @property {WhatsApp} whatsapp - WhatsApp handoff overrides.
|
|
71
86
|
* @property {Strategy} strategy - the strategy used to position the webchat. Defaults to 'absolute'
|
|
72
87
|
*/
|
|
73
|
-
exports.
|
|
88
|
+
exports.modes = modes;
|
|
74
89
|
let Webchat = /*#__PURE__*/function () {
|
|
75
90
|
function Webchat() {
|
|
76
91
|
_classCallCheck(this, Webchat);
|
|
@@ -94,36 +109,6 @@ let Webchat = /*#__PURE__*/function () {
|
|
|
94
109
|
}
|
|
95
110
|
this._placement = value;
|
|
96
111
|
}
|
|
97
|
-
}, {
|
|
98
|
-
key: "classes",
|
|
99
|
-
get: function () {
|
|
100
|
-
if (typeof this._classes === 'string') {
|
|
101
|
-
return this._classes.split(',').map(c => c.trim());
|
|
102
|
-
} else {
|
|
103
|
-
return this._classes;
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
set: function (value) {
|
|
107
|
-
if (!Array.isArray(value) && typeof value !== 'string') {
|
|
108
|
-
throw new Error('classes must be an array or a string');
|
|
109
|
-
}
|
|
110
|
-
this._classes = value;
|
|
111
|
-
}
|
|
112
|
-
}, {
|
|
113
|
-
key: "triggerClasses",
|
|
114
|
-
get: function () {
|
|
115
|
-
if (typeof this._triggerClasses === 'string') {
|
|
116
|
-
return this._triggerClasses.split(',').map(c => c.trim());
|
|
117
|
-
} else {
|
|
118
|
-
return this._triggerClasses;
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
set: function (value) {
|
|
122
|
-
if (!Array.isArray(value) && typeof value !== 'string') {
|
|
123
|
-
throw new Error('triggerClasses must be an array or a string');
|
|
124
|
-
}
|
|
125
|
-
this._triggerClasses = value;
|
|
126
|
-
}
|
|
127
112
|
}, {
|
|
128
113
|
key: "id",
|
|
129
114
|
get: function () {
|
|
@@ -159,17 +144,100 @@ let Webchat = /*#__PURE__*/function () {
|
|
|
159
144
|
});
|
|
160
145
|
this._style = value;
|
|
161
146
|
}
|
|
147
|
+
}, {
|
|
148
|
+
key: "appearance",
|
|
149
|
+
get: function () {
|
|
150
|
+
return this._appearance;
|
|
151
|
+
},
|
|
152
|
+
set: function (value) {
|
|
153
|
+
if (!this.isPlainObject(value)) {
|
|
154
|
+
throw new Error('Appearance must be an object');
|
|
155
|
+
}
|
|
156
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
157
|
+
if (!['header', 'launcher'].includes(key)) {
|
|
158
|
+
throw new Error(`Invalid appearance property: ${key}`);
|
|
159
|
+
}
|
|
160
|
+
if (!this.isPlainObject(nestedValue)) {
|
|
161
|
+
throw new Error(`Appearance ${key} must be an object`);
|
|
162
|
+
}
|
|
163
|
+
Object.entries(nestedValue).forEach(([nestedKey, propertyValue]) => {
|
|
164
|
+
if (key === 'header' && nestedKey !== 'name') {
|
|
165
|
+
throw new Error(`Invalid appearance header property: ${nestedKey}`);
|
|
166
|
+
}
|
|
167
|
+
if (key === 'launcher' && nestedKey !== 'iconUrl') {
|
|
168
|
+
throw new Error(`Invalid appearance launcher property: ${nestedKey}`);
|
|
169
|
+
}
|
|
170
|
+
if (propertyValue == null) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (typeof propertyValue !== 'string') {
|
|
174
|
+
throw new Error(`Invalid appearance ${key}.${nestedKey} value: ${propertyValue}`);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
this._appearance = value;
|
|
179
|
+
}
|
|
180
|
+
}, {
|
|
181
|
+
key: "whatsapp",
|
|
182
|
+
get: function () {
|
|
183
|
+
return this._whatsapp;
|
|
184
|
+
},
|
|
185
|
+
set: function (value) {
|
|
186
|
+
if (!this.isPlainObject(value)) {
|
|
187
|
+
throw new Error('WhatsApp must be an object');
|
|
188
|
+
}
|
|
189
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
190
|
+
if (!['number', 'restrictToChannel'].includes(key)) {
|
|
191
|
+
throw new Error(`Invalid WhatsApp property: ${key}`);
|
|
192
|
+
}
|
|
193
|
+
if (nestedValue == null) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (key === 'number' && typeof nestedValue !== 'string') {
|
|
197
|
+
throw new Error(`Invalid WhatsApp number value: ${nestedValue}`);
|
|
198
|
+
}
|
|
199
|
+
if (key === 'restrictToChannel' && typeof nestedValue !== 'boolean') {
|
|
200
|
+
throw new Error(`Invalid WhatsApp restrictToChannel value: ${nestedValue}`);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
this._whatsapp = value;
|
|
204
|
+
}
|
|
205
|
+
}, {
|
|
206
|
+
key: "mode",
|
|
207
|
+
get: function () {
|
|
208
|
+
return this._mode;
|
|
209
|
+
},
|
|
210
|
+
set: function (value) {
|
|
211
|
+
if (!Object.values(modes).includes(value)) {
|
|
212
|
+
throw new Error(`Invalid mode value: ${value}`);
|
|
213
|
+
}
|
|
214
|
+
this._mode = value;
|
|
215
|
+
}
|
|
162
216
|
}, {
|
|
163
217
|
key: "behaviour",
|
|
164
218
|
get: function () {
|
|
165
219
|
return this._behaviour;
|
|
166
220
|
},
|
|
167
221
|
set: function (value) {
|
|
168
|
-
if (
|
|
222
|
+
if (value == null) {
|
|
223
|
+
this._behaviour = value;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
169
227
|
throw new Error(`Invalid behaviour value: ${value}`);
|
|
170
228
|
}
|
|
171
229
|
this._behaviour = value;
|
|
172
230
|
}
|
|
231
|
+
}, {
|
|
232
|
+
key: "hasBehaviourOverride",
|
|
233
|
+
get: function () {
|
|
234
|
+
return this._hasBehaviourOverride;
|
|
235
|
+
}
|
|
236
|
+
}, {
|
|
237
|
+
key: "behaviourOverride",
|
|
238
|
+
set: function (value) {
|
|
239
|
+
this._hasBehaviourOverride = !!value;
|
|
240
|
+
}
|
|
173
241
|
}, {
|
|
174
242
|
key: "strategy",
|
|
175
243
|
get: function () {
|
|
@@ -199,6 +267,11 @@ let Webchat = /*#__PURE__*/function () {
|
|
|
199
267
|
value: function isHexOrRgba(value) {
|
|
200
268
|
return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(value) || /^rgba?\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3},?\s*(0|1|0?\.\d+)?\s*\)$/.test(value);
|
|
201
269
|
}
|
|
270
|
+
}, {
|
|
271
|
+
key: "isPlainObject",
|
|
272
|
+
value: function isPlainObject(value) {
|
|
273
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
274
|
+
}
|
|
202
275
|
}]);
|
|
203
276
|
return Webchat;
|
|
204
277
|
}();
|
|
@@ -206,8 +279,10 @@ exports.Webchat = Webchat;
|
|
|
206
279
|
Webchat._id = void 0;
|
|
207
280
|
Webchat._container = 'body';
|
|
208
281
|
Webchat._placement = 'bottom-right';
|
|
209
|
-
Webchat._classes = [];
|
|
210
|
-
Webchat._triggerClasses = [];
|
|
211
282
|
Webchat._style = {};
|
|
212
|
-
Webchat.
|
|
283
|
+
Webchat._appearance = {};
|
|
284
|
+
Webchat._whatsapp = {};
|
|
285
|
+
Webchat._mode = modes.POPOVER;
|
|
286
|
+
Webchat._behaviour = null;
|
|
287
|
+
Webchat._hasBehaviourOverride = false;
|
|
213
288
|
Webchat._strategy = null;
|