@inappstory/slide-api 0.1.26 → 0.1.28
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/index.cjs +1021 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -6
- package/dist/index.d.ts +94 -6
- package/dist/index.js +1021 -85
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1043,6 +1043,12 @@ class EsModuleSdkApi {
|
|
|
1043
1043
|
constructor(sdkBinding) {
|
|
1044
1044
|
this.sdkBinding = sdkBinding;
|
|
1045
1045
|
}
|
|
1046
|
+
onWidgetRequirePauseUI() {
|
|
1047
|
+
return this.sdkBinding.onWidgetRequirePauseUI();
|
|
1048
|
+
}
|
|
1049
|
+
onWidgetRequireResumeUI() {
|
|
1050
|
+
return this.sdkBinding.onWidgetRequireResumeUI();
|
|
1051
|
+
}
|
|
1046
1052
|
getCardServerData(cardId) {
|
|
1047
1053
|
return this.sdkBinding.getCardServerData(cardId);
|
|
1048
1054
|
}
|
|
@@ -1136,8 +1142,8 @@ class EsModuleSdkApi {
|
|
|
1136
1142
|
isSdkSupportUpdateTimeline() {
|
|
1137
1143
|
return true;
|
|
1138
1144
|
}
|
|
1139
|
-
updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
1140
|
-
this.sdkBinding.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
|
|
1145
|
+
async updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
1146
|
+
await this.sdkBinding.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
|
|
1141
1147
|
}
|
|
1142
1148
|
cardPausedCallback(currentTime) { }
|
|
1143
1149
|
cardResumedCallback(currentTime) { }
|
|
@@ -1183,6 +1189,18 @@ class EsModuleSdkApi {
|
|
|
1183
1189
|
// console.log("onCardLoadingStateChange", { state });
|
|
1184
1190
|
this.sdkBinding.onCardLoadingStateChange(state, reason);
|
|
1185
1191
|
}
|
|
1192
|
+
get isSdkSupportProductCart() {
|
|
1193
|
+
return true;
|
|
1194
|
+
}
|
|
1195
|
+
productCartUpdate(data) {
|
|
1196
|
+
return this.sdkBinding.productCartUpdate(data);
|
|
1197
|
+
}
|
|
1198
|
+
productCartGetState() {
|
|
1199
|
+
return this.sdkBinding.productCartGetState();
|
|
1200
|
+
}
|
|
1201
|
+
productCartClicked() {
|
|
1202
|
+
this.sdkBinding.productCartClicked();
|
|
1203
|
+
}
|
|
1186
1204
|
static get [Symbol.for("___CTOR_ARGS___")]() { return [`SDKInterface`]; }
|
|
1187
1205
|
}
|
|
1188
1206
|
|
|
@@ -3411,7 +3429,7 @@ class SlideTimeline {
|
|
|
3411
3429
|
await this.slideReady.then();
|
|
3412
3430
|
// window._log(`updateTimeline, a: ${action} ct: ${currentTime} d: ${duration} tds: ${this.timelineDisabledState}`, true);
|
|
3413
3431
|
// console.trace(`updateTimeline ${action} slideIndex: ${this.slideIndex} currentTime:${currentTime} duration:${duration} tds: ${this.timelineDisabledState} showLoader: ${showLoader} showError: ${showError}`);
|
|
3414
|
-
this.slideApiDeps.updateTimeline(this.slideIndex, action, currentTime, duration, showLoader, showError);
|
|
3432
|
+
await this.slideApiDeps.updateTimeline(this.slideIndex, action, currentTime, duration, showLoader, showError);
|
|
3415
3433
|
if (action === "pause" /* TIMELINE_ACTION.PAUSE */ && showLoader) {
|
|
3416
3434
|
this.dataWaitingStartedAt = Date.now();
|
|
3417
3435
|
}
|
|
@@ -3437,13 +3455,13 @@ class SlideTimeline {
|
|
|
3437
3455
|
* Start timeline after slide started
|
|
3438
3456
|
* Nothing do if old sdk
|
|
3439
3457
|
*/
|
|
3440
|
-
slideStarted() {
|
|
3458
|
+
async slideStarted() {
|
|
3441
3459
|
// console.trace("slideStarted");
|
|
3442
3460
|
this.onBeforeStateChanged();
|
|
3443
3461
|
if (this.isSDKSupportUpdateTimeline) {
|
|
3444
3462
|
this.resumedAt = new Date().getTime();
|
|
3445
3463
|
this.timeSpent = 0; // for case when instance exists, but we return to slide again
|
|
3446
|
-
this.updateTimeline("start" /* TIMELINE_ACTION.START */);
|
|
3464
|
+
await this.updateTimeline("start" /* TIMELINE_ACTION.START */);
|
|
3447
3465
|
}
|
|
3448
3466
|
}
|
|
3449
3467
|
slideRestarted() {
|
|
@@ -3649,10 +3667,20 @@ class Layer {
|
|
|
3649
3667
|
});
|
|
3650
3668
|
};
|
|
3651
3669
|
const onWidgetRequirePauseUI = (cardId, slideIndex) => {
|
|
3652
|
-
this.
|
|
3670
|
+
if (this.slideApiDeps.isWeb) {
|
|
3671
|
+
this.slideApiDeps.onWidgetRequirePauseUI();
|
|
3672
|
+
}
|
|
3673
|
+
else {
|
|
3674
|
+
this._slidePauseUI();
|
|
3675
|
+
}
|
|
3653
3676
|
};
|
|
3654
3677
|
const onWidgetRequireResumeUI = (cardId, slideIndex) => {
|
|
3655
|
-
this.
|
|
3678
|
+
if (this.slideApiDeps.isWeb) {
|
|
3679
|
+
this.slideApiDeps.onWidgetRequireResumeUI();
|
|
3680
|
+
}
|
|
3681
|
+
else {
|
|
3682
|
+
this._slideResumeUI();
|
|
3683
|
+
}
|
|
3656
3684
|
};
|
|
3657
3685
|
const _elementsNodes = this._nodeRef.querySelectorAll(".narrative-slide-elements .narrative-element:not(.narrative-element-child-element)");
|
|
3658
3686
|
let layerWithWidgetQuest = false;
|
|
@@ -3891,7 +3919,7 @@ class Layer {
|
|
|
3891
3919
|
}
|
|
3892
3920
|
// skip start timeline if we returned to slide with enabled timer and opened WidgetProducts modal
|
|
3893
3921
|
if (!this.isLayerForcePaused) {
|
|
3894
|
-
this.timeline.slideStarted();
|
|
3922
|
+
await this.timeline.slideStarted();
|
|
3895
3923
|
}
|
|
3896
3924
|
return { currentTime };
|
|
3897
3925
|
}
|
|
@@ -5486,6 +5514,12 @@ class SlideApiDepsMultiSlideMode {
|
|
|
5486
5514
|
this.sdkApi = sdkApi;
|
|
5487
5515
|
this.slider = slider;
|
|
5488
5516
|
}
|
|
5517
|
+
onWidgetRequirePauseUI() {
|
|
5518
|
+
return this.sdkApi.onWidgetRequirePauseUI();
|
|
5519
|
+
}
|
|
5520
|
+
onWidgetRequireResumeUI() {
|
|
5521
|
+
return this.sdkApi.onWidgetRequireResumeUI();
|
|
5522
|
+
}
|
|
5489
5523
|
getWidgetsSharedData(cardId, widget) {
|
|
5490
5524
|
return this.sdkApi.getWidgetsSharedData(cardId, widget);
|
|
5491
5525
|
}
|
|
@@ -5609,6 +5643,18 @@ class SlideApiDepsMultiSlideMode {
|
|
|
5609
5643
|
showLayer(index) {
|
|
5610
5644
|
this.sdkApi.showLayer(index);
|
|
5611
5645
|
}
|
|
5646
|
+
get isSdkSupportProductCart() {
|
|
5647
|
+
return this.sdkApi.isSdkSupportProductCart;
|
|
5648
|
+
}
|
|
5649
|
+
productCartUpdate(data) {
|
|
5650
|
+
return this.sdkApi.productCartUpdate(data);
|
|
5651
|
+
}
|
|
5652
|
+
productCartGetState() {
|
|
5653
|
+
return this.sdkApi.productCartGetState();
|
|
5654
|
+
}
|
|
5655
|
+
productCartClicked() {
|
|
5656
|
+
this.sdkApi.productCartClicked();
|
|
5657
|
+
}
|
|
5612
5658
|
/**
|
|
5613
5659
|
* For single slide mode - proxy these methods via SDKApi
|
|
5614
5660
|
* =================================================================================================================
|
|
@@ -5622,8 +5668,8 @@ class SlideApiDepsMultiSlideMode {
|
|
|
5622
5668
|
isSdkSupportUpdateTimeline() {
|
|
5623
5669
|
return true;
|
|
5624
5670
|
}
|
|
5625
|
-
updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
5626
|
-
this.slider.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
|
|
5671
|
+
async updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
5672
|
+
await this.slider.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
|
|
5627
5673
|
}
|
|
5628
5674
|
isSdkSupportTimelineOnBeforeStart() {
|
|
5629
5675
|
return true;
|
|
@@ -5642,6 +5688,12 @@ class SlideApiDepsSingleSlideMode {
|
|
|
5642
5688
|
constructor(sdkApi) {
|
|
5643
5689
|
this.sdkApi = sdkApi;
|
|
5644
5690
|
}
|
|
5691
|
+
onWidgetRequirePauseUI() {
|
|
5692
|
+
return this.sdkApi.onWidgetRequirePauseUI();
|
|
5693
|
+
}
|
|
5694
|
+
onWidgetRequireResumeUI() {
|
|
5695
|
+
return this.sdkApi.onWidgetRequireResumeUI();
|
|
5696
|
+
}
|
|
5645
5697
|
getWidgetsSharedData(cardId, widget) {
|
|
5646
5698
|
return this.sdkApi.getWidgetsSharedData(cardId, widget);
|
|
5647
5699
|
}
|
|
@@ -5763,6 +5815,18 @@ class SlideApiDepsSingleSlideMode {
|
|
|
5763
5815
|
showLayer(index) {
|
|
5764
5816
|
this.sdkApi.showLayer(index);
|
|
5765
5817
|
}
|
|
5818
|
+
get isSdkSupportProductCart() {
|
|
5819
|
+
return this.sdkApi.isSdkSupportProductCart;
|
|
5820
|
+
}
|
|
5821
|
+
productCartUpdate(data) {
|
|
5822
|
+
return this.sdkApi.productCartUpdate(data);
|
|
5823
|
+
}
|
|
5824
|
+
productCartGetState() {
|
|
5825
|
+
return this.sdkApi.productCartGetState();
|
|
5826
|
+
}
|
|
5827
|
+
productCartClicked() {
|
|
5828
|
+
this.sdkApi.productCartClicked();
|
|
5829
|
+
}
|
|
5766
5830
|
/**
|
|
5767
5831
|
* For single slide mode - proxy these methods via SDKApi
|
|
5768
5832
|
*/
|
|
@@ -5775,8 +5839,8 @@ class SlideApiDepsSingleSlideMode {
|
|
|
5775
5839
|
isSdkSupportUpdateTimeline() {
|
|
5776
5840
|
return this.sdkApi.isSdkSupportUpdateTimeline();
|
|
5777
5841
|
}
|
|
5778
|
-
updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
5779
|
-
this.sdkApi.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
|
|
5842
|
+
async updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
5843
|
+
await this.sdkApi.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
|
|
5780
5844
|
}
|
|
5781
5845
|
isSdkSupportTimelineOnBeforeStart() {
|
|
5782
5846
|
return this.sdkApi.isSdkSupportTimelineOnBeforeStart();
|
|
@@ -5940,6 +6004,8 @@ class Slider {
|
|
|
5940
6004
|
});
|
|
5941
6005
|
}
|
|
5942
6006
|
isAnimating = false;
|
|
6007
|
+
// block click while slide loading and starting (prevent several timeline starting)
|
|
6008
|
+
isSlideStarting = false;
|
|
5943
6009
|
activeIndex = -1;
|
|
5944
6010
|
get activeSlide() {
|
|
5945
6011
|
return this.slides[this.activeIndex];
|
|
@@ -5956,7 +6022,7 @@ class Slider {
|
|
|
5956
6022
|
css += `--navbar-edge-offset: ${navbarAppearance.edge_offset};`;
|
|
5957
6023
|
}
|
|
5958
6024
|
if (navbarAppearance.active_timeline_width != null) {
|
|
5959
|
-
css += `--navbar-active-
|
|
6025
|
+
css += `--navbar-active-timeline-width: ${navbarAppearance.active_timeline_width};`;
|
|
5960
6026
|
}
|
|
5961
6027
|
if (navbarAppearance.background_color != null) {
|
|
5962
6028
|
css += `--navbar-background-color: ${navbarAppearance.background_color};`;
|
|
@@ -6049,25 +6115,28 @@ class Slider {
|
|
|
6049
6115
|
bullets.classList.add("cards-slider__navbar--position-bottom");
|
|
6050
6116
|
}
|
|
6051
6117
|
bullets.dir = getLayoutDirection();
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
const
|
|
6062
|
-
if (
|
|
6063
|
-
|
|
6118
|
+
// skip creating view elements for single slide
|
|
6119
|
+
if (count > 1) {
|
|
6120
|
+
for (let i = 0; i < count; ++i) {
|
|
6121
|
+
const bullet = document.createElement("div");
|
|
6122
|
+
bullet.classList.add("cards-slider__timeline", "touchable");
|
|
6123
|
+
bullet.setAttribute("data-index", String(i));
|
|
6124
|
+
bullet.onclick = (e) => {
|
|
6125
|
+
e.stopPropagation();
|
|
6126
|
+
e.preventDefault();
|
|
6127
|
+
const bullet = e.target;
|
|
6128
|
+
if (bullet != null) {
|
|
6129
|
+
const index = bullet.dataset.index;
|
|
6130
|
+
if (index != null) {
|
|
6131
|
+
this.showByIndex(parseInt(index));
|
|
6132
|
+
}
|
|
6064
6133
|
}
|
|
6065
|
-
}
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6134
|
+
};
|
|
6135
|
+
const bulletFill = document.createElement("div");
|
|
6136
|
+
bulletFill.classList.add("cards-slider__timeline-fill");
|
|
6137
|
+
bullet.append(bulletFill);
|
|
6138
|
+
bullets.appendChild(bullet);
|
|
6139
|
+
}
|
|
6071
6140
|
}
|
|
6072
6141
|
// const onUpdateActiveIndex = (activeIndex: number) => {
|
|
6073
6142
|
// if (activeIndex >= 0 && activeIndex < count) {
|
|
@@ -6095,42 +6164,25 @@ class Slider {
|
|
|
6095
6164
|
}
|
|
6096
6165
|
async showByIndex(newIndex) {
|
|
6097
6166
|
const prevIndex = this.activeIndex;
|
|
6098
|
-
if (this.isAnimating)
|
|
6167
|
+
if (this.isAnimating) {
|
|
6099
6168
|
return prevIndex;
|
|
6100
|
-
if (newIndex === prevIndex)
|
|
6101
|
-
return prevIndex;
|
|
6102
|
-
if (prevIndex !== -1) {
|
|
6103
|
-
// skip for slider start
|
|
6104
|
-
this.config.onSlideLeft(this.slides[prevIndex].element, prevIndex);
|
|
6105
|
-
await this.config.onSlideStop();
|
|
6106
|
-
}
|
|
6107
|
-
const { index, loadingError } = await this.initAndRenderSlide(newIndex);
|
|
6108
|
-
if (loadingError) {
|
|
6109
|
-
// todo via updateTimeline ????
|
|
6110
|
-
this.config.onSlideLoadingError(index, loadingError);
|
|
6111
6169
|
}
|
|
6112
|
-
if (
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
await this.slideTo(index);
|
|
6116
|
-
if (!loadingError) {
|
|
6117
|
-
this.config.onSlideStart();
|
|
6170
|
+
if (this.isSlideStarting) {
|
|
6171
|
+
// block click while slide loading and starting (prevent several timeline starting)
|
|
6172
|
+
return prevIndex;
|
|
6118
6173
|
}
|
|
6119
|
-
|
|
6120
|
-
}
|
|
6121
|
-
async showNextSlide() {
|
|
6122
|
-
const prevIndex = this.activeIndex;
|
|
6123
|
-
if (this.isAnimating)
|
|
6174
|
+
if (newIndex === prevIndex) {
|
|
6124
6175
|
return prevIndex;
|
|
6125
|
-
|
|
6176
|
+
}
|
|
6126
6177
|
if (newIndex < 0 || newIndex >= this.slides.length) {
|
|
6127
|
-
return
|
|
6178
|
+
return prevIndex;
|
|
6128
6179
|
}
|
|
6129
6180
|
if (prevIndex !== -1) {
|
|
6130
6181
|
// skip for slider start
|
|
6131
6182
|
this.config.onSlideLeft(this.slides[prevIndex].element, prevIndex);
|
|
6132
6183
|
await this.config.onSlideStop();
|
|
6133
6184
|
}
|
|
6185
|
+
this.isSlideStarting = true;
|
|
6134
6186
|
const { index, loadingError } = await this.initAndRenderSlide(newIndex);
|
|
6135
6187
|
if (loadingError) {
|
|
6136
6188
|
// todo via updateTimeline ????
|
|
@@ -6139,12 +6191,16 @@ class Slider {
|
|
|
6139
6191
|
if (!loadingError) {
|
|
6140
6192
|
this.onShowSlide(index);
|
|
6141
6193
|
}
|
|
6142
|
-
await this.slideTo(index);
|
|
6194
|
+
this.config.onSlideChangeActiveIndex(await this.slideTo(index));
|
|
6143
6195
|
if (!loadingError) {
|
|
6144
|
-
this.config.onSlideStart();
|
|
6196
|
+
await this.config.onSlideStart();
|
|
6145
6197
|
}
|
|
6198
|
+
this.isSlideStarting = false;
|
|
6146
6199
|
return newIndex;
|
|
6147
6200
|
}
|
|
6201
|
+
async showNextSlide() {
|
|
6202
|
+
return this.showByIndex(this.activeIndex + 1);
|
|
6203
|
+
}
|
|
6148
6204
|
async initAndRenderSlide(index) {
|
|
6149
6205
|
this.config.onBeforeLoadSlide(index);
|
|
6150
6206
|
let showSlidePromise;
|
|
@@ -6192,11 +6248,13 @@ class Slider {
|
|
|
6192
6248
|
return k * index * cardWidth;
|
|
6193
6249
|
}
|
|
6194
6250
|
async slideTo(index, speed = 300) {
|
|
6195
|
-
if (index < 0 || index > this.slides.length - 1 || this.isAnimating)
|
|
6196
|
-
return;
|
|
6251
|
+
if (index < 0 || index > this.slides.length - 1 || this.isAnimating) {
|
|
6252
|
+
return this.activeIndex;
|
|
6253
|
+
}
|
|
6197
6254
|
const cardOffset = this.getSlideOffset(index);
|
|
6198
6255
|
await this.translateTo(cardOffset, speed);
|
|
6199
6256
|
this.activeIndex = index;
|
|
6257
|
+
return this.activeIndex;
|
|
6200
6258
|
}
|
|
6201
6259
|
setTranslate(value) {
|
|
6202
6260
|
this.sliderTrack?.style.setProperty("transform", `translateX(${value}px)`);
|
|
@@ -6235,7 +6293,7 @@ class Slider {
|
|
|
6235
6293
|
this.config.root.removeChild(this.slideWrapperElement);
|
|
6236
6294
|
}
|
|
6237
6295
|
}
|
|
6238
|
-
updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
6296
|
+
async updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
6239
6297
|
switch (action) {
|
|
6240
6298
|
case "before_start" /* TIMELINE_ACTION.BEFORE_START */: {
|
|
6241
6299
|
// switch timeline to active slide and wait for start (wait VOD loading)
|
|
@@ -6309,6 +6367,7 @@ class Slider {
|
|
|
6309
6367
|
getLayoutDirection: GetLayoutDirection;
|
|
6310
6368
|
|
|
6311
6369
|
onSlideTimerEnd: OnSlideTimerEnd;
|
|
6370
|
+
onSlideChangeActiveIndex: OnSlideChangeActiveIndex;
|
|
6312
6371
|
onSlideStart: OnSlideStart;
|
|
6313
6372
|
onSlideStop: OnSlideStop;
|
|
6314
6373
|
onSlideDataWaiting: OnSlideDataWaiting;
|
|
@@ -6697,6 +6756,7 @@ class CardApi {
|
|
|
6697
6756
|
onSlideLeft,
|
|
6698
6757
|
getLayoutDirection: () => this.layoutDirection,
|
|
6699
6758
|
onSlideTimerEnd: () => this.activeSlide.slideTimerEnd(),
|
|
6759
|
+
onSlideChangeActiveIndex: index => (this.activeSlide = this.slides[index].slide),
|
|
6700
6760
|
onSlideStart: () => {
|
|
6701
6761
|
// return Promise.resolve({currentTime: 0});
|
|
6702
6762
|
this.cardLoadingStateController.onSetLoadEndState();
|
|
@@ -6795,11 +6855,7 @@ class CardApi {
|
|
|
6795
6855
|
else if (index < 0) {
|
|
6796
6856
|
index = this.slides.length - 1;
|
|
6797
6857
|
}
|
|
6798
|
-
this.slider.showByIndex(index)
|
|
6799
|
-
if (currentIndex === index)
|
|
6800
|
-
return;
|
|
6801
|
-
this.activeSlide = this.slides[index].slide;
|
|
6802
|
-
});
|
|
6858
|
+
this.slider.showByIndex(index);
|
|
6803
6859
|
}
|
|
6804
6860
|
return result;
|
|
6805
6861
|
}
|
|
@@ -18951,6 +19007,852 @@ class SwipeGestureDetector {
|
|
|
18951
19007
|
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `boolean`, `(e: MouseEvent | TouchEvent) => boolean`, `(e: MouseEvent | TouchEvent) => void`, `(e: MouseEvent | TouchEvent) => void`, `(e: MouseEvent | TouchEvent, gesture: SwipeGesture) => void`]; }
|
|
18952
19008
|
}
|
|
18953
19009
|
|
|
19010
|
+
class RenderableComponent {
|
|
19011
|
+
_root = null;
|
|
19012
|
+
props;
|
|
19013
|
+
constructor(props) {
|
|
19014
|
+
this.props = (props ?? {});
|
|
19015
|
+
}
|
|
19016
|
+
render() {
|
|
19017
|
+
const newRoot = this.renderTemplate();
|
|
19018
|
+
const style = this.styleContent();
|
|
19019
|
+
if (style) {
|
|
19020
|
+
newRoot?.prepend(this.createStyleElement(style));
|
|
19021
|
+
}
|
|
19022
|
+
if (this._root) {
|
|
19023
|
+
this._root.replaceWith(newRoot ?? "");
|
|
19024
|
+
}
|
|
19025
|
+
this._root = newRoot;
|
|
19026
|
+
return this._root;
|
|
19027
|
+
}
|
|
19028
|
+
updateProps(props) {
|
|
19029
|
+
this.props = { ...this.props, ...props };
|
|
19030
|
+
this.render();
|
|
19031
|
+
}
|
|
19032
|
+
destroy() {
|
|
19033
|
+
this._root?.remove();
|
|
19034
|
+
this._root = null;
|
|
19035
|
+
}
|
|
19036
|
+
createStyleElement(css) {
|
|
19037
|
+
const styleEl = document.createElement("style");
|
|
19038
|
+
styleEl.textContent = css;
|
|
19039
|
+
return styleEl;
|
|
19040
|
+
}
|
|
19041
|
+
styleContent() {
|
|
19042
|
+
return "";
|
|
19043
|
+
}
|
|
19044
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`Props`]; }
|
|
19045
|
+
}
|
|
19046
|
+
|
|
19047
|
+
function h(tag, ...rest) {
|
|
19048
|
+
let props = {};
|
|
19049
|
+
let children = [];
|
|
19050
|
+
if (rest[0] && typeof rest[0] === "object" && !(rest[0] instanceof Node)) {
|
|
19051
|
+
props = rest.shift();
|
|
19052
|
+
}
|
|
19053
|
+
children = rest.flat();
|
|
19054
|
+
const el = document.createElement(tag);
|
|
19055
|
+
for (const [key, value] of Object.entries(props)) {
|
|
19056
|
+
if (value == null)
|
|
19057
|
+
continue;
|
|
19058
|
+
if (key === "class" || key === "className") {
|
|
19059
|
+
el.className = value;
|
|
19060
|
+
}
|
|
19061
|
+
else if (key === "textContent") {
|
|
19062
|
+
el.textContent = value;
|
|
19063
|
+
}
|
|
19064
|
+
else if (key === "html" || key === "innerHTML") {
|
|
19065
|
+
el.innerHTML = value;
|
|
19066
|
+
}
|
|
19067
|
+
else if (key === "ref" && typeof value === "function") {
|
|
19068
|
+
value(el);
|
|
19069
|
+
}
|
|
19070
|
+
else if (key.startsWith("data-")) {
|
|
19071
|
+
el.setAttribute(key, value);
|
|
19072
|
+
}
|
|
19073
|
+
else if (key.startsWith("on") && typeof value === "function") {
|
|
19074
|
+
const event = key.slice(2).toLowerCase();
|
|
19075
|
+
el.addEventListener(event, value);
|
|
19076
|
+
}
|
|
19077
|
+
else if (key in el) {
|
|
19078
|
+
// @ts-ignore — any valid DOM props
|
|
19079
|
+
el[key] = value;
|
|
19080
|
+
}
|
|
19081
|
+
else {
|
|
19082
|
+
el.setAttribute(key, value);
|
|
19083
|
+
}
|
|
19084
|
+
}
|
|
19085
|
+
for (const child of children) {
|
|
19086
|
+
if (child == null)
|
|
19087
|
+
continue;
|
|
19088
|
+
if (typeof child === "string") {
|
|
19089
|
+
el.appendChild(document.createTextNode(child));
|
|
19090
|
+
}
|
|
19091
|
+
else {
|
|
19092
|
+
el.appendChild(child);
|
|
19093
|
+
}
|
|
19094
|
+
}
|
|
19095
|
+
return el;
|
|
19096
|
+
}
|
|
19097
|
+
|
|
19098
|
+
class BottomSheet extends RenderableComponent {
|
|
19099
|
+
isClosing = false;
|
|
19100
|
+
_isOpened = false;
|
|
19101
|
+
constructor(props) {
|
|
19102
|
+
super(props ?? {});
|
|
19103
|
+
}
|
|
19104
|
+
get isOpened() {
|
|
19105
|
+
return this._isOpened;
|
|
19106
|
+
}
|
|
19107
|
+
renderTemplate() {
|
|
19108
|
+
// TODO: calculate border-radius;
|
|
19109
|
+
const borderRadius = 30;
|
|
19110
|
+
return h("div", { class: `ias-bottom-sheet ${this._isOpened ? "ias-bottom-sheet--open" : ""}` }, h("div", {
|
|
19111
|
+
class: "ias-bottom-sheet__backdrop",
|
|
19112
|
+
onClick: this.handleBackdropClick,
|
|
19113
|
+
}), h("div", {
|
|
19114
|
+
class: "ias-bottom-sheet__container",
|
|
19115
|
+
style: this.props.minHeight != null ? `min-height: ${this.props.minHeight + borderRadius}px` : "",
|
|
19116
|
+
}, h("div", { class: "ias-bottom-sheet__content" },
|
|
19117
|
+
/* h("div", { class: "ias-bottom-sheet__header" }), */
|
|
19118
|
+
h("div", { class: "ias-bottom-sheet__body" }, ...(this.props?.children?.map(c => c.render()) ?? [])))));
|
|
19119
|
+
}
|
|
19120
|
+
setMinHeight(height) {
|
|
19121
|
+
if (!this._root)
|
|
19122
|
+
return;
|
|
19123
|
+
const container = this._root.querySelector(".ias-bottom-sheet__container");
|
|
19124
|
+
if (!container)
|
|
19125
|
+
return;
|
|
19126
|
+
container.style.minHeight = `${height}px`;
|
|
19127
|
+
}
|
|
19128
|
+
open() {
|
|
19129
|
+
if (this.isOpened)
|
|
19130
|
+
return;
|
|
19131
|
+
this._isOpened = true;
|
|
19132
|
+
requestAnimationFrame(() => {
|
|
19133
|
+
requestAnimationFrame(() => {
|
|
19134
|
+
this._root?.classList.add("ias-bottom-sheet--open");
|
|
19135
|
+
});
|
|
19136
|
+
});
|
|
19137
|
+
}
|
|
19138
|
+
async close() {
|
|
19139
|
+
if (!this._root || this.isClosing)
|
|
19140
|
+
return;
|
|
19141
|
+
const root = this._root;
|
|
19142
|
+
root.classList.remove("ias-bottom-sheet--open");
|
|
19143
|
+
this.isClosing = true;
|
|
19144
|
+
await new Promise(resolve => {
|
|
19145
|
+
root.addEventListener("transitionend", () => resolve(), { once: true });
|
|
19146
|
+
});
|
|
19147
|
+
this.isClosing = false;
|
|
19148
|
+
this.props?.onClose?.();
|
|
19149
|
+
}
|
|
19150
|
+
handleBackdropClick = (e) => {
|
|
19151
|
+
e.preventDefault();
|
|
19152
|
+
e.stopPropagation();
|
|
19153
|
+
this.close();
|
|
19154
|
+
};
|
|
19155
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`BottomSheetProps`]; }
|
|
19156
|
+
}
|
|
19157
|
+
|
|
19158
|
+
class ProductDetailsDescription extends RenderableComponent {
|
|
19159
|
+
constructor(props) {
|
|
19160
|
+
super(props);
|
|
19161
|
+
}
|
|
19162
|
+
renderTemplate() {
|
|
19163
|
+
const { name, description } = this.props;
|
|
19164
|
+
return h("div", { class: "ias-product-details__description" }, name ? h("h6", { class: "ias-product-details__name", textContent: name }) : null, description ? h("p", { class: "ias-product-details__text", textContent: description }) : null);
|
|
19165
|
+
}
|
|
19166
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductDetailsDescriptionProps`]; }
|
|
19167
|
+
}
|
|
19168
|
+
|
|
19169
|
+
class ProductDetailsGallery extends RenderableComponent {
|
|
19170
|
+
constructor(props) {
|
|
19171
|
+
super(props);
|
|
19172
|
+
}
|
|
19173
|
+
renderTemplate() {
|
|
19174
|
+
const { imageUrls = [] } = this.props;
|
|
19175
|
+
return h("div", { class: "ias-product-details__gallery" }, imageUrls.map(url => h("figure", { class: "ias-product-details__image" }, h("img", { src: url /* , loading: "lazy" */ }))));
|
|
19176
|
+
}
|
|
19177
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductDetailsGalleryProps`]; }
|
|
19178
|
+
}
|
|
19179
|
+
|
|
19180
|
+
const ADD_TO_CART_TIMEOUT = 60000;
|
|
19181
|
+
|
|
19182
|
+
class ProductDetailsPurchaseAction extends RenderableComponent {
|
|
19183
|
+
button;
|
|
19184
|
+
isLoading = false;
|
|
19185
|
+
constructor(props) {
|
|
19186
|
+
super(props);
|
|
19187
|
+
}
|
|
19188
|
+
renderTemplate() {
|
|
19189
|
+
this.button = h("button", {
|
|
19190
|
+
class: "ias-product-details__action-button",
|
|
19191
|
+
textContent: this.props.translations.addToCart,
|
|
19192
|
+
onClick: this.handleClickAddToCart,
|
|
19193
|
+
});
|
|
19194
|
+
return this.button;
|
|
19195
|
+
}
|
|
19196
|
+
handleClickAddToCart = async () => {
|
|
19197
|
+
if (this.isLoading)
|
|
19198
|
+
return;
|
|
19199
|
+
try {
|
|
19200
|
+
this.isLoading = true;
|
|
19201
|
+
this.showLoader();
|
|
19202
|
+
await this.addToCart();
|
|
19203
|
+
}
|
|
19204
|
+
catch (error) {
|
|
19205
|
+
this.handleAddToCartError(error);
|
|
19206
|
+
}
|
|
19207
|
+
finally {
|
|
19208
|
+
this.hideLoader();
|
|
19209
|
+
this.isLoading = false;
|
|
19210
|
+
}
|
|
19211
|
+
};
|
|
19212
|
+
showLoader() {
|
|
19213
|
+
this.button.classList.add("ias-product-details__action-button--loading");
|
|
19214
|
+
}
|
|
19215
|
+
hideLoader() {
|
|
19216
|
+
this.button.classList.remove("ias-product-details__action-button--loading");
|
|
19217
|
+
}
|
|
19218
|
+
handleAddToCartError(error) {
|
|
19219
|
+
this.props.onAddToCartError({ error });
|
|
19220
|
+
}
|
|
19221
|
+
async addToCart() {
|
|
19222
|
+
await Promise.race([this.props.onAddToCart(), new Promise((resolve, reject) => setTimeout(reject, ADD_TO_CART_TIMEOUT))]);
|
|
19223
|
+
}
|
|
19224
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductDetailsPurchaseActionProps`]; }
|
|
19225
|
+
}
|
|
19226
|
+
|
|
19227
|
+
class ProductDetailsPurchasePrice extends RenderableComponent {
|
|
19228
|
+
constructor(props) {
|
|
19229
|
+
super(props);
|
|
19230
|
+
}
|
|
19231
|
+
renderTemplate() {
|
|
19232
|
+
const { price, oldPrice, currency } = this.props.product;
|
|
19233
|
+
const rootEl = h("div", { class: "ias-product-details__price" });
|
|
19234
|
+
if (price != null && currency) {
|
|
19235
|
+
const currentPriceEl = h("div", {
|
|
19236
|
+
class: "ias-product-details__current-price",
|
|
19237
|
+
html: formatter.asCurrency(price, currency),
|
|
19238
|
+
});
|
|
19239
|
+
rootEl.appendChild(currentPriceEl);
|
|
19240
|
+
}
|
|
19241
|
+
if (oldPrice != null && currency) {
|
|
19242
|
+
const oldPriceEl = h("div", {
|
|
19243
|
+
class: "ias-product-details__old-price",
|
|
19244
|
+
html: formatter.asCurrency(oldPrice, currency),
|
|
19245
|
+
});
|
|
19246
|
+
rootEl.appendChild(oldPriceEl);
|
|
19247
|
+
}
|
|
19248
|
+
return rootEl;
|
|
19249
|
+
}
|
|
19250
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductDetailsPurchasePriceProps`]; }
|
|
19251
|
+
}
|
|
19252
|
+
|
|
19253
|
+
class ProductDetailsCounter extends RenderableComponent {
|
|
19254
|
+
_value = 1;
|
|
19255
|
+
countElement = null;
|
|
19256
|
+
get value() {
|
|
19257
|
+
return this._value;
|
|
19258
|
+
}
|
|
19259
|
+
updateProps() {
|
|
19260
|
+
this._value = 1;
|
|
19261
|
+
this.render();
|
|
19262
|
+
}
|
|
19263
|
+
renderTemplate() {
|
|
19264
|
+
return h("div", { class: "ias-product-details__counter" }, h("button", {
|
|
19265
|
+
class: "ias-product-details__counter-button",
|
|
19266
|
+
textContent: "−",
|
|
19267
|
+
onClick: this.handleClickOnMinusButton,
|
|
19268
|
+
}), h("span", {
|
|
19269
|
+
class: "ias-product-details__counter-count",
|
|
19270
|
+
textContent: this._value.toString(),
|
|
19271
|
+
ref: (el) => (this.countElement = el),
|
|
19272
|
+
}), h("button", {
|
|
19273
|
+
class: "ias-product-details__counter-button",
|
|
19274
|
+
textContent: "+",
|
|
19275
|
+
onClick: this.handleClickOnPlusButton,
|
|
19276
|
+
}));
|
|
19277
|
+
}
|
|
19278
|
+
handleClickOnMinusButton = () => {
|
|
19279
|
+
this._value = Math.max(this._value - 1, 1);
|
|
19280
|
+
this.updateCountValue();
|
|
19281
|
+
};
|
|
19282
|
+
handleClickOnPlusButton = () => {
|
|
19283
|
+
this._value++;
|
|
19284
|
+
this.updateCountValue();
|
|
19285
|
+
};
|
|
19286
|
+
updateCountValue() {
|
|
19287
|
+
if (this.countElement) {
|
|
19288
|
+
this.countElement.textContent = this._value.toString();
|
|
19289
|
+
}
|
|
19290
|
+
}
|
|
19291
|
+
}
|
|
19292
|
+
|
|
19293
|
+
class ProductDetailsPurchase extends RenderableComponent {
|
|
19294
|
+
price;
|
|
19295
|
+
action;
|
|
19296
|
+
counter = new ProductDetailsCounter();
|
|
19297
|
+
constructor(props) {
|
|
19298
|
+
super(props);
|
|
19299
|
+
}
|
|
19300
|
+
renderTemplate() {
|
|
19301
|
+
this.price = new ProductDetailsPurchasePrice(this.props);
|
|
19302
|
+
this.action = new ProductDetailsPurchaseAction({
|
|
19303
|
+
onAddToCart: this.handleOnAddToCart,
|
|
19304
|
+
onAddToCartError: this.props.onAddToCartError,
|
|
19305
|
+
translations: this.props.translations,
|
|
19306
|
+
});
|
|
19307
|
+
return h("div", { class: "ias-product-details__purchase" }, h("div", { class: "ias-product-details__price-box" }, this.price.render(), this.counter.render()), this.action.render());
|
|
19308
|
+
}
|
|
19309
|
+
updateProps(props) {
|
|
19310
|
+
this.props = { ...this.props, ...props };
|
|
19311
|
+
this.price.updateProps(this.props);
|
|
19312
|
+
this.counter.updateProps();
|
|
19313
|
+
}
|
|
19314
|
+
handleOnAddToCart = async () => {
|
|
19315
|
+
return this.props.onAddToCart({
|
|
19316
|
+
quantity: this.counter.value,
|
|
19317
|
+
product: this.props.product,
|
|
19318
|
+
});
|
|
19319
|
+
};
|
|
19320
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductDetailsPurchaseProps`]; }
|
|
19321
|
+
}
|
|
19322
|
+
|
|
19323
|
+
class ProductOptionButton extends RenderableComponent {
|
|
19324
|
+
constructor(props) {
|
|
19325
|
+
super(props);
|
|
19326
|
+
}
|
|
19327
|
+
renderTemplate() {
|
|
19328
|
+
const params = {
|
|
19329
|
+
class: `ias-product-details__option-button ${this.props.selected ? "ias-product-details__option-button--active" : ""} ${this.props.disabled ? "ias-product-details__option-button--disabled" : ""}`,
|
|
19330
|
+
textContent: this.props.label,
|
|
19331
|
+
onclick: () => {
|
|
19332
|
+
this.props.onClick();
|
|
19333
|
+
},
|
|
19334
|
+
};
|
|
19335
|
+
return h("button", params);
|
|
19336
|
+
}
|
|
19337
|
+
setSelected(selected) {
|
|
19338
|
+
if (!this._root)
|
|
19339
|
+
return;
|
|
19340
|
+
if (selected)
|
|
19341
|
+
this._root.classList.add("ias-product-details__option-button--active");
|
|
19342
|
+
else
|
|
19343
|
+
this._root.classList.remove("ias-product-details__option-button--active");
|
|
19344
|
+
}
|
|
19345
|
+
setDisabled(disabled) {
|
|
19346
|
+
if (!this._root)
|
|
19347
|
+
return;
|
|
19348
|
+
if (disabled)
|
|
19349
|
+
this._root.classList.add("ias-product-details__option-button--disabled");
|
|
19350
|
+
else
|
|
19351
|
+
this._root.classList.remove("ias-product-details__option-button--disabled");
|
|
19352
|
+
}
|
|
19353
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductOptionButtonProps`]; }
|
|
19354
|
+
}
|
|
19355
|
+
|
|
19356
|
+
class ProductOptionsManager {
|
|
19357
|
+
optionNames;
|
|
19358
|
+
productVariants;
|
|
19359
|
+
subscribers = [];
|
|
19360
|
+
selectedOptions = {};
|
|
19361
|
+
allOptionsByName = {};
|
|
19362
|
+
availableOptionsByName = {};
|
|
19363
|
+
constructor(optionNames, productVariants) {
|
|
19364
|
+
this.optionNames = optionNames;
|
|
19365
|
+
this.productVariants = productVariants;
|
|
19366
|
+
this.allOptionsByName = this.extractAllOptions();
|
|
19367
|
+
}
|
|
19368
|
+
get selected() {
|
|
19369
|
+
return { ...this.selectedOptions };
|
|
19370
|
+
}
|
|
19371
|
+
get availableOptions() {
|
|
19372
|
+
return this.availableOptionsByName;
|
|
19373
|
+
}
|
|
19374
|
+
selectOption(option) {
|
|
19375
|
+
const compatibleVariants = this.findCompatibleVariants(option);
|
|
19376
|
+
this.ensureVariantsExist(option, compatibleVariants);
|
|
19377
|
+
const matchingVariant = this.findMatchingVariant(compatibleVariants);
|
|
19378
|
+
this.selectVariant(matchingVariant);
|
|
19379
|
+
}
|
|
19380
|
+
selectVariant(variant) {
|
|
19381
|
+
this.optionNames.forEach(name => {
|
|
19382
|
+
const currentSelected = this.selectedOptions[name];
|
|
19383
|
+
const newOption = variant.options[name];
|
|
19384
|
+
if (currentSelected && newOption && currentSelected.value === newOption.value) {
|
|
19385
|
+
this.selectedOptions[name] = currentSelected;
|
|
19386
|
+
}
|
|
19387
|
+
else {
|
|
19388
|
+
this.selectedOptions[name] = newOption;
|
|
19389
|
+
}
|
|
19390
|
+
});
|
|
19391
|
+
this.availableOptionsByName = this.extractAvailableOptions();
|
|
19392
|
+
this.notifySubscribers(variant);
|
|
19393
|
+
}
|
|
19394
|
+
onChange(callback) {
|
|
19395
|
+
this.subscribers.push(callback);
|
|
19396
|
+
}
|
|
19397
|
+
isOptionSelected(option) {
|
|
19398
|
+
return this.selected[option.name]?.value === option.value;
|
|
19399
|
+
}
|
|
19400
|
+
isOptionDisabled(option) {
|
|
19401
|
+
const options = this.availableOptions[option.name];
|
|
19402
|
+
return !options?.some(o => o.value === option.value);
|
|
19403
|
+
}
|
|
19404
|
+
getOptionsFor(name) {
|
|
19405
|
+
return this.allOptionsByName[name] ?? [];
|
|
19406
|
+
}
|
|
19407
|
+
findCompatibleVariants(option) {
|
|
19408
|
+
return this.productVariants.filter(variant => variant.options[option.name]?.value === option.value);
|
|
19409
|
+
}
|
|
19410
|
+
ensureVariantsExist(option, variants) {
|
|
19411
|
+
if (variants.length === 0) {
|
|
19412
|
+
throw new Error(`[IAS]: No compatible variant for option <${option.name}:${option.value}>`);
|
|
19413
|
+
}
|
|
19414
|
+
}
|
|
19415
|
+
findMatchingVariant(variants) {
|
|
19416
|
+
return (variants.find(variant => this.optionNames.every(name => !this.selectedOptions[name] || variant.options[name]?.value === this.selectedOptions[name]?.value)) ?? variants[0]);
|
|
19417
|
+
}
|
|
19418
|
+
extractAvailableOptions() {
|
|
19419
|
+
const result = {};
|
|
19420
|
+
for (const name of this.optionNames) {
|
|
19421
|
+
const filteredVariants = this.filterVariantsExcludingOption(name);
|
|
19422
|
+
const available = filteredVariants.filter(v => v.available && v.options[name]).map(v => v.options[name]);
|
|
19423
|
+
result[name] = this.getUniqueByKey(available, o => o.value);
|
|
19424
|
+
}
|
|
19425
|
+
return result;
|
|
19426
|
+
}
|
|
19427
|
+
filterVariantsExcludingOption(excludedName) {
|
|
19428
|
+
const filters = { ...this.selectedOptions };
|
|
19429
|
+
delete filters[excludedName];
|
|
19430
|
+
return this.productVariants.filter(variant => Object.entries(filters).every(([name, selected]) => variant.options[name]?.value === selected?.value));
|
|
19431
|
+
}
|
|
19432
|
+
extractAllOptions() {
|
|
19433
|
+
const all = {};
|
|
19434
|
+
for (const name of this.optionNames) {
|
|
19435
|
+
const options = this.productVariants.map(v => v.options[name]).filter(Boolean);
|
|
19436
|
+
all[name] = this.getUniqueByKey(options, o => o.value);
|
|
19437
|
+
}
|
|
19438
|
+
return all;
|
|
19439
|
+
}
|
|
19440
|
+
getUniqueByKey(items, getKey) {
|
|
19441
|
+
return items.filter((item, index, self) => index === self.findIndex(i => getKey(i) === getKey(item)));
|
|
19442
|
+
}
|
|
19443
|
+
notifySubscribers(variant) {
|
|
19444
|
+
this.subscribers.forEach(cb => cb(variant));
|
|
19445
|
+
}
|
|
19446
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductOptionName[]`, `ProductVariant[]`]; }
|
|
19447
|
+
}
|
|
19448
|
+
|
|
19449
|
+
class ProductOptions extends RenderableComponent {
|
|
19450
|
+
optionsManager;
|
|
19451
|
+
optionsContainer;
|
|
19452
|
+
optionButtonsMap = new Map();
|
|
19453
|
+
constructor(props) {
|
|
19454
|
+
super(props);
|
|
19455
|
+
this.optionsManager = new ProductOptionsManager(props.optionNames, props.products);
|
|
19456
|
+
this.init(props.products);
|
|
19457
|
+
}
|
|
19458
|
+
renderTemplate() {
|
|
19459
|
+
this.optionsContainer = h("div", { class: "ias-product-details__options" }, this.renderOptionSelectors());
|
|
19460
|
+
return this.optionsContainer;
|
|
19461
|
+
}
|
|
19462
|
+
init(products) {
|
|
19463
|
+
this.optionsManager.selectVariant(products[0]);
|
|
19464
|
+
this.optionsManager.onChange(variant => {
|
|
19465
|
+
this.updateButtonsState();
|
|
19466
|
+
this.props.onChange(variant);
|
|
19467
|
+
});
|
|
19468
|
+
}
|
|
19469
|
+
renderOptionSelectors() {
|
|
19470
|
+
return this.props.optionNames.map(optionName => this.optionsManager.getOptionsFor(optionName).length > 0
|
|
19471
|
+
? h("div", { class: "ias-product-details__selector" }, h("div", { class: "ias-product-details__selector-name", textContent: this.getOptionLabelByName(optionName) }), h("div", { class: "ias-product-details__option-selector" }, this.renderOptionsBySelector(optionName)))
|
|
19472
|
+
: null);
|
|
19473
|
+
}
|
|
19474
|
+
getOptionLabelByName(optionName) {
|
|
19475
|
+
switch (optionName) {
|
|
19476
|
+
case "color":
|
|
19477
|
+
return this.props.translations.color;
|
|
19478
|
+
case "size":
|
|
19479
|
+
return this.props.translations.size;
|
|
19480
|
+
}
|
|
19481
|
+
}
|
|
19482
|
+
renderOptionsBySelector(name) {
|
|
19483
|
+
const options = this.optionsManager.getOptionsFor(name);
|
|
19484
|
+
const buttons = [];
|
|
19485
|
+
const buttonElements = options.map(option => {
|
|
19486
|
+
const disabled = this.optionsManager.isOptionDisabled(option);
|
|
19487
|
+
const selected = this.optionsManager.isOptionSelected(option);
|
|
19488
|
+
const productOptionButton = new ProductOptionButton({
|
|
19489
|
+
selected,
|
|
19490
|
+
label: option.value,
|
|
19491
|
+
disabled,
|
|
19492
|
+
onClick: () => {
|
|
19493
|
+
this.optionsManager.selectOption(option);
|
|
19494
|
+
},
|
|
19495
|
+
});
|
|
19496
|
+
buttons.push(productOptionButton);
|
|
19497
|
+
return productOptionButton.render();
|
|
19498
|
+
});
|
|
19499
|
+
this.optionButtonsMap.set(name, buttons);
|
|
19500
|
+
return buttonElements;
|
|
19501
|
+
}
|
|
19502
|
+
updateButtonsState() {
|
|
19503
|
+
for (const [optionName, buttons] of this.optionButtonsMap.entries()) {
|
|
19504
|
+
const options = this.optionsManager.getOptionsFor(optionName);
|
|
19505
|
+
buttons.forEach((button, index) => {
|
|
19506
|
+
const option = options[index];
|
|
19507
|
+
const isSelected = this.optionsManager.isOptionSelected(option);
|
|
19508
|
+
const isDisabled = this.optionsManager.isOptionDisabled(option);
|
|
19509
|
+
button.setSelected(isSelected);
|
|
19510
|
+
button.setDisabled(isDisabled);
|
|
19511
|
+
});
|
|
19512
|
+
}
|
|
19513
|
+
}
|
|
19514
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductOptionsProps`]; }
|
|
19515
|
+
}
|
|
19516
|
+
|
|
19517
|
+
class ProductDetailsCover extends RenderableComponent {
|
|
19518
|
+
renderTemplate() {
|
|
19519
|
+
return h(`div`, { class: "ias-product-details__cover" }, h("img", { src: this.props.src }));
|
|
19520
|
+
}
|
|
19521
|
+
styleContent() {
|
|
19522
|
+
return `
|
|
19523
|
+
.ias-product-details__cover {
|
|
19524
|
+
position: absolute;
|
|
19525
|
+
z-index: -1;
|
|
19526
|
+
inset: 0;
|
|
19527
|
+
}
|
|
19528
|
+
|
|
19529
|
+
.ias-product-details__cover img {
|
|
19530
|
+
width: 100%;
|
|
19531
|
+
height: 100%;
|
|
19532
|
+
object-fit: cover;
|
|
19533
|
+
}
|
|
19534
|
+
`;
|
|
19535
|
+
}
|
|
19536
|
+
}
|
|
19537
|
+
|
|
19538
|
+
class ProductDetails extends RenderableComponent {
|
|
19539
|
+
constructor(props) {
|
|
19540
|
+
super(props);
|
|
19541
|
+
}
|
|
19542
|
+
renderTemplate() {
|
|
19543
|
+
const { props } = this;
|
|
19544
|
+
const purchase = new ProductDetailsPurchase(props);
|
|
19545
|
+
const cover = new ProductDetailsCover({
|
|
19546
|
+
src: this.props.product.coverUrl ?? "",
|
|
19547
|
+
});
|
|
19548
|
+
const gallery = new ProductDetailsGallery({
|
|
19549
|
+
imageUrls: this.props.product.imageUrls ?? [],
|
|
19550
|
+
});
|
|
19551
|
+
const description = new ProductDetailsDescription(props.product);
|
|
19552
|
+
const productOptions = this.createProductOptions({ purchase, gallery, description, cover });
|
|
19553
|
+
const relatedProductsLength = this.props.relatedProducts.length ?? 0;
|
|
19554
|
+
return h("div", { class: "ias-product-details" },
|
|
19555
|
+
/* this.props.product.coverUrl ? cover.render() : null, */
|
|
19556
|
+
h("div", { class: "ias-product-details__scrollable" }, gallery.render(), h("div", { class: "ias-product-details__content" }, description.render(), relatedProductsLength > 0 ? productOptions.render() : null)), this.createFooter(purchase));
|
|
19557
|
+
}
|
|
19558
|
+
createProductOptions({ purchase, gallery, description, cover, }) {
|
|
19559
|
+
return new ProductOptions({
|
|
19560
|
+
optionNames: ["color", "size"],
|
|
19561
|
+
products: [this.props.product, ...this.props.relatedProducts],
|
|
19562
|
+
onChange: (product) => {
|
|
19563
|
+
if (this.props.isCartSupported)
|
|
19564
|
+
purchase.updateProps({ product: product });
|
|
19565
|
+
gallery.updateProps(product);
|
|
19566
|
+
description.updateProps(product);
|
|
19567
|
+
cover.updateProps({
|
|
19568
|
+
src: product.coverUrl,
|
|
19569
|
+
});
|
|
19570
|
+
},
|
|
19571
|
+
translations: this.props.translations,
|
|
19572
|
+
});
|
|
19573
|
+
}
|
|
19574
|
+
createFooter(purchase) {
|
|
19575
|
+
if (this.props.isCartSupported) {
|
|
19576
|
+
return h("div", { class: "ias-product-details__footer" }, purchase.render());
|
|
19577
|
+
}
|
|
19578
|
+
else if (this.props.product.url) {
|
|
19579
|
+
return h("div", { class: "ias-product-details__footer" }, this.createOpenUrlButton());
|
|
19580
|
+
}
|
|
19581
|
+
return null;
|
|
19582
|
+
}
|
|
19583
|
+
createOpenUrlButton() {
|
|
19584
|
+
return h("button", {
|
|
19585
|
+
class: "ias-product-details__action-button ias-product-details__open-url-button",
|
|
19586
|
+
textContent: this.props.translations.openUrl,
|
|
19587
|
+
onclick: () => {
|
|
19588
|
+
this.props.onOpenUrl();
|
|
19589
|
+
},
|
|
19590
|
+
});
|
|
19591
|
+
}
|
|
19592
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductDetailsProps`]; }
|
|
19593
|
+
}
|
|
19594
|
+
|
|
19595
|
+
const successSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="none"><path stroke="#212121" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M40 14 18 36 8 26"></path></svg>`;
|
|
19596
|
+
class ProductCheckout extends RenderableComponent {
|
|
19597
|
+
constructor(props) {
|
|
19598
|
+
super(props);
|
|
19599
|
+
}
|
|
19600
|
+
renderTemplate() {
|
|
19601
|
+
return h("div", { class: "ias-product-checkout" }, h("div", { class: "ias-product-checkout__box" }, h("div", {
|
|
19602
|
+
class: "ias-product-checkout__icon",
|
|
19603
|
+
html: successSvg,
|
|
19604
|
+
}), h("span", {
|
|
19605
|
+
class: "ias-product-checkout__text",
|
|
19606
|
+
textContent: this.props.translations.successAddToCart,
|
|
19607
|
+
}), h("span", {
|
|
19608
|
+
class: "ias-product-checkout__sub-text",
|
|
19609
|
+
textContent: this.props.translations.successSubAddToCart,
|
|
19610
|
+
})), h("div", {
|
|
19611
|
+
class: "ias-product-checkout__actions",
|
|
19612
|
+
}, h("button", {
|
|
19613
|
+
class: "ias-product-checkout__button ias-product-checkout__button--close",
|
|
19614
|
+
textContent: this.props.translations.continueBtn,
|
|
19615
|
+
onclick: () => {
|
|
19616
|
+
this.props.onClose();
|
|
19617
|
+
},
|
|
19618
|
+
}), h("button", {
|
|
19619
|
+
class: "ias-product-checkout__button ias-product-checkout__button--checkout",
|
|
19620
|
+
textContent: this.props.translations.goToCartBtn,
|
|
19621
|
+
onclick: () => {
|
|
19622
|
+
this.props.onCheckout();
|
|
19623
|
+
},
|
|
19624
|
+
})));
|
|
19625
|
+
}
|
|
19626
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductCheckoutProps`]; }
|
|
19627
|
+
}
|
|
19628
|
+
|
|
19629
|
+
const cartSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 20 20" fill="none">
|
|
19630
|
+
<path stroke="rgba(255, 255, 255, 1)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.333" d="M4 1.333 2 4v9.333a1.333 1.333 0 0 0 1.333 1.334h9.334A1.334 1.334 0 0 0 14 13.333V4l-2-2.667H4ZM2 4h12"></path>
|
|
19631
|
+
<path stroke="rgba(255, 255, 255, 1)" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.333" d="M10.667 6.667a2.667 2.667 0 1 1-5.333 0"></path>
|
|
19632
|
+
</svg>`;
|
|
19633
|
+
class ProductCartButton extends RenderableComponent {
|
|
19634
|
+
constructor(props) {
|
|
19635
|
+
super(props);
|
|
19636
|
+
}
|
|
19637
|
+
renderTemplate() {
|
|
19638
|
+
return h("div", { class: "ias-product-cart-button", onclick: () => this.props.onClick(), innerHTML: cartSvg });
|
|
19639
|
+
}
|
|
19640
|
+
styleContent() {
|
|
19641
|
+
return `
|
|
19642
|
+
.ias-product-cart-button {
|
|
19643
|
+
position: absolute;
|
|
19644
|
+
left: 0;
|
|
19645
|
+
top: 20%;
|
|
19646
|
+
padding: .25em;
|
|
19647
|
+
padding-left: .5em;
|
|
19648
|
+
background: black;
|
|
19649
|
+
border-top-right-radius: 0.69em;
|
|
19650
|
+
border-bottom-right-radius: 0.69em;
|
|
19651
|
+
display: flex;
|
|
19652
|
+
justify-content: center;
|
|
19653
|
+
align-items: center;
|
|
19654
|
+
cursor: pointer;
|
|
19655
|
+
transition: all 200ms ease-in;
|
|
19656
|
+
transform: translate3d(-.25em, 0, 0);
|
|
19657
|
+
}
|
|
19658
|
+
|
|
19659
|
+
.ias-product-cart-button:hover {
|
|
19660
|
+
transform: translate3d(0, 0, 0);
|
|
19661
|
+
}
|
|
19662
|
+
`;
|
|
19663
|
+
}
|
|
19664
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ProductCartButtonProps`]; }
|
|
19665
|
+
}
|
|
19666
|
+
|
|
19667
|
+
class ProductComponentsFactory {
|
|
19668
|
+
widgetDeps;
|
|
19669
|
+
props;
|
|
19670
|
+
constructor(widgetDeps, props) {
|
|
19671
|
+
this.widgetDeps = widgetDeps;
|
|
19672
|
+
this.props = props;
|
|
19673
|
+
}
|
|
19674
|
+
createBottomSheet(props) {
|
|
19675
|
+
const bs = new BottomSheet({
|
|
19676
|
+
onClose: () => {
|
|
19677
|
+
bs.destroy();
|
|
19678
|
+
},
|
|
19679
|
+
children: [],
|
|
19680
|
+
minHeight: props.minHeight,
|
|
19681
|
+
});
|
|
19682
|
+
return bs;
|
|
19683
|
+
}
|
|
19684
|
+
createProductDetails(params) {
|
|
19685
|
+
return new ProductDetails({
|
|
19686
|
+
product: params.product,
|
|
19687
|
+
relatedProducts: params.relatedProducts,
|
|
19688
|
+
onAddToCart: params.onAddToCart,
|
|
19689
|
+
onAddToCartError: ({ error }) => {
|
|
19690
|
+
this.widgetDeps.slideApiDeps.showToast(error.message);
|
|
19691
|
+
},
|
|
19692
|
+
translations: this.props.translations,
|
|
19693
|
+
isCartSupported: params.isCartSupported,
|
|
19694
|
+
onOpenUrl: () => {
|
|
19695
|
+
if (params.product.url)
|
|
19696
|
+
this.widgetDeps.slideApiDeps.openUrl({ type: "link", link: { type: "url", target: params.product.url } });
|
|
19697
|
+
},
|
|
19698
|
+
});
|
|
19699
|
+
}
|
|
19700
|
+
createProductCheckout(bottomSheet, offers) {
|
|
19701
|
+
const offersByIds = {};
|
|
19702
|
+
for (const offer of offers)
|
|
19703
|
+
offersByIds[offer.offerId] = offer;
|
|
19704
|
+
return new ProductCheckout({
|
|
19705
|
+
onClose: () => bottomSheet.close(),
|
|
19706
|
+
onCheckout: () => {
|
|
19707
|
+
this.widgetDeps.slideApiDeps.productCartClicked();
|
|
19708
|
+
},
|
|
19709
|
+
translations: this.props.translations,
|
|
19710
|
+
});
|
|
19711
|
+
}
|
|
19712
|
+
createProductCartButton() {
|
|
19713
|
+
return new ProductCartButton({
|
|
19714
|
+
onClick: async () => {
|
|
19715
|
+
try {
|
|
19716
|
+
const state = await this.widgetDeps.slideApiDeps.productCartGetState();
|
|
19717
|
+
console.log({ cart: state });
|
|
19718
|
+
this.widgetDeps.slideApiDeps.showToast(JSON.stringify(state.offers.map(({ offerId, name, quantity }) => ({
|
|
19719
|
+
offerId,
|
|
19720
|
+
name,
|
|
19721
|
+
quantity,
|
|
19722
|
+
}))));
|
|
19723
|
+
}
|
|
19724
|
+
catch (error) {
|
|
19725
|
+
this.widgetDeps.slideApiDeps.showToast(error.message);
|
|
19726
|
+
}
|
|
19727
|
+
},
|
|
19728
|
+
});
|
|
19729
|
+
}
|
|
19730
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`WidgetDeps`, `{
|
|
19731
|
+
translations: TranslationsMap;
|
|
19732
|
+
}`]; }
|
|
19733
|
+
}
|
|
19734
|
+
|
|
19735
|
+
class ProductOfferMapper {
|
|
19736
|
+
static fromOfferDtoToProductOffer(offerDto) {
|
|
19737
|
+
return {
|
|
19738
|
+
id: offerDto.id.toString(),
|
|
19739
|
+
offerId: offerDto.offerId,
|
|
19740
|
+
available: offerDto.availability !== 0,
|
|
19741
|
+
availability: offerDto.availability,
|
|
19742
|
+
options: {
|
|
19743
|
+
color: offerDto.color ? { name: "color", value: offerDto.color } : { name: "color", value: "Undefined" },
|
|
19744
|
+
size: offerDto.size ? { name: "size", value: offerDto.size } : { name: "size", value: "Undefined" },
|
|
19745
|
+
},
|
|
19746
|
+
name: offerDto.name,
|
|
19747
|
+
price: offerDto.price,
|
|
19748
|
+
oldPrice: offerDto.oldPrice,
|
|
19749
|
+
currency: offerDto.currency,
|
|
19750
|
+
description: offerDto.description,
|
|
19751
|
+
imageUrls: offerDto.images?.map(image => image.url) ?? [],
|
|
19752
|
+
adult: offerDto.adult,
|
|
19753
|
+
coverUrl: offerDto.coverUrl,
|
|
19754
|
+
groupId: offerDto.groupId,
|
|
19755
|
+
url: offerDto.url,
|
|
19756
|
+
};
|
|
19757
|
+
}
|
|
19758
|
+
static fromOfferDtoToProductCartOffer(offerDto, quantity) {
|
|
19759
|
+
return {
|
|
19760
|
+
offerId: offerDto.offerId,
|
|
19761
|
+
imageUrls: offerDto.images?.map(image => image.url) ?? [],
|
|
19762
|
+
availability: offerDto.availability,
|
|
19763
|
+
quantity,
|
|
19764
|
+
groupId: offerDto.groupId,
|
|
19765
|
+
name: offerDto.name,
|
|
19766
|
+
description: offerDto.description,
|
|
19767
|
+
url: offerDto.url,
|
|
19768
|
+
coverUrl: offerDto.coverUrl,
|
|
19769
|
+
currency: offerDto.currency,
|
|
19770
|
+
price: offerDto.price,
|
|
19771
|
+
oldPrice: offerDto.oldPrice,
|
|
19772
|
+
adult: offerDto.adult,
|
|
19773
|
+
size: offerDto.size,
|
|
19774
|
+
color: offerDto.color,
|
|
19775
|
+
};
|
|
19776
|
+
}
|
|
19777
|
+
}
|
|
19778
|
+
|
|
19779
|
+
class ProductDetailsBottomSheet extends RenderableComponent {
|
|
19780
|
+
widgetDeps;
|
|
19781
|
+
factory;
|
|
19782
|
+
bottomSheet;
|
|
19783
|
+
constructor(widgetDeps, props) {
|
|
19784
|
+
super(props);
|
|
19785
|
+
this.widgetDeps = widgetDeps;
|
|
19786
|
+
this.factory = new ProductComponentsFactory(this.widgetDeps, this.props);
|
|
19787
|
+
this.bottomSheet = this.factory.createBottomSheet({ minHeight: props.height });
|
|
19788
|
+
}
|
|
19789
|
+
renderTemplate() {
|
|
19790
|
+
return this.bottomSheet.render();
|
|
19791
|
+
}
|
|
19792
|
+
open(params) {
|
|
19793
|
+
this.showProductDetails(params);
|
|
19794
|
+
this.bottomSheet.open();
|
|
19795
|
+
}
|
|
19796
|
+
showProductDetails = ({ offer, isCartSupported }) => {
|
|
19797
|
+
const factory = new ProductComponentsFactory(this.widgetDeps, this.props);
|
|
19798
|
+
const offerDtos = [offer, ...(offer.subOffersApi ?? [])];
|
|
19799
|
+
this.renderProductDetails({ factory, offer, offerDtos, isCartSupported });
|
|
19800
|
+
};
|
|
19801
|
+
renderProductDetails({ factory, offer, offerDtos, isCartSupported, }) {
|
|
19802
|
+
const { product, relatedProducts } = this.getProductAndRelatedProducts(offer);
|
|
19803
|
+
const productDetails = factory.createProductDetails({
|
|
19804
|
+
product,
|
|
19805
|
+
relatedProducts,
|
|
19806
|
+
onAddToCart: async (payload) => {
|
|
19807
|
+
await this.productCartUpdate({
|
|
19808
|
+
offerDtos,
|
|
19809
|
+
product: payload.product,
|
|
19810
|
+
quantity: payload.quantity,
|
|
19811
|
+
});
|
|
19812
|
+
this.showProductCheckout({ offerDtos });
|
|
19813
|
+
},
|
|
19814
|
+
isCartSupported,
|
|
19815
|
+
});
|
|
19816
|
+
this.updateBottomSheetContent(productDetails);
|
|
19817
|
+
}
|
|
19818
|
+
showProductCheckout({ offerDtos }) {
|
|
19819
|
+
const productCheckout = this.factory.createProductCheckout(this.bottomSheet, offerDtos);
|
|
19820
|
+
this.updateBottomSheetContent(productCheckout);
|
|
19821
|
+
}
|
|
19822
|
+
updateBottomSheetContent(content) {
|
|
19823
|
+
const cartButton = this.factory.createProductCartButton();
|
|
19824
|
+
const children = process.env.NODE_ENV === "staging" ? [cartButton, content] : [content];
|
|
19825
|
+
this.bottomSheet.updateProps({
|
|
19826
|
+
children,
|
|
19827
|
+
});
|
|
19828
|
+
}
|
|
19829
|
+
async productCartUpdate({ offerDtos, product, quantity }) {
|
|
19830
|
+
const offerDto = offerDtos.find(offerDto => product.offerId === offerDto.offerId);
|
|
19831
|
+
if (!offerDto)
|
|
19832
|
+
throw new Error(`[IAS]: Not found offer for ID ${product.offerId}`);
|
|
19833
|
+
const cartOffer = ProductOfferMapper.fromOfferDtoToProductCartOffer(offerDto, quantity);
|
|
19834
|
+
const delay = async () => new Promise(resolve => setTimeout(resolve, 300));
|
|
19835
|
+
const [productCart] = await Promise.all([
|
|
19836
|
+
await await this.widgetDeps.slideApiDeps.productCartUpdate({
|
|
19837
|
+
offer: cartOffer,
|
|
19838
|
+
}),
|
|
19839
|
+
delay(),
|
|
19840
|
+
]);
|
|
19841
|
+
return productCart.offers;
|
|
19842
|
+
}
|
|
19843
|
+
getProductAndRelatedProducts(offerDto) {
|
|
19844
|
+
return {
|
|
19845
|
+
product: ProductOfferMapper.fromOfferDtoToProductOffer(offerDto),
|
|
19846
|
+
relatedProducts: offerDto.subOffersApi
|
|
19847
|
+
? offerDto.subOffersApi
|
|
19848
|
+
.filter(subOffer => subOffer.size != null && subOffer.color != null)
|
|
19849
|
+
.map(subOffer => ProductOfferMapper.fromOfferDtoToProductOffer(subOffer))
|
|
19850
|
+
: [],
|
|
19851
|
+
};
|
|
19852
|
+
}
|
|
19853
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`WidgetDeps`, `ProductDetailsBottomSheetProps`]; }
|
|
19854
|
+
}
|
|
19855
|
+
|
|
18954
19856
|
/**
|
|
18955
19857
|
* adult: null
|
|
18956
19858
|
* availability: 1
|
|
@@ -19016,6 +19918,7 @@ class WidgetProducts extends WidgetBase {
|
|
|
19016
19918
|
}
|
|
19017
19919
|
onStart() {
|
|
19018
19920
|
super.onStart();
|
|
19921
|
+
this.isLoading = false;
|
|
19019
19922
|
// reinit for case when we returned to slide from other slide and onStop destroyed SwipeGestureDetector
|
|
19020
19923
|
this.initSwipeGestureDetector();
|
|
19021
19924
|
}
|
|
@@ -19100,12 +20003,22 @@ class WidgetProducts extends WidgetBase {
|
|
|
19100
20003
|
console.error(error);
|
|
19101
20004
|
}
|
|
19102
20005
|
}
|
|
20006
|
+
async getOrFetchProducts() {
|
|
20007
|
+
if (this.currentModels.length > 0)
|
|
20008
|
+
return this.currentModels;
|
|
20009
|
+
const result = await this.fetchProducts();
|
|
20010
|
+
if (result.models.length > 0) {
|
|
20011
|
+
this.currentModels = result.models;
|
|
20012
|
+
return result.models;
|
|
20013
|
+
}
|
|
20014
|
+
throw new Error(result.message);
|
|
20015
|
+
}
|
|
19103
20016
|
async fetchProducts() {
|
|
19104
20017
|
const fetchAndCacheMedia = async () => {
|
|
19105
20018
|
if (!this.linkTarget.length) {
|
|
19106
20019
|
return { message: this.msgServiceError ?? "", models: [] };
|
|
19107
20020
|
}
|
|
19108
|
-
let qs = `id=${this.linkTarget.join(",")}`;
|
|
20021
|
+
let qs = `id=${this.linkTarget.join(",")}&expand=images,subOffersApi`;
|
|
19109
20022
|
const sdkClientVariables = this.widgetDeps.getSdkClientVariables();
|
|
19110
20023
|
if (sdkClientVariables != null && sdkClientVariables.pos != null) {
|
|
19111
20024
|
qs += `&pos=${String(sdkClientVariables.pos)}`;
|
|
@@ -19214,12 +20127,13 @@ class WidgetProducts extends WidgetBase {
|
|
|
19214
20127
|
}
|
|
19215
20128
|
productsView = null;
|
|
19216
20129
|
isOpen = false;
|
|
20130
|
+
isLoading = false;
|
|
19217
20131
|
get isForcePaused() {
|
|
19218
20132
|
return this.isOpen;
|
|
19219
20133
|
}
|
|
19220
20134
|
currentModels = [];
|
|
19221
20135
|
async openProductsView() {
|
|
19222
|
-
if (this.isOpen) {
|
|
20136
|
+
if (this.isOpen || this.isLoading) {
|
|
19223
20137
|
return;
|
|
19224
20138
|
}
|
|
19225
20139
|
this._statEventWidgetClick();
|
|
@@ -19229,14 +20143,10 @@ class WidgetProducts extends WidgetBase {
|
|
|
19229
20143
|
if (!this.isTransparentElement()) {
|
|
19230
20144
|
this.element.classList.add("loader");
|
|
19231
20145
|
}
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
// console.log({result})
|
|
19237
|
-
if (result.models.length > 0) {
|
|
19238
|
-
this.currentModels = result.models;
|
|
19239
|
-
this.productsView = this.createProductsView(this.currentModels, this.closeProductsView.bind(this));
|
|
20146
|
+
try {
|
|
20147
|
+
this.isLoading = true;
|
|
20148
|
+
const models = await this.getOrFetchProducts();
|
|
20149
|
+
this.productsView = this.createProductsView(models, this.closeProductsView.bind(this));
|
|
19240
20150
|
this.productsView.classList.add("ias-products-container-view--visible");
|
|
19241
20151
|
this.slide.appendChild(this.productsView);
|
|
19242
20152
|
this.element.classList.add("hidden");
|
|
@@ -19246,15 +20156,16 @@ class WidgetProducts extends WidgetBase {
|
|
|
19246
20156
|
this.widgetDeps.slideApiDeps.disableHorizontalSwipeGesture();
|
|
19247
20157
|
this.widgetDeps.slideApiDeps.disableVerticalSwipeGesture();
|
|
19248
20158
|
this.widgetDeps.slideApiDeps.disableBackpress();
|
|
19249
|
-
this._statEventWidgetOpen(
|
|
20159
|
+
this._statEventWidgetOpen(models);
|
|
19250
20160
|
this.initSwipeGestureDetector();
|
|
19251
20161
|
}
|
|
19252
|
-
|
|
19253
|
-
|
|
19254
|
-
|
|
19255
|
-
|
|
20162
|
+
catch (error) {
|
|
20163
|
+
this.widgetDeps.slideApiDeps.showToast(error.message);
|
|
20164
|
+
}
|
|
20165
|
+
finally {
|
|
20166
|
+
this.isLoading = false;
|
|
20167
|
+
this.element.classList.remove("loader");
|
|
19256
20168
|
}
|
|
19257
|
-
this.element.classList.remove("loader");
|
|
19258
20169
|
}
|
|
19259
20170
|
closeProductsView() {
|
|
19260
20171
|
if (!this.isOpen) {
|
|
@@ -19328,9 +20239,7 @@ class WidgetProducts extends WidgetBase {
|
|
|
19328
20239
|
e.stopPropagation();
|
|
19329
20240
|
e.preventDefault();
|
|
19330
20241
|
this._statEventWidgetCardClick(offer);
|
|
19331
|
-
|
|
19332
|
-
this.widgetDeps.slideApiDeps.openUrl({ type: "link", link: { type: "url", target: offer.url } });
|
|
19333
|
-
}
|
|
20242
|
+
this.showProductDetails({ offer, card });
|
|
19334
20243
|
};
|
|
19335
20244
|
card.appendChild(figure);
|
|
19336
20245
|
// card.appendChild(subTitle);
|
|
@@ -19338,6 +20247,33 @@ class WidgetProducts extends WidgetBase {
|
|
|
19338
20247
|
card.appendChild(title);
|
|
19339
20248
|
return card;
|
|
19340
20249
|
}
|
|
20250
|
+
showProductDetails = ({ card, offer }) => {
|
|
20251
|
+
if (!this.productsView)
|
|
20252
|
+
return;
|
|
20253
|
+
const backgroundView = this.slide.querySelector(".ias-products-container-background-view");
|
|
20254
|
+
const scrollViewGroup = this.slide.querySelector(".ias-products-scroll-view-group");
|
|
20255
|
+
const backgroundViewHeight = backgroundView?.clientHeight ?? 0;
|
|
20256
|
+
let scrollViewGroupHeight = scrollViewGroup?.offsetTop ?? 0;
|
|
20257
|
+
scrollViewGroupHeight = scrollViewGroupHeight > 0 ? 0 : -scrollViewGroupHeight;
|
|
20258
|
+
const bs = new ProductDetailsBottomSheet(this.widgetDeps, {
|
|
20259
|
+
translations: {
|
|
20260
|
+
color: getTagData(this.element, "msgColor") ?? "",
|
|
20261
|
+
size: getTagData(this.element, "msgSize") ?? "",
|
|
20262
|
+
addToCart: getTagData(this.element, "msgAddToCart") ?? "",
|
|
20263
|
+
successAddToCart: getTagData(this.element, "msgSuccess") ?? "",
|
|
20264
|
+
successSubAddToCart: getTagData(this.element, "msgSuccessSub") ?? "",
|
|
20265
|
+
errorAddToCart: getTagData(this.element, "msgError") ?? "",
|
|
20266
|
+
goToCartBtn: getTagData(this.element, "msgGoToCart") ?? "",
|
|
20267
|
+
continueBtn: getTagData(this.element, "msgContinue") ?? "",
|
|
20268
|
+
openUrl: getTagData(this.element, "msgOpenUrl") ?? "",
|
|
20269
|
+
},
|
|
20270
|
+
height: backgroundViewHeight + scrollViewGroupHeight,
|
|
20271
|
+
});
|
|
20272
|
+
const isCartEnabled = getTagData(this.element, "isCartEnabled") === "true";
|
|
20273
|
+
const isCartSupported = this.widgetDeps.slideApiDeps.isSdkSupportProductCart && isCartEnabled;
|
|
20274
|
+
this.productsView.appendChild(bs.render());
|
|
20275
|
+
bs.open({ offer, isCartSupported });
|
|
20276
|
+
};
|
|
19341
20277
|
createScrollView(offers) {
|
|
19342
20278
|
const scrollViewGroup = document.createElement("div");
|
|
19343
20279
|
scrollViewGroup.classList.add("ias-products-scroll-view-group");
|