@hellotext/hellotext 2.4.1 → 2.4.3
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/lib/controllers/message_controller.cjs +167 -31
- package/lib/controllers/message_controller.js +169 -33
- package/lib/controllers/mixins/usePopover.cjs +2 -0
- package/lib/controllers/mixins/usePopover.js +2 -0
- package/lib/controllers/webchat/useTeaser.cjs +3 -1
- package/lib/controllers/webchat/useTeaser.js +3 -1
- package/lib/controllers/webchat_controller.cjs +195 -25
- package/lib/controllers/webchat_controller.js +209 -25
- package/lib/core/configuration.cjs +19 -0
- package/lib/core/configuration.js +19 -0
- package/lib/models/business.cjs +86 -5
- package/lib/models/business.js +82 -5
- package/lib/models/webchat.cjs +18 -3
- package/lib/models/webchat.js +27 -6
- package/package.json +1 -1
- package/src/controllers/message_controller.js +155 -29
- package/src/controllers/mixins/usePopover.js +1 -0
- package/src/controllers/webchat/useTeaser.js +4 -1
- package/src/controllers/webchat_controller.js +219 -27
- package/src/core/configuration.js +25 -0
- package/src/models/business.js +86 -5
- package/src/models/webchat.js +22 -3
package/lib/models/business.js
CHANGED
|
@@ -7,6 +7,8 @@ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typ
|
|
|
7
7
|
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); }
|
|
8
8
|
import locales from '../locales';
|
|
9
9
|
import BusinessesAPI from '../api/businesses';
|
|
10
|
+
var stylesheetAttribute = 'data-hellotext-stylesheet';
|
|
11
|
+
var stylesheetLoadTimeout = 10000;
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* @typedef {Object} BusinessCountry
|
|
@@ -46,6 +48,8 @@ var Business = /*#__PURE__*/function () {
|
|
|
46
48
|
_classCallCheck(this, Business);
|
|
47
49
|
this.id = id;
|
|
48
50
|
this.data = null;
|
|
51
|
+
this.stylesheet = null;
|
|
52
|
+
this.stylesheetLoaded = Promise.resolve(false);
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
/**
|
|
@@ -91,11 +95,12 @@ var Business = /*#__PURE__*/function () {
|
|
|
91
95
|
key: "setData",
|
|
92
96
|
value: function setData(data) {
|
|
93
97
|
this.data = data;
|
|
94
|
-
if (typeof document !== 'undefined') {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
if (typeof document !== 'undefined' && data.style_url) {
|
|
99
|
+
this.stylesheet = this.constructor.ensureStylesheet(data.style_url);
|
|
100
|
+
this.stylesheetLoaded = this.constructor.waitForStylesheet(this.stylesheet);
|
|
101
|
+
} else {
|
|
102
|
+
this.stylesheet = null;
|
|
103
|
+
this.stylesheetLoaded = Promise.resolve(false);
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
}, {
|
|
@@ -139,6 +144,78 @@ var Business = /*#__PURE__*/function () {
|
|
|
139
144
|
get: function get() {
|
|
140
145
|
return this.data.features;
|
|
141
146
|
}
|
|
147
|
+
}], [{
|
|
148
|
+
key: "stylesheetSelector",
|
|
149
|
+
get: function get() {
|
|
150
|
+
return "link[rel=\"stylesheet\"][".concat(stylesheetAttribute, "]");
|
|
151
|
+
}
|
|
152
|
+
}, {
|
|
153
|
+
key: "ensureStylesheet",
|
|
154
|
+
value: function ensureStylesheet(styleUrl) {
|
|
155
|
+
var href = this.normalizedStylesheetUrl(styleUrl);
|
|
156
|
+
var existingLink = this.stylesheetLinks.find(link => link.href === href);
|
|
157
|
+
if (existingLink) {
|
|
158
|
+
existingLink.setAttribute(stylesheetAttribute, 'true');
|
|
159
|
+
return existingLink;
|
|
160
|
+
}
|
|
161
|
+
var linkTag = document.createElement('link');
|
|
162
|
+
linkTag.rel = 'stylesheet';
|
|
163
|
+
linkTag.href = styleUrl;
|
|
164
|
+
linkTag.setAttribute(stylesheetAttribute, 'true');
|
|
165
|
+
this.waitForStylesheet(linkTag);
|
|
166
|
+
document.head.append(linkTag);
|
|
167
|
+
return linkTag;
|
|
168
|
+
}
|
|
169
|
+
}, {
|
|
170
|
+
key: "stylesheetLinks",
|
|
171
|
+
get: function get() {
|
|
172
|
+
if (typeof document === 'undefined') return [];
|
|
173
|
+
return Array.from(document.querySelectorAll(this.stylesheetSelector));
|
|
174
|
+
}
|
|
175
|
+
}, {
|
|
176
|
+
key: "latestStylesheet",
|
|
177
|
+
get: function get() {
|
|
178
|
+
return this.stylesheetLinks[this.stylesheetLinks.length - 1];
|
|
179
|
+
}
|
|
180
|
+
}, {
|
|
181
|
+
key: "normalizedStylesheetUrl",
|
|
182
|
+
value: function normalizedStylesheetUrl(styleUrl) {
|
|
183
|
+
try {
|
|
184
|
+
return new URL(styleUrl, document.baseURI).href;
|
|
185
|
+
} catch (_error) {
|
|
186
|
+
return styleUrl;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}, {
|
|
190
|
+
key: "waitForStylesheet",
|
|
191
|
+
value: function waitForStylesheet(linkTag) {
|
|
192
|
+
if (!linkTag) return Promise.resolve(false);
|
|
193
|
+
if (this.stylesheetIsLoaded(linkTag)) return Promise.resolve(true);
|
|
194
|
+
if (linkTag.dataset.hellotextStylesheetLoaded === 'false') return Promise.resolve(false);
|
|
195
|
+
if (linkTag._hellotextStylesheetLoaded) return linkTag._hellotextStylesheetLoaded;
|
|
196
|
+
linkTag._hellotextStylesheetLoaded = new Promise(resolve => {
|
|
197
|
+
var timeout;
|
|
198
|
+
var finish = loaded => {
|
|
199
|
+
clearTimeout(timeout);
|
|
200
|
+
linkTag.removeEventListener('load', handleLoad);
|
|
201
|
+
linkTag.removeEventListener('error', handleError);
|
|
202
|
+
linkTag.dataset.hellotextStylesheetLoaded = loaded ? 'true' : 'false';
|
|
203
|
+
resolve(loaded);
|
|
204
|
+
};
|
|
205
|
+
var handleLoad = () => finish(this.stylesheetIsLoaded(linkTag));
|
|
206
|
+
var handleError = () => finish(false);
|
|
207
|
+
linkTag.addEventListener('load', handleLoad);
|
|
208
|
+
linkTag.addEventListener('error', handleError);
|
|
209
|
+
timeout = setTimeout(() => finish(this.stylesheetIsLoaded(linkTag)), stylesheetLoadTimeout);
|
|
210
|
+
if (timeout.unref) timeout.unref();
|
|
211
|
+
});
|
|
212
|
+
return linkTag._hellotextStylesheetLoaded;
|
|
213
|
+
}
|
|
214
|
+
}, {
|
|
215
|
+
key: "stylesheetIsLoaded",
|
|
216
|
+
value: function stylesheetIsLoaded(linkTag) {
|
|
217
|
+
return linkTag.dataset.hellotextStylesheetLoaded === 'true' || !!linkTag.sheet;
|
|
218
|
+
}
|
|
142
219
|
}]);
|
|
143
220
|
return Business;
|
|
144
221
|
}();
|
package/lib/models/webchat.cjs
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.Webchat = void 0;
|
|
7
7
|
var _core = require("../core");
|
|
8
8
|
var _api = _interopRequireDefault(require("../api"));
|
|
9
|
+
var _business = require("./business");
|
|
9
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
11
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
11
12
|
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); } }
|
|
@@ -16,13 +17,20 @@ let Webchat = /*#__PURE__*/function () {
|
|
|
16
17
|
function Webchat(data) {
|
|
17
18
|
_classCallCheck(this, Webchat);
|
|
18
19
|
this.data = data;
|
|
19
|
-
this.
|
|
20
|
+
this.mounted = false;
|
|
21
|
+
this.rendered = Promise.resolve(false);
|
|
20
22
|
}
|
|
21
23
|
_createClass(Webchat, [{
|
|
22
24
|
key: "render",
|
|
23
|
-
value: function render() {
|
|
25
|
+
value: async function render() {
|
|
24
26
|
this.applyBehaviourOverride();
|
|
27
|
+
if (!(await this.stylesheetLoaded)) {
|
|
28
|
+
console.warn('Hellotext webchat was not mounted because its stylesheet failed to load.');
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
25
31
|
this.containerToAppendTo.appendChild(this.data.html);
|
|
32
|
+
this.mounted = true;
|
|
33
|
+
return true;
|
|
26
34
|
}
|
|
27
35
|
}, {
|
|
28
36
|
key: "applyBehaviourOverride",
|
|
@@ -53,13 +61,20 @@ let Webchat = /*#__PURE__*/function () {
|
|
|
53
61
|
get: function () {
|
|
54
62
|
return document.querySelector(_core.Configuration.webchat.container);
|
|
55
63
|
}
|
|
64
|
+
}, {
|
|
65
|
+
key: "stylesheetLoaded",
|
|
66
|
+
get: function () {
|
|
67
|
+
return _business.Business.waitForStylesheet(_business.Business.latestStylesheet);
|
|
68
|
+
}
|
|
56
69
|
}], [{
|
|
57
70
|
key: "load",
|
|
58
71
|
value: async function load(id) {
|
|
59
|
-
|
|
72
|
+
const webchat = new Webchat({
|
|
60
73
|
id,
|
|
61
74
|
html: await _api.default.webchats.get(id)
|
|
62
75
|
});
|
|
76
|
+
webchat.rendered = webchat.render();
|
|
77
|
+
return webchat;
|
|
63
78
|
}
|
|
64
79
|
}]);
|
|
65
80
|
return Webchat;
|
package/lib/models/webchat.js
CHANGED
|
@@ -7,18 +7,32 @@ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typ
|
|
|
7
7
|
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); }
|
|
8
8
|
import { Configuration } from '../core';
|
|
9
9
|
import API from '../api';
|
|
10
|
+
import { Business } from './business';
|
|
10
11
|
var Webchat = /*#__PURE__*/function () {
|
|
11
12
|
function Webchat(data) {
|
|
12
13
|
_classCallCheck(this, Webchat);
|
|
13
14
|
this.data = data;
|
|
14
|
-
this.
|
|
15
|
+
this.mounted = false;
|
|
16
|
+
this.rendered = Promise.resolve(false);
|
|
15
17
|
}
|
|
16
18
|
_createClass(Webchat, [{
|
|
17
19
|
key: "render",
|
|
18
|
-
value: function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
value: function () {
|
|
21
|
+
var _render = _asyncToGenerator(function* () {
|
|
22
|
+
this.applyBehaviourOverride();
|
|
23
|
+
if (!(yield this.stylesheetLoaded)) {
|
|
24
|
+
console.warn('Hellotext webchat was not mounted because its stylesheet failed to load.');
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
this.containerToAppendTo.appendChild(this.data.html);
|
|
28
|
+
this.mounted = true;
|
|
29
|
+
return true;
|
|
30
|
+
});
|
|
31
|
+
function render() {
|
|
32
|
+
return _render.apply(this, arguments);
|
|
33
|
+
}
|
|
34
|
+
return render;
|
|
35
|
+
}()
|
|
22
36
|
}, {
|
|
23
37
|
key: "applyBehaviourOverride",
|
|
24
38
|
value: function applyBehaviourOverride() {
|
|
@@ -48,14 +62,21 @@ var Webchat = /*#__PURE__*/function () {
|
|
|
48
62
|
get: function get() {
|
|
49
63
|
return document.querySelector(Configuration.webchat.container);
|
|
50
64
|
}
|
|
65
|
+
}, {
|
|
66
|
+
key: "stylesheetLoaded",
|
|
67
|
+
get: function get() {
|
|
68
|
+
return Business.waitForStylesheet(Business.latestStylesheet);
|
|
69
|
+
}
|
|
51
70
|
}], [{
|
|
52
71
|
key: "load",
|
|
53
72
|
value: function () {
|
|
54
73
|
var _load = _asyncToGenerator(function* (id) {
|
|
55
|
-
|
|
74
|
+
var webchat = new Webchat({
|
|
56
75
|
id,
|
|
57
76
|
html: yield API.webchats.get(id)
|
|
58
77
|
});
|
|
78
|
+
webchat.rendered = webchat.render();
|
|
79
|
+
return webchat;
|
|
59
80
|
});
|
|
60
81
|
function load(_x) {
|
|
61
82
|
return _load.apply(this, arguments);
|
package/package.json
CHANGED
|
@@ -4,7 +4,9 @@ import Hellotext from '../hellotext'
|
|
|
4
4
|
|
|
5
5
|
export default class extends Controller {
|
|
6
6
|
static values = {
|
|
7
|
+
fadeDistance: { type: Number, default: 64 },
|
|
7
8
|
id: String,
|
|
9
|
+
pageStartOffset: { type: Number, default: 0 },
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
static targets = ['carouselContainer', 'leftFade', 'rightFade', 'carouselCard']
|
|
@@ -24,14 +26,16 @@ export default class extends Controller {
|
|
|
24
26
|
|
|
25
27
|
quickReply({ currentTarget }) {
|
|
26
28
|
const card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]')
|
|
29
|
+
const messageElement = currentTarget.closest('[data-controller~="hellotext--message"]')
|
|
30
|
+
const body = currentTarget.dataset.text || currentTarget.textContent.trim()
|
|
27
31
|
|
|
28
32
|
this.dispatch('quickReply', {
|
|
29
33
|
detail: {
|
|
30
34
|
id: this.idValue,
|
|
31
|
-
product: card
|
|
35
|
+
product: card?.dataset.id,
|
|
32
36
|
buttonId: currentTarget.dataset.id,
|
|
33
|
-
body
|
|
34
|
-
cardElement: card,
|
|
37
|
+
body,
|
|
38
|
+
cardElement: card || messageElement || currentTarget,
|
|
35
39
|
},
|
|
36
40
|
})
|
|
37
41
|
}
|
|
@@ -39,25 +43,31 @@ export default class extends Controller {
|
|
|
39
43
|
addToCart({ currentTarget }) {
|
|
40
44
|
const card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]')
|
|
41
45
|
|
|
42
|
-
const
|
|
46
|
+
const { id, reference, source } = card.dataset
|
|
47
|
+
const item = { product: id, quantity: 1 }
|
|
48
|
+
|
|
49
|
+
Hellotext.track('cart.added', { object_parameters: { items: [item] } })
|
|
50
|
+
|
|
51
|
+
Hellotext.eventEmitter.dispatch('cart.added', {
|
|
43
52
|
object_parameters: {
|
|
44
53
|
items: [
|
|
45
54
|
{
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
...item,
|
|
56
|
+
...(reference && { reference }),
|
|
57
|
+
...(source && { source }),
|
|
48
58
|
},
|
|
49
59
|
],
|
|
50
60
|
},
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
Hellotext.track('cart.added', payload)
|
|
54
|
-
Hellotext.eventEmitter.dispatch('cart.added', payload)
|
|
61
|
+
})
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
moveToLeft() {
|
|
58
65
|
if (!this.hasCarouselContainerTarget) return
|
|
59
66
|
|
|
60
|
-
const
|
|
67
|
+
const nextScrollLeft = this.getPreviousPageScrollLeft()
|
|
68
|
+
const scrollAmount = this.carouselContainerTarget.scrollLeft - nextScrollLeft
|
|
69
|
+
|
|
70
|
+
if (scrollAmount < 1) return
|
|
61
71
|
|
|
62
72
|
this.carouselContainerTarget.scrollBy({
|
|
63
73
|
left: -scrollAmount,
|
|
@@ -68,7 +78,10 @@ export default class extends Controller {
|
|
|
68
78
|
moveToRight() {
|
|
69
79
|
if (!this.hasCarouselContainerTarget) return
|
|
70
80
|
|
|
71
|
-
const
|
|
81
|
+
const nextScrollLeft = this.getNextPageScrollLeft()
|
|
82
|
+
const scrollAmount = nextScrollLeft - this.carouselContainerTarget.scrollLeft
|
|
83
|
+
|
|
84
|
+
if (scrollAmount < 1) return
|
|
72
85
|
|
|
73
86
|
this.carouselContainerTarget.scrollBy({
|
|
74
87
|
left: scrollAmount,
|
|
@@ -77,7 +90,10 @@ export default class extends Controller {
|
|
|
77
90
|
}
|
|
78
91
|
|
|
79
92
|
getScrollAmount() {
|
|
80
|
-
|
|
93
|
+
return this.getCardScrollAmount()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getCardScrollAmount() {
|
|
81
97
|
const firstCard = this.carouselContainerTarget.querySelector('.message__carousel_card')
|
|
82
98
|
|
|
83
99
|
if (!firstCard) {
|
|
@@ -85,31 +101,141 @@ export default class extends Controller {
|
|
|
85
101
|
}
|
|
86
102
|
|
|
87
103
|
const cardWidth = firstCard.offsetWidth
|
|
88
|
-
const gap = 16 // gap-x-4 = 1rem = 16px
|
|
89
104
|
|
|
90
|
-
return cardWidth +
|
|
105
|
+
return cardWidth + this.getGap()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
getPageScrollAmount() {
|
|
109
|
+
const scrollAmount = this.carouselContainerTarget.clientWidth - this.getGap()
|
|
110
|
+
|
|
111
|
+
return scrollAmount > 0 ? scrollAmount : this.getCardScrollAmount()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getNextPageScrollLeft() {
|
|
115
|
+
const currentScrollLeft = this.getCurrentScrollLeft()
|
|
116
|
+
const viewportRight = currentScrollLeft + this.carouselContainerTarget.clientWidth
|
|
117
|
+
const cardMetrics = this.getCardMetrics()
|
|
118
|
+
const nextCard = cardMetrics.find(card => card.end > viewportRight + 1)
|
|
119
|
+
const targetScrollLeft = nextCard
|
|
120
|
+
? this.getPageAlignedScrollLeft(nextCard.start)
|
|
121
|
+
: currentScrollLeft + this.getPageScrollAmount()
|
|
122
|
+
const fallbackScrollLeft = currentScrollLeft + this.getPageScrollAmount()
|
|
123
|
+
|
|
124
|
+
return this.clampScrollLeft(targetScrollLeft > currentScrollLeft + 1 ? targetScrollLeft : fallbackScrollLeft)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getPreviousPageScrollLeft() {
|
|
128
|
+
const currentScrollLeft = this.getCurrentScrollLeft()
|
|
129
|
+
|
|
130
|
+
if (currentScrollLeft <= 1) return 0
|
|
131
|
+
|
|
132
|
+
const targetThreshold = Math.max(currentScrollLeft - this.getPageScrollAmount(), 0)
|
|
133
|
+
|
|
134
|
+
if (targetThreshold <= 1) return 0
|
|
135
|
+
|
|
136
|
+
const cardMetrics = this.getCardMetrics()
|
|
137
|
+
const previousPageCard = cardMetrics.find(card => card.start >= targetThreshold - 1 && card.start < currentScrollLeft - 1)
|
|
138
|
+
const previousCard = [...cardMetrics].reverse().find(card => card.start < currentScrollLeft - 1)
|
|
139
|
+
|
|
140
|
+
return this.getPageAlignedScrollLeft(previousPageCard?.start ?? previousCard?.start ?? 0)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
getPageAlignedScrollLeft(cardStart) {
|
|
144
|
+
const pageStartOffset = this.getPageStartOffset()
|
|
145
|
+
|
|
146
|
+
if (cardStart <= pageStartOffset + 1) return 0
|
|
147
|
+
|
|
148
|
+
return this.clampScrollLeft(cardStart - pageStartOffset)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
getCardMetrics() {
|
|
152
|
+
return Array.from(this.carouselContainerTarget.querySelectorAll('.message__carousel_card')).map(card => {
|
|
153
|
+
const start = this.getCardScrollLeft(card)
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
start,
|
|
157
|
+
end: start + card.offsetWidth,
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
getCardScrollLeft(card) {
|
|
163
|
+
const cardRect = card.getBoundingClientRect()
|
|
164
|
+
const containerRect = this.carouselContainerTarget.getBoundingClientRect()
|
|
165
|
+
|
|
166
|
+
if (cardRect.left || cardRect.width || containerRect.left || containerRect.width) {
|
|
167
|
+
return cardRect.left - containerRect.left + this.carouselContainerTarget.scrollLeft
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return card.offsetLeft || 0
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
getCurrentScrollLeft() {
|
|
174
|
+
return this.clampScrollLeft(this.carouselContainerTarget.scrollLeft)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
clampScrollLeft(scrollLeft) {
|
|
178
|
+
const maxScroll = Math.max(this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth, 0)
|
|
179
|
+
|
|
180
|
+
return Math.min(Math.max(scrollLeft, 0), maxScroll)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
getGap() {
|
|
184
|
+
const styles = window.getComputedStyle(this.carouselContainerTarget)
|
|
185
|
+
const gap = Number.parseFloat(styles.columnGap || styles.gap)
|
|
186
|
+
|
|
187
|
+
return Number.isFinite(gap) ? gap : 16
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
getFadeDistance() {
|
|
191
|
+
return Number.isFinite(this.fadeDistanceValue) ? this.fadeDistanceValue : 64
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
getPageStartOffset() {
|
|
195
|
+
return Number.isFinite(this.pageStartOffsetValue) ? this.pageStartOffsetValue : 0
|
|
91
196
|
}
|
|
92
197
|
|
|
93
198
|
updateFades() {
|
|
94
199
|
if (!this.hasCarouselContainerTarget) return
|
|
95
200
|
|
|
96
|
-
const
|
|
97
|
-
const maxScroll =
|
|
98
|
-
this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth
|
|
201
|
+
const maxScroll = Math.max(this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth, 0)
|
|
99
202
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
this.
|
|
103
|
-
|
|
104
|
-
this.leftFadeTarget.classList.add('hidden')
|
|
203
|
+
if (maxScroll <= 1) {
|
|
204
|
+
this.hideFade(this.leftFadeTarget)
|
|
205
|
+
this.hideFade(this.rightFadeTarget)
|
|
206
|
+
return
|
|
105
207
|
}
|
|
106
208
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
209
|
+
const scrollLeft = Math.min(Math.max(this.carouselContainerTarget.scrollLeft, 0), maxScroll)
|
|
210
|
+
|
|
211
|
+
const fadeDistance = this.getFadeDistance()
|
|
212
|
+
|
|
213
|
+
this.setFadeOpacity(this.leftFadeTarget, scrollLeft / fadeDistance)
|
|
214
|
+
this.setFadeOpacity(this.rightFadeTarget, (maxScroll - scrollLeft) / fadeDistance)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
setFadeOpacity(fadeTarget, opacity) {
|
|
218
|
+
const clampedOpacity = Math.min(Math.max(opacity, 0), 1)
|
|
219
|
+
|
|
220
|
+
if (clampedOpacity <= 0.05) {
|
|
221
|
+
this.hideFade(fadeTarget)
|
|
222
|
+
return
|
|
113
223
|
}
|
|
224
|
+
|
|
225
|
+
fadeTarget.classList.remove('hidden')
|
|
226
|
+
fadeTarget.removeAttribute('disabled')
|
|
227
|
+
fadeTarget.removeAttribute('tabindex')
|
|
228
|
+
fadeTarget.setAttribute('aria-hidden', 'false')
|
|
229
|
+
fadeTarget.style.opacity = clampedOpacity.toFixed(3)
|
|
230
|
+
fadeTarget.style.pointerEvents = 'auto'
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
hideFade(fadeTarget) {
|
|
234
|
+
fadeTarget.style.opacity = '0'
|
|
235
|
+
fadeTarget.style.pointerEvents = 'none'
|
|
236
|
+
fadeTarget.setAttribute('aria-hidden', 'true')
|
|
237
|
+
fadeTarget.setAttribute('tabindex', '-1')
|
|
238
|
+
if ('disabled' in fadeTarget) fadeTarget.disabled = true
|
|
239
|
+
fadeTarget.classList.add('hidden')
|
|
114
240
|
}
|
|
115
241
|
}
|
|
@@ -141,7 +141,10 @@ export const useTeaser = controller => {
|
|
|
141
141
|
},
|
|
142
142
|
|
|
143
143
|
teaserSeenKey() {
|
|
144
|
-
|
|
144
|
+
const teaserVersion = this.hasTeaserTarget ? this.teaserTarget.dataset.teaserVersion : ''
|
|
145
|
+
const versionSegment = teaserVersion ? `:${teaserVersion}` : ''
|
|
146
|
+
|
|
147
|
+
return `hellotext:webchat:${this.idValue || this.element.id}:teaser-seen${versionSegment}`
|
|
145
148
|
},
|
|
146
149
|
|
|
147
150
|
teaserSeenForSession() {
|