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