@hellotext/hellotext 2.5.6 → 2.5.8
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/README.md +5 -26
- package/dist/hellotext.js +1 -1
- package/dist/hellotext.js.LICENSE.txt +1 -1
- package/index.d.ts +15 -6
- package/lib/api/acks.cjs +17 -31
- package/lib/api/acks.js +17 -42
- package/lib/api/businesses.cjs +14 -28
- package/lib/api/businesses.js +13 -36
- package/lib/api/events.cjs +26 -40
- package/lib/api/events.js +28 -52
- package/lib/api/forms.cjs +24 -40
- package/lib/api/forms.js +24 -57
- package/lib/api/identifications.cjs +15 -29
- package/lib/api/identifications.js +15 -40
- package/lib/api/index.cjs +26 -46
- package/lib/api/index.js +28 -49
- package/lib/api/push/identities.cjs +43 -0
- package/lib/api/push/identities.js +35 -0
- package/lib/api/response.cjs +30 -52
- package/lib/api/response.js +31 -60
- package/lib/api/submissions.cjs +18 -34
- package/lib/api/submissions.js +18 -48
- package/lib/api/webchat/messages.cjs +44 -64
- package/lib/api/webchat/messages.js +44 -80
- package/lib/api/webchats.cjs +37 -56
- package/lib/api/webchats.js +37 -65
- package/lib/api/whatsapp_widgets.cjs +49 -72
- package/lib/api/whatsapp_widgets.js +48 -91
- package/lib/builders/input_builder.cjs +36 -48
- package/lib/builders/input_builder.js +36 -48
- package/lib/builders/logo_builder.cjs +10 -29
- package/lib/builders/logo_builder.js +20 -28
- package/lib/channels/application_channel.cjs +136 -178
- package/lib/channels/application_channel.js +137 -180
- package/lib/channels/webchat_channel.cjs +125 -170
- package/lib/channels/webchat_channel.js +125 -170
- package/lib/controllers/form_controller.cjs +82 -121
- package/lib/controllers/form_controller.js +82 -130
- package/lib/controllers/message_controller.cjs +211 -282
- package/lib/controllers/message_controller.js +209 -284
- package/lib/controllers/mixins/usePopover.cjs +3 -6
- package/lib/controllers/mixins/usePopover.js +17 -22
- package/lib/controllers/webchat/emoji_picker_controller.cjs +106 -150
- package/lib/controllers/webchat/emoji_picker_controller.js +105 -170
- package/lib/controllers/webchat/useBehaviour.js +5 -5
- package/lib/controllers/webchat/useOpeningSequence.js +6 -6
- package/lib/controllers/webchat/useTeaser.js +9 -9
- package/lib/controllers/webchat_controller.cjs +916 -1088
- package/lib/controllers/webchat_controller.js +926 -1152
- package/lib/core/configuration/forms.cjs +21 -35
- package/lib/core/configuration/forms.js +20 -35
- package/lib/core/configuration/locale.cjs +36 -71
- package/lib/core/configuration/locale.js +36 -70
- package/lib/core/configuration/push.cjs +16 -0
- package/lib/core/configuration/push.js +10 -0
- package/lib/core/configuration/webchat.cjs +142 -182
- package/lib/core/configuration/webchat.js +145 -189
- package/lib/core/configuration/whatsapp.cjs +76 -102
- package/lib/core/configuration/whatsapp.js +76 -105
- package/lib/core/configuration.cjs +62 -75
- package/lib/core/configuration.js +61 -75
- package/lib/core/event.cjs +36 -59
- package/lib/core/event.js +35 -61
- package/lib/core/sanitize_html.js +4 -4
- package/lib/errors/invalid_event.cjs +5 -26
- package/lib/errors/invalid_event.js +5 -26
- package/lib/errors/not_initialized_error.cjs +5 -26
- package/lib/errors/not_initialized_error.js +5 -26
- package/lib/hellotext.cjs +186 -211
- package/lib/hellotext.js +189 -236
- package/lib/index.js +1 -1
- package/lib/models/business.cjs +115 -152
- package/lib/models/business.js +118 -162
- package/lib/models/cookies.cjs +34 -51
- package/lib/models/cookies.js +34 -51
- package/lib/models/fingerprint.cjs +8 -23
- package/lib/models/fingerprint.js +25 -58
- package/lib/models/form.cjs +106 -142
- package/lib/models/form.js +105 -153
- package/lib/models/form_collection.cjs +63 -101
- package/lib/models/form_collection.js +61 -107
- package/lib/models/index.cjs +7 -0
- package/lib/models/index.js +1 -0
- package/lib/models/page.cjs +106 -129
- package/lib/models/page.js +106 -131
- package/lib/models/push.cjs +345 -0
- package/lib/models/push.js +339 -0
- package/lib/models/query.cjs +21 -41
- package/lib/models/query.js +21 -41
- package/lib/models/session.cjs +33 -65
- package/lib/models/session.js +30 -63
- package/lib/models/user.cjs +29 -51
- package/lib/models/user.js +29 -51
- package/lib/models/utm.cjs +15 -27
- package/lib/models/utm.js +17 -32
- package/lib/models/webchat.cjs +52 -76
- package/lib/models/webchat.js +52 -90
- package/lib/models/whatsapp_widget.cjs +41 -59
- package/lib/models/whatsapp_widget.js +41 -73
- package/lib/vanilla.cjs +4 -7
- package/lib/vanilla.js +2 -1
- package/package.json +2 -10
- package/src/api/index.js +5 -0
- package/src/api/push/identities.js +42 -0
- package/src/core/configuration/push.js +12 -0
- package/src/core/configuration.js +5 -0
- package/src/hellotext.js +15 -1
- package/src/index.bundle.js +0 -1
- package/src/models/business.js +1 -0
- package/src/models/index.js +1 -0
- package/src/models/push.js +397 -0
- package/src/vanilla.js +2 -1
- package/styles/index.css +0 -30
|
@@ -7,290 +7,219 @@ exports.default = void 0;
|
|
|
7
7
|
var _stimulus = require("@hotwired/stimulus");
|
|
8
8
|
var _hellotext = _interopRequireDefault(require("../hellotext"));
|
|
9
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
10
|
+
class _default extends _stimulus.Controller {
|
|
11
|
+
static values = {
|
|
12
|
+
fadeDistance: {
|
|
13
|
+
type: Number,
|
|
14
|
+
default: 64
|
|
15
|
+
},
|
|
16
|
+
id: String,
|
|
17
|
+
kind: String,
|
|
18
|
+
pageStartOffset: {
|
|
19
|
+
type: Number,
|
|
20
|
+
default: 0
|
|
21
|
+
},
|
|
22
|
+
utm: Object
|
|
23
|
+
};
|
|
24
|
+
static targets = ['carouselContainer', 'leftFade', 'rightFade', 'carouselCard'];
|
|
25
|
+
connect() {
|
|
26
|
+
this.updateFades();
|
|
27
|
+
this.observeContainerSize();
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}, {
|
|
55
|
-
key: "quickReply",
|
|
56
|
-
value: function quickReply({
|
|
57
|
-
currentTarget
|
|
58
|
-
}) {
|
|
59
|
-
const card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]');
|
|
60
|
-
const messageElement = currentTarget.closest('[data-controller~="hellotext--message"]');
|
|
61
|
-
const body = currentTarget.dataset.text || currentTarget.textContent.trim();
|
|
62
|
-
this.dispatch('quickReply', {
|
|
63
|
-
detail: {
|
|
64
|
-
id: this.idValue,
|
|
65
|
-
product: card === null || card === void 0 ? void 0 : card.dataset.id,
|
|
66
|
-
buttonId: currentTarget.dataset.id,
|
|
67
|
-
body,
|
|
68
|
-
cardElement: card || messageElement || currentTarget
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}, {
|
|
73
|
-
key: "addToCart",
|
|
74
|
-
value: function addToCart({
|
|
75
|
-
currentTarget
|
|
76
|
-
}) {
|
|
77
|
-
const card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]');
|
|
78
|
-
const {
|
|
79
|
-
id,
|
|
80
|
-
reference,
|
|
81
|
-
source
|
|
82
|
-
} = card.dataset;
|
|
83
|
-
const item = {
|
|
84
|
-
product: id,
|
|
85
|
-
quantity: 1
|
|
86
|
-
};
|
|
87
|
-
if (this.hasUtmValue) _hellotext.default.page.utm.save(this.utmValue);
|
|
88
|
-
_hellotext.default.eventEmitter.dispatch('cart.added', {
|
|
89
|
-
object_parameters: {
|
|
90
|
-
items: [{
|
|
91
|
-
...item,
|
|
92
|
-
...(reference && {
|
|
93
|
-
reference
|
|
94
|
-
}),
|
|
95
|
-
...(source && {
|
|
96
|
-
source
|
|
97
|
-
})
|
|
98
|
-
}]
|
|
99
|
-
},
|
|
100
|
-
source: {
|
|
101
|
-
kind: this.kindValue,
|
|
102
|
-
message_id: this.idValue,
|
|
103
|
-
button_id: currentTarget.dataset.id
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
}, {
|
|
108
|
-
key: "moveToLeft",
|
|
109
|
-
value: function moveToLeft() {
|
|
110
|
-
if (!this.hasCarouselContainerTarget) return;
|
|
111
|
-
const nextScrollLeft = this.getPreviousPageScrollLeft();
|
|
112
|
-
const scrollAmount = this.carouselContainerTarget.scrollLeft - nextScrollLeft;
|
|
113
|
-
if (scrollAmount < 1) return;
|
|
114
|
-
this.carouselContainerTarget.scrollBy({
|
|
115
|
-
left: -scrollAmount,
|
|
116
|
-
behavior: 'smooth'
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
}, {
|
|
120
|
-
key: "moveToRight",
|
|
121
|
-
value: function moveToRight() {
|
|
122
|
-
if (!this.hasCarouselContainerTarget) return;
|
|
123
|
-
const nextScrollLeft = this.getNextPageScrollLeft();
|
|
124
|
-
const scrollAmount = nextScrollLeft - this.carouselContainerTarget.scrollLeft;
|
|
125
|
-
if (scrollAmount < 1) return;
|
|
126
|
-
this.carouselContainerTarget.scrollBy({
|
|
127
|
-
left: scrollAmount,
|
|
128
|
-
behavior: 'smooth'
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}, {
|
|
132
|
-
key: "getScrollAmount",
|
|
133
|
-
value: function getScrollAmount() {
|
|
134
|
-
return this.getCardScrollAmount();
|
|
135
|
-
}
|
|
136
|
-
}, {
|
|
137
|
-
key: "getCardScrollAmount",
|
|
138
|
-
value: function getCardScrollAmount() {
|
|
139
|
-
const firstCard = this.carouselContainerTarget.querySelector('.message__carousel_card');
|
|
140
|
-
if (!firstCard) {
|
|
141
|
-
return 280; // Fallback to default desktop card width
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const cardWidth = firstCard.offsetWidth;
|
|
145
|
-
return cardWidth + this.getGap();
|
|
146
|
-
}
|
|
147
|
-
}, {
|
|
148
|
-
key: "getPageScrollAmount",
|
|
149
|
-
value: function getPageScrollAmount() {
|
|
150
|
-
const scrollAmount = this.carouselContainerTarget.clientWidth - this.getGap();
|
|
151
|
-
return scrollAmount > 0 ? scrollAmount : this.getCardScrollAmount();
|
|
152
|
-
}
|
|
153
|
-
}, {
|
|
154
|
-
key: "getNextPageScrollLeft",
|
|
155
|
-
value: function getNextPageScrollLeft() {
|
|
156
|
-
const currentScrollLeft = this.getCurrentScrollLeft();
|
|
157
|
-
const viewportRight = currentScrollLeft + this.carouselContainerTarget.clientWidth;
|
|
158
|
-
const cardMetrics = this.getCardMetrics();
|
|
159
|
-
const nextCard = cardMetrics.find(card => card.end > viewportRight + 1);
|
|
160
|
-
const targetScrollLeft = nextCard ? this.getPageAlignedScrollLeft(nextCard.start) : currentScrollLeft + this.getPageScrollAmount();
|
|
161
|
-
const fallbackScrollLeft = currentScrollLeft + this.getPageScrollAmount();
|
|
162
|
-
return this.clampScrollLeft(targetScrollLeft > currentScrollLeft + 1 ? targetScrollLeft : fallbackScrollLeft);
|
|
163
|
-
}
|
|
164
|
-
}, {
|
|
165
|
-
key: "getPreviousPageScrollLeft",
|
|
166
|
-
value: function getPreviousPageScrollLeft() {
|
|
167
|
-
const currentScrollLeft = this.getCurrentScrollLeft();
|
|
168
|
-
if (currentScrollLeft <= 1) return 0;
|
|
169
|
-
const targetThreshold = Math.max(currentScrollLeft - this.getPageScrollAmount(), 0);
|
|
170
|
-
if (targetThreshold <= 1) return 0;
|
|
171
|
-
const cardMetrics = this.getCardMetrics();
|
|
172
|
-
const previousPageCard = cardMetrics.find(card => card.start >= targetThreshold - 1 && card.start < currentScrollLeft - 1);
|
|
173
|
-
const previousCard = [...cardMetrics].reverse().find(card => card.start < currentScrollLeft - 1);
|
|
174
|
-
return this.getPageAlignedScrollLeft((previousPageCard === null || previousPageCard === void 0 ? void 0 : previousPageCard.start) ?? (previousCard === null || previousCard === void 0 ? void 0 : previousCard.start) ?? 0);
|
|
175
|
-
}
|
|
176
|
-
}, {
|
|
177
|
-
key: "getPageAlignedScrollLeft",
|
|
178
|
-
value: function getPageAlignedScrollLeft(cardStart) {
|
|
179
|
-
const pageStartOffset = this.getPageStartOffset();
|
|
180
|
-
if (cardStart <= pageStartOffset + 1) return 0;
|
|
181
|
-
return this.clampScrollLeft(cardStart - pageStartOffset);
|
|
182
|
-
}
|
|
183
|
-
}, {
|
|
184
|
-
key: "getCardMetrics",
|
|
185
|
-
value: function getCardMetrics() {
|
|
186
|
-
return Array.from(this.carouselContainerTarget.querySelectorAll('.message__carousel_card')).map(card => {
|
|
187
|
-
const start = this.getCardScrollLeft(card);
|
|
188
|
-
return {
|
|
189
|
-
start,
|
|
190
|
-
end: start + card.offsetWidth
|
|
191
|
-
};
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
}, {
|
|
195
|
-
key: "getCardScrollLeft",
|
|
196
|
-
value: function getCardScrollLeft(card) {
|
|
197
|
-
const cardRect = card.getBoundingClientRect();
|
|
198
|
-
const containerRect = this.carouselContainerTarget.getBoundingClientRect();
|
|
199
|
-
if (cardRect.left || cardRect.width || containerRect.left || containerRect.width) {
|
|
200
|
-
return cardRect.left - containerRect.left + this.carouselContainerTarget.scrollLeft;
|
|
201
|
-
}
|
|
202
|
-
return card.offsetLeft || 0;
|
|
203
|
-
}
|
|
204
|
-
}, {
|
|
205
|
-
key: "getCurrentScrollLeft",
|
|
206
|
-
value: function getCurrentScrollLeft() {
|
|
207
|
-
return this.clampScrollLeft(this.carouselContainerTarget.scrollLeft);
|
|
208
|
-
}
|
|
209
|
-
}, {
|
|
210
|
-
key: "clampScrollLeft",
|
|
211
|
-
value: function clampScrollLeft(scrollLeft) {
|
|
212
|
-
const maxScroll = Math.max(this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth, 0);
|
|
213
|
-
return Math.min(Math.max(scrollLeft, 0), maxScroll);
|
|
214
|
-
}
|
|
215
|
-
}, {
|
|
216
|
-
key: "getGap",
|
|
217
|
-
value: function getGap() {
|
|
218
|
-
const styles = window.getComputedStyle(this.carouselContainerTarget);
|
|
219
|
-
const gap = Number.parseFloat(styles.columnGap || styles.gap);
|
|
220
|
-
return Number.isFinite(gap) ? gap : 16;
|
|
221
|
-
}
|
|
222
|
-
}, {
|
|
223
|
-
key: "getFadeDistance",
|
|
224
|
-
value: function getFadeDistance() {
|
|
225
|
-
return Number.isFinite(this.fadeDistanceValue) ? this.fadeDistanceValue : 64;
|
|
226
|
-
}
|
|
227
|
-
}, {
|
|
228
|
-
key: "getPageStartOffset",
|
|
229
|
-
value: function getPageStartOffset() {
|
|
230
|
-
return Number.isFinite(this.pageStartOffsetValue) ? this.pageStartOffsetValue : 0;
|
|
231
|
-
}
|
|
232
|
-
}, {
|
|
233
|
-
key: "observeContainerSize",
|
|
234
|
-
value: function observeContainerSize() {
|
|
235
|
-
if (!this.hasCarouselContainerTarget || !window.ResizeObserver) return;
|
|
236
|
-
this.resizeObserver = new ResizeObserver(() => this.updateFades());
|
|
237
|
-
this.resizeObserver.observe(this.carouselContainerTarget);
|
|
238
|
-
}
|
|
239
|
-
}, {
|
|
240
|
-
key: "updateFades",
|
|
241
|
-
value: function updateFades() {
|
|
242
|
-
if (!this.hasCarouselContainerTarget) return;
|
|
243
|
-
const maxScroll = Math.max(this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth, 0);
|
|
244
|
-
if (maxScroll <= 1) {
|
|
245
|
-
this.hideFade(this.leftFadeTarget);
|
|
246
|
-
this.hideFade(this.rightFadeTarget);
|
|
247
|
-
return;
|
|
29
|
+
disconnect() {
|
|
30
|
+
this.resizeObserver?.disconnect();
|
|
31
|
+
}
|
|
32
|
+
setId({
|
|
33
|
+
detail: id
|
|
34
|
+
}) {
|
|
35
|
+
this.idValue = id;
|
|
36
|
+
this.element.id = id;
|
|
37
|
+
}
|
|
38
|
+
onScroll() {
|
|
39
|
+
this.updateFades();
|
|
40
|
+
}
|
|
41
|
+
quickReply({
|
|
42
|
+
currentTarget
|
|
43
|
+
}) {
|
|
44
|
+
const card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]');
|
|
45
|
+
const messageElement = currentTarget.closest('[data-controller~="hellotext--message"]');
|
|
46
|
+
const body = currentTarget.dataset.text || currentTarget.textContent.trim();
|
|
47
|
+
this.dispatch('quickReply', {
|
|
48
|
+
detail: {
|
|
49
|
+
id: this.idValue,
|
|
50
|
+
product: card?.dataset.id,
|
|
51
|
+
buttonId: currentTarget.dataset.id,
|
|
52
|
+
body,
|
|
53
|
+
cardElement: card || messageElement || currentTarget
|
|
248
54
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
addToCart({
|
|
58
|
+
currentTarget
|
|
59
|
+
}) {
|
|
60
|
+
const card = currentTarget.closest('[data-hellotext--message-target="carouselCard"]');
|
|
61
|
+
const {
|
|
62
|
+
id,
|
|
63
|
+
reference,
|
|
64
|
+
source
|
|
65
|
+
} = card.dataset;
|
|
66
|
+
const item = {
|
|
67
|
+
product: id,
|
|
68
|
+
quantity: 1
|
|
69
|
+
};
|
|
70
|
+
if (this.hasUtmValue) _hellotext.default.page.utm.save(this.utmValue);
|
|
71
|
+
_hellotext.default.eventEmitter.dispatch('cart.added', {
|
|
72
|
+
object_parameters: {
|
|
73
|
+
items: [{
|
|
74
|
+
...item,
|
|
75
|
+
...(reference && {
|
|
76
|
+
reference
|
|
77
|
+
}),
|
|
78
|
+
...(source && {
|
|
79
|
+
source
|
|
80
|
+
})
|
|
81
|
+
}]
|
|
82
|
+
},
|
|
83
|
+
source: {
|
|
84
|
+
kind: this.kindValue,
|
|
85
|
+
message_id: this.idValue,
|
|
86
|
+
button_id: currentTarget.dataset.id
|
|
261
87
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
moveToLeft() {
|
|
91
|
+
if (!this.hasCarouselContainerTarget) return;
|
|
92
|
+
const nextScrollLeft = this.getPreviousPageScrollLeft();
|
|
93
|
+
const scrollAmount = this.carouselContainerTarget.scrollLeft - nextScrollLeft;
|
|
94
|
+
if (scrollAmount < 1) return;
|
|
95
|
+
this.carouselContainerTarget.scrollBy({
|
|
96
|
+
left: -scrollAmount,
|
|
97
|
+
behavior: 'smooth'
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
moveToRight() {
|
|
101
|
+
if (!this.hasCarouselContainerTarget) return;
|
|
102
|
+
const nextScrollLeft = this.getNextPageScrollLeft();
|
|
103
|
+
const scrollAmount = nextScrollLeft - this.carouselContainerTarget.scrollLeft;
|
|
104
|
+
if (scrollAmount < 1) return;
|
|
105
|
+
this.carouselContainerTarget.scrollBy({
|
|
106
|
+
left: scrollAmount,
|
|
107
|
+
behavior: 'smooth'
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
getScrollAmount() {
|
|
111
|
+
return this.getCardScrollAmount();
|
|
112
|
+
}
|
|
113
|
+
getCardScrollAmount() {
|
|
114
|
+
const firstCard = this.carouselContainerTarget.querySelector('.message__carousel_card');
|
|
115
|
+
if (!firstCard) {
|
|
116
|
+
return 280; // Fallback to default desktop card width
|
|
268
117
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
118
|
+
|
|
119
|
+
const cardWidth = firstCard.offsetWidth;
|
|
120
|
+
return cardWidth + this.getGap();
|
|
121
|
+
}
|
|
122
|
+
getPageScrollAmount() {
|
|
123
|
+
const scrollAmount = this.carouselContainerTarget.clientWidth - this.getGap();
|
|
124
|
+
return scrollAmount > 0 ? scrollAmount : this.getCardScrollAmount();
|
|
125
|
+
}
|
|
126
|
+
getNextPageScrollLeft() {
|
|
127
|
+
const currentScrollLeft = this.getCurrentScrollLeft();
|
|
128
|
+
const viewportRight = currentScrollLeft + this.carouselContainerTarget.clientWidth;
|
|
129
|
+
const cardMetrics = this.getCardMetrics();
|
|
130
|
+
const nextCard = cardMetrics.find(card => card.end > viewportRight + 1);
|
|
131
|
+
const targetScrollLeft = nextCard ? this.getPageAlignedScrollLeft(nextCard.start) : currentScrollLeft + this.getPageScrollAmount();
|
|
132
|
+
const fallbackScrollLeft = currentScrollLeft + this.getPageScrollAmount();
|
|
133
|
+
return this.clampScrollLeft(targetScrollLeft > currentScrollLeft + 1 ? targetScrollLeft : fallbackScrollLeft);
|
|
134
|
+
}
|
|
135
|
+
getPreviousPageScrollLeft() {
|
|
136
|
+
const currentScrollLeft = this.getCurrentScrollLeft();
|
|
137
|
+
if (currentScrollLeft <= 1) return 0;
|
|
138
|
+
const targetThreshold = Math.max(currentScrollLeft - this.getPageScrollAmount(), 0);
|
|
139
|
+
if (targetThreshold <= 1) return 0;
|
|
140
|
+
const cardMetrics = this.getCardMetrics();
|
|
141
|
+
const previousPageCard = cardMetrics.find(card => card.start >= targetThreshold - 1 && card.start < currentScrollLeft - 1);
|
|
142
|
+
const previousCard = [...cardMetrics].reverse().find(card => card.start < currentScrollLeft - 1);
|
|
143
|
+
return this.getPageAlignedScrollLeft(previousPageCard?.start ?? previousCard?.start ?? 0);
|
|
144
|
+
}
|
|
145
|
+
getPageAlignedScrollLeft(cardStart) {
|
|
146
|
+
const pageStartOffset = this.getPageStartOffset();
|
|
147
|
+
if (cardStart <= pageStartOffset + 1) return 0;
|
|
148
|
+
return this.clampScrollLeft(cardStart - pageStartOffset);
|
|
149
|
+
}
|
|
150
|
+
getCardMetrics() {
|
|
151
|
+
return Array.from(this.carouselContainerTarget.querySelectorAll('.message__carousel_card')).map(card => {
|
|
152
|
+
const start = this.getCardScrollLeft(card);
|
|
153
|
+
return {
|
|
154
|
+
start,
|
|
155
|
+
end: start + card.offsetWidth
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
getCardScrollLeft(card) {
|
|
160
|
+
const cardRect = card.getBoundingClientRect();
|
|
161
|
+
const containerRect = this.carouselContainerTarget.getBoundingClientRect();
|
|
162
|
+
if (cardRect.left || cardRect.width || containerRect.left || containerRect.width) {
|
|
163
|
+
return cardRect.left - containerRect.left + this.carouselContainerTarget.scrollLeft;
|
|
278
164
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
|
|
165
|
+
return card.offsetLeft || 0;
|
|
166
|
+
}
|
|
167
|
+
getCurrentScrollLeft() {
|
|
168
|
+
return this.clampScrollLeft(this.carouselContainerTarget.scrollLeft);
|
|
169
|
+
}
|
|
170
|
+
clampScrollLeft(scrollLeft) {
|
|
171
|
+
const maxScroll = Math.max(this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth, 0);
|
|
172
|
+
return Math.min(Math.max(scrollLeft, 0), maxScroll);
|
|
173
|
+
}
|
|
174
|
+
getGap() {
|
|
175
|
+
const styles = window.getComputedStyle(this.carouselContainerTarget);
|
|
176
|
+
const gap = Number.parseFloat(styles.columnGap || styles.gap);
|
|
177
|
+
return Number.isFinite(gap) ? gap : 16;
|
|
178
|
+
}
|
|
179
|
+
getFadeDistance() {
|
|
180
|
+
return Number.isFinite(this.fadeDistanceValue) ? this.fadeDistanceValue : 64;
|
|
181
|
+
}
|
|
182
|
+
getPageStartOffset() {
|
|
183
|
+
return Number.isFinite(this.pageStartOffsetValue) ? this.pageStartOffsetValue : 0;
|
|
184
|
+
}
|
|
185
|
+
observeContainerSize() {
|
|
186
|
+
if (!this.hasCarouselContainerTarget || !window.ResizeObserver) return;
|
|
187
|
+
this.resizeObserver = new ResizeObserver(() => this.updateFades());
|
|
188
|
+
this.resizeObserver.observe(this.carouselContainerTarget);
|
|
189
|
+
}
|
|
190
|
+
updateFades() {
|
|
191
|
+
if (!this.hasCarouselContainerTarget) return;
|
|
192
|
+
const maxScroll = Math.max(this.carouselContainerTarget.scrollWidth - this.carouselContainerTarget.clientWidth, 0);
|
|
193
|
+
if (maxScroll <= 1) {
|
|
194
|
+
this.hideFade(this.leftFadeTarget);
|
|
195
|
+
this.hideFade(this.rightFadeTarget);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const scrollLeft = Math.min(Math.max(this.carouselContainerTarget.scrollLeft, 0), maxScroll);
|
|
199
|
+
const fadeDistance = this.getFadeDistance();
|
|
200
|
+
this.setFadeOpacity(this.leftFadeTarget, scrollLeft / fadeDistance);
|
|
201
|
+
this.setFadeOpacity(this.rightFadeTarget, (maxScroll - scrollLeft) / fadeDistance);
|
|
202
|
+
}
|
|
203
|
+
setFadeOpacity(fadeTarget, opacity) {
|
|
204
|
+
const clampedOpacity = Math.min(Math.max(opacity, 0), 1);
|
|
205
|
+
if (clampedOpacity <= 0.05) {
|
|
206
|
+
this.hideFade(fadeTarget);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
fadeTarget.classList.remove('hidden');
|
|
210
|
+
fadeTarget.removeAttribute('disabled');
|
|
211
|
+
fadeTarget.removeAttribute('tabindex');
|
|
212
|
+
fadeTarget.setAttribute('aria-hidden', 'false');
|
|
213
|
+
fadeTarget.style.opacity = clampedOpacity.toFixed(3);
|
|
214
|
+
fadeTarget.style.pointerEvents = 'auto';
|
|
215
|
+
}
|
|
216
|
+
hideFade(fadeTarget) {
|
|
217
|
+
fadeTarget.style.opacity = '0';
|
|
218
|
+
fadeTarget.style.pointerEvents = 'none';
|
|
219
|
+
fadeTarget.setAttribute('aria-hidden', 'true');
|
|
220
|
+
fadeTarget.setAttribute('tabindex', '-1');
|
|
221
|
+
if ('disabled' in fadeTarget) fadeTarget.disabled = true;
|
|
222
|
+
fadeTarget.classList.add('hidden');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.default = _default;
|