@inappstory/slide-api 0.1.25 → 0.1.26

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.js CHANGED
@@ -1133,6 +1133,9 @@ class EsModuleSdkApi {
1133
1133
  getCardSessionValue(element, key) {
1134
1134
  return this.sdkBinding.getCardSessionValue(key);
1135
1135
  }
1136
+ isSdkSupportUpdateTimeline() {
1137
+ return true;
1138
+ }
1136
1139
  updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
1137
1140
  this.sdkBinding.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
1138
1141
  }
@@ -1177,12 +1180,75 @@ class EsModuleSdkApi {
1177
1180
  this.sdkBinding.onEvent(name, event);
1178
1181
  }
1179
1182
  onCardLoadingStateChange(state, reason) {
1180
- console.log("onCardLoadingStateChange", { state });
1183
+ // console.log("onCardLoadingStateChange", { state });
1181
1184
  this.sdkBinding.onCardLoadingStateChange(state, reason);
1182
1185
  }
1183
1186
  static get [Symbol.for("___CTOR_ARGS___")]() { return [`SDKInterface`]; }
1184
1187
  }
1185
1188
 
1189
+ class CardLoadingStateController {
1190
+ onCardLoadingStateChange;
1191
+ constructor(onCardLoadingStateChange) {
1192
+ this.onCardLoadingStateChange = onCardLoadingStateChange;
1193
+ }
1194
+ timeout = 300;
1195
+ onSetLoadStartState() {
1196
+ this.onBeforeStateChanged();
1197
+ // prevent micro loaders in UI
1198
+ if (this.currentState === 1 /* CARD_LOADING_STATE.LOADED */) {
1199
+ this.deferredDataWaitingStateTimerId = window.setTimeout(() => {
1200
+ this.onCardLoadingStateChange(0 /* CARD_LOADING_STATE.LOADING */);
1201
+ this.dataWaitingStartedAt = Date.now();
1202
+ }, this.timeout);
1203
+ }
1204
+ else {
1205
+ this.onCardLoadingStateChange(0 /* CARD_LOADING_STATE.LOADING */);
1206
+ this.dataWaitingStartedAt = Date.now();
1207
+ }
1208
+ this.currentState = 0 /* CARD_LOADING_STATE.LOADING */;
1209
+ }
1210
+ onSetLoadEndState() {
1211
+ this.onBeforeStateChanged();
1212
+ // prevent micro loaders in UI
1213
+ const delay = this.timeout;
1214
+ let dataWaitingLoaderSpent = delay;
1215
+ if (this.dataWaitingStartedAt != null) {
1216
+ dataWaitingLoaderSpent = Date.now() - this.dataWaitingStartedAt;
1217
+ }
1218
+ if (dataWaitingLoaderSpent < delay) {
1219
+ this.deferredResumeStateTimerId = window.setTimeout(() => this.onCardLoadingStateChange(1 /* CARD_LOADING_STATE.LOADED */), dataWaitingLoaderSpent - delay);
1220
+ }
1221
+ else {
1222
+ this.onCardLoadingStateChange(1 /* CARD_LOADING_STATE.LOADED */);
1223
+ }
1224
+ this.currentState = 1 /* CARD_LOADING_STATE.LOADED */;
1225
+ }
1226
+ onSetLoadErrorState(reason) {
1227
+ this.onBeforeStateChanged();
1228
+ this.onCardLoadingStateChange(2 /* CARD_LOADING_STATE.LOADING_ERROR */, reason);
1229
+ this.currentState = 2 /* CARD_LOADING_STATE.LOADING_ERROR */;
1230
+ }
1231
+ currentState = 0 /* CARD_LOADING_STATE.LOADING */;
1232
+ deferredDataWaitingStateTimerId = null;
1233
+ deferredResumeStateTimerId = null;
1234
+ dataWaitingStartedAt = null;
1235
+ clearDeferredDataWaitingStateTimerId() {
1236
+ if (this.deferredDataWaitingStateTimerId != null) {
1237
+ window.clearTimeout(this.deferredDataWaitingStateTimerId);
1238
+ }
1239
+ }
1240
+ clearDeferredResumeStateTimerId() {
1241
+ if (this.deferredResumeStateTimerId != null) {
1242
+ window.clearTimeout(this.deferredResumeStateTimerId);
1243
+ }
1244
+ }
1245
+ onBeforeStateChanged() {
1246
+ this.clearDeferredDataWaitingStateTimerId();
1247
+ this.clearDeferredResumeStateTimerId();
1248
+ }
1249
+ static get [Symbol.for("___CTOR_ARGS___")]() { return [`(state: CARD_LOADING_STATE, reason?: string) => void`]; }
1250
+ }
1251
+
1186
1252
  const DEFAULT_SLIDE_DURATION = 10000;
1187
1253
 
1188
1254
  class DataInput {
@@ -3301,19 +3367,7 @@ class SlideTimeline {
3301
3367
  return SlideTimeline.layoutService;
3302
3368
  }
3303
3369
  get isSDKSupportUpdateTimeline() {
3304
- if (this.slideApiDeps.isAndroid) {
3305
- return Boolean(SlideTimeline.layoutService.env.Android && "updateTimeline" in SlideTimeline.layoutService.env.Android);
3306
- }
3307
- else if (this.slideApiDeps.isIOS) {
3308
- const mh = SlideTimeline.layoutService.env?.webkit?.messageHandlers ?? {};
3309
- return "updateTimeline" in mh;
3310
- }
3311
- else if (this.slideApiDeps.isWeb) {
3312
- return true;
3313
- }
3314
- else {
3315
- return false;
3316
- }
3370
+ return this.slideApiDeps.isSdkSupportUpdateTimeline();
3317
3371
  }
3318
3372
  get isSdkSupportTimelineOnBeforeStart() {
3319
3373
  return this.slideApiDeps.isSdkSupportTimelineOnBeforeStart();
@@ -3458,6 +3512,7 @@ class SlideTimeline {
3458
3512
  this.onBeforeStateChanged();
3459
3513
  if (this.isSDKSupportUpdateTimeline) {
3460
3514
  this.updateTimeline("stop" /* TIMELINE_ACTION.STOP */);
3515
+ // console.log(`TIMELINE_ACTION -> slideStopped, index: ${this.slideIndex}`);
3461
3516
  }
3462
3517
  }
3463
3518
  /**
@@ -4689,7 +4744,9 @@ let SlideApi$1 = class SlideApi {
4689
4744
  this._state = 5 /* STATE.RESUMED */;
4690
4745
  }
4691
4746
  async slideStop(options) {
4692
- if (!(this._state === 3 /* STATE.STARTED */ || this._state === 5 /* STATE.RESUMED */ || this._state === 9 /* STATE.USER_PAUSED */)) {
4747
+ // console.log(`TIMELINE_ACTION -> STOP, index: ${this.slide.slideIndex}, state: ${this._state}`);
4748
+ // из состояния START (слайд (например с видео) еще не стартовал) тоже позволяем прерывать - чтобы был правильный LC при быстром пролистывании слайдера
4749
+ if (!(this._state === 2 /* STATE.START */ || this._state === 3 /* STATE.STARTED */ || this._state === 5 /* STATE.RESUMED */ || this._state === 9 /* STATE.USER_PAUSED */)) {
4693
4750
  return;
4694
4751
  }
4695
4752
  this._state = 11 /* STATE.STOP */;
@@ -5528,7 +5585,9 @@ class SlideApiDepsMultiSlideMode {
5528
5585
  return this.sdkApi.isExistsShowNextCard;
5529
5586
  }
5530
5587
  cardShowNext() {
5531
- this.sdkApi.cardShowNext();
5588
+ return;
5589
+ // skip action in multislide mode (business logic)
5590
+ // this.sdkApi.cardShowNext();
5532
5591
  }
5533
5592
  /** @deprecated, used only in native sdk **/
5534
5593
  cardPausedCallback(currentTime) {
@@ -5560,6 +5619,9 @@ class SlideApiDepsMultiSlideMode {
5560
5619
  showCardSlide(index) {
5561
5620
  this.slider.showByIndex(index);
5562
5621
  }
5622
+ isSdkSupportUpdateTimeline() {
5623
+ return true;
5624
+ }
5563
5625
  updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
5564
5626
  this.slider.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
5565
5627
  }
@@ -5710,6 +5772,9 @@ class SlideApiDepsSingleSlideMode {
5710
5772
  showCardSlide(index) {
5711
5773
  this.sdkApi.showCardSlide(index);
5712
5774
  }
5775
+ isSdkSupportUpdateTimeline() {
5776
+ return this.sdkApi.isSdkSupportUpdateTimeline();
5777
+ }
5713
5778
  updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
5714
5779
  this.sdkApi.updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError);
5715
5780
  }
@@ -5766,12 +5831,16 @@ class SlideTimer {
5766
5831
  this.timerId = null;
5767
5832
  }
5768
5833
  }
5769
- resume(duration = 0) {
5834
+ resume(currentTime = undefined, duration = 0) {
5770
5835
  this._pause = false;
5771
5836
  if (!this._started) {
5772
5837
  this.start(duration);
5773
5838
  }
5774
5839
  else {
5840
+ if (currentTime != null) {
5841
+ // timeLeft correction
5842
+ this.timeLeft = this.duration - currentTime;
5843
+ }
5775
5844
  this.tick();
5776
5845
  }
5777
5846
  }
@@ -5787,12 +5856,12 @@ class SlideTimer {
5787
5856
  }
5788
5857
  const dtDiff = new Date().getTime() - rafStartTime;
5789
5858
  this.timeLeft -= dtDiff;
5790
- let progress = Math.round(((this.duration - this.timeLeft) / this.duration) * 100 * 10000) / 10000;
5791
- if (progress > 100) {
5792
- progress = 100;
5859
+ let progressPercent = Math.round(((this.duration - this.timeLeft) / this.duration) * 100 * 10000) / 10000;
5860
+ if (progressPercent > 100) {
5861
+ progressPercent = 100;
5793
5862
  }
5794
- this.updateCb(progress);
5795
- if (progress < 100) {
5863
+ this.updateCb(progressPercent);
5864
+ if (progressPercent < 100) {
5796
5865
  if (this._pause !== true) {
5797
5866
  this.tick();
5798
5867
  }
@@ -5802,7 +5871,43 @@ class SlideTimer {
5802
5871
  }
5803
5872
  });
5804
5873
  }
5805
- static get [Symbol.for("___CTOR_ARGS___")]() { return [`(callback: () => void) => number`, `(timerId: number) => void`, `(progress: number) => void`, `() => void`]; }
5874
+ static get [Symbol.for("___CTOR_ARGS___")]() { return [`(callback: () => void) => number`, `(timerId: number) => void`, `(progressPercent: number) => void`, `() => void`]; }
5875
+ }
5876
+
5877
+ /**
5878
+ * usage TS interface with ctor
5879
+ * https://blog.logrocket.com/writing-constructor-typescript/
5880
+ *
5881
+ * @param ctor
5882
+ * @param slides
5883
+ * @param getLayoutDirection
5884
+ */
5885
+ function createTimelineController(ctor, slides, getLayoutDirection) {
5886
+ return new ctor(slides, getLayoutDirection);
5887
+ }
5888
+ class TimelineController {
5889
+ slides;
5890
+ getLayoutDirection;
5891
+ constructor(slides, getLayoutDirection) {
5892
+ this.slides = slides;
5893
+ this.getLayoutDirection = getLayoutDirection;
5894
+ }
5895
+ onSlideTimerUpdate(index, progressPercent) {
5896
+ this.slides[index]?.updateTimelineProgress(progressPercent, true);
5897
+ }
5898
+ onSlideBeforeStart(index) {
5899
+ // fill to 100% all previous slides
5900
+ for (let i = 0; i < index; ++i) {
5901
+ this.slides[i]?.updateTimelineProgress(100, false);
5902
+ }
5903
+ // fill to 0% all next slides (for user revert direction)
5904
+ for (let i = index + 1; i < this.slides.length; ++i) {
5905
+ this.slides[i]?.updateTimelineProgress(0, false);
5906
+ }
5907
+ // activate current slide
5908
+ this.slides[index]?.updateTimelineProgress(0, true);
5909
+ }
5910
+ static get [Symbol.for("___CTOR_ARGS___")]() { return [`Array`, `GetLayoutDirection`]; }
5806
5911
  }
5807
5912
 
5808
5913
  class Slider {
@@ -5824,9 +5929,11 @@ class Slider {
5824
5929
  slides: config.slides,
5825
5930
  nonce: config.nonce,
5826
5931
  slideRender: config.slideRender,
5932
+ navbarAppearance: config.navbarAppearance,
5827
5933
  });
5828
5934
  config.root.appendChild(slideWrapper);
5829
5935
  this.slideWrapperElement = slideWrapper;
5936
+ this.timelineController = createTimelineController(TimelineController, this.slides, this.config.getLayoutDirection.bind(this));
5830
5937
  // cardMounted: (card: HTMLElement) => Promise<void>
5831
5938
  requestAnimationFrame(async () => {
5832
5939
  await Promise.all(this.slides.map((slide, index) => config.onSlideMounted(slide.element, index)));
@@ -5842,44 +5949,109 @@ class Slider {
5842
5949
  bulletsContainer = null;
5843
5950
  slidesFirstRenders = [];
5844
5951
  slideWrapperElement;
5845
- updateBulletActiveIndex;
5846
- updateTimelineProgress;
5847
- createSliderElement = ({ slides, nonce, slideRender }) => {
5952
+ timelineController;
5953
+ assembleNavbarCssVariables(navbarAppearance) {
5954
+ let css = "";
5955
+ if (navbarAppearance.edge_offset != null) {
5956
+ css += `--navbar-edge-offset: ${navbarAppearance.edge_offset};`;
5957
+ }
5958
+ if (navbarAppearance.active_timeline_width != null) {
5959
+ css += `--navbar-active-timeline_width: ${navbarAppearance.active_timeline_width};`;
5960
+ }
5961
+ if (navbarAppearance.background_color != null) {
5962
+ css += `--navbar-background-color: ${navbarAppearance.background_color};`;
5963
+ }
5964
+ if (navbarAppearance.border_radius != null) {
5965
+ css += `--navbar-border-radius: ${navbarAppearance.border_radius};`;
5966
+ }
5967
+ if (navbarAppearance.drop_shadow_blur != null) {
5968
+ css += `--navbar-drop-shadow-blur: ${navbarAppearance.drop_shadow_blur};`;
5969
+ }
5970
+ if (navbarAppearance.drop_shadow_color != null) {
5971
+ css += `--navbar-drop-shadow-color: ${navbarAppearance.drop_shadow_color};`;
5972
+ }
5973
+ if (navbarAppearance.drop_shadow_x_offset != null) {
5974
+ css += `--navbar-drop-shadow-x-offset: ${navbarAppearance.drop_shadow_x_offset};`;
5975
+ }
5976
+ if (navbarAppearance.drop_shadow_y_offset != null) {
5977
+ css += `--navbar-drop-shadow-y-offset: ${navbarAppearance.drop_shadow_y_offset};`;
5978
+ }
5979
+ if (navbarAppearance.timeline_background_color != null) {
5980
+ css += `--navbar-timeline-background-color: ${navbarAppearance.timeline_background_color};`;
5981
+ }
5982
+ if (navbarAppearance.timeline_fill_color != null) {
5983
+ css += `--navbar-timeline-fill-color: ${navbarAppearance.timeline_fill_color};`;
5984
+ }
5985
+ if (navbarAppearance.timeline_size != null) {
5986
+ css += `--navbar-timeline-size: ${navbarAppearance.timeline_size};`;
5987
+ }
5988
+ if (navbarAppearance.timelines_gap != null) {
5989
+ css += `--navbar-timelines-gap: ${navbarAppearance.timelines_gap};`;
5990
+ }
5991
+ if (navbarAppearance.vertical_padding != null) {
5992
+ css += `--navbar-vertical-padding: ${navbarAppearance.vertical_padding};`;
5993
+ }
5994
+ if (navbarAppearance.horizontal_padding != null) {
5995
+ css += `--navbar-horizontal-padding: ${navbarAppearance.horizontal_padding};`;
5996
+ }
5997
+ return `.cards-slider {${css}`;
5998
+ }
5999
+ createSliderElement = ({ slides, nonce, slideRender, navbarAppearance, }) => {
5848
6000
  const style = document.createElement("style");
5849
6001
  if (nonce != null) {
5850
6002
  style.nonce = nonce;
5851
6003
  }
6004
+ style.innerText = this.assembleNavbarCssVariables(navbarAppearance);
5852
6005
  const slider = document.createElement("div");
5853
6006
  slider.classList.add("cards-slider");
5854
6007
  const track = document.createElement("div");
5855
6008
  track.classList.add("cards-slider__track");
5856
6009
  this.sliderTrack = track;
5857
- for (let i = 0; i < slides.length; ++i) {
5858
- const slide = document.createElement("div");
5859
- slide.classList.add("cards-slider__slide");
5860
- slide.setAttribute("data-index", String(i));
5861
- this.slides[i] = {
5862
- element: slideRender(slides[i], i, this.slidesFirstRenders[i].firstRenderCallPromise),
5863
- timer: new SlideTimer(cb => window.requestAnimationFrame(cb), handle => window.cancelAnimationFrame(handle), this.onSlideTimerUpdate.bind(this), this.onSlideTimerEnd.bind(this)),
5864
- };
5865
- slide.appendChild(this.slides[i].element);
5866
- track.appendChild(slide);
5867
- }
5868
- const [bullets, updateBulletActiveIndex, updateTimelineProgress] = this.createBulletPoints(slides.length);
6010
+ const [bullets, updateTimelineProgress] = this.createBulletPoints(slides.length, this.config.getLayoutDirection.bind(this), navbarAppearance.position);
5869
6011
  this.bulletsContainer = bullets;
5870
- this.updateBulletActiveIndex = updateBulletActiveIndex.bind(this);
5871
- this.updateTimelineProgress = updateTimelineProgress.bind(this);
6012
+ this.slides = slides.map((slide, i) => ({
6013
+ element: slideRender(slide, i, this.slidesFirstRenders[i].firstRenderCallPromise),
6014
+ timer: new SlideTimer(cb => window.requestAnimationFrame(cb), handle => window.cancelAnimationFrame(handle), progressPercent => this.timelineController.onSlideTimerUpdate(i, progressPercent), this.onSlideTimerEnd.bind(this)),
6015
+ updateTimelineProgress: (progressPercent, isActive) => updateTimelineProgress(i, progressPercent, isActive),
6016
+ }));
6017
+ for (let i = 0; i < this.slides.length; ++i) {
6018
+ const slideElement = document.createElement("div");
6019
+ slideElement.classList.add("cards-slider__slide");
6020
+ slideElement.setAttribute("data-index", String(i));
6021
+ slideElement.appendChild(this.slides[i].element);
6022
+ track.appendChild(slideElement);
6023
+ }
5872
6024
  slider.appendChild(track);
5873
- slider.appendChild(bullets);
6025
+ const safeAreaView = document.createElement("div");
6026
+ safeAreaView.classList.add("safe-area-view", "inset-0", "non-touchable");
6027
+ const safeAreaRelativeZoneView = document.createElement("div");
6028
+ safeAreaRelativeZoneView.classList.add("safe-area-relative-zone-view");
6029
+ safeAreaRelativeZoneView.appendChild(bullets);
6030
+ safeAreaView.appendChild(safeAreaRelativeZoneView);
6031
+ slider.appendChild(safeAreaView);
5874
6032
  slider.appendChild(style);
5875
6033
  return slider;
5876
6034
  };
5877
- createBulletPoints(count) {
6035
+ createBulletPoints(count, getLayoutDirection, position) {
5878
6036
  const bullets = document.createElement("div");
5879
- bullets.classList.toggle("cards-slider__bullets");
6037
+ bullets.classList.add("cards-slider__navbar");
6038
+ if (position === 0) {
6039
+ bullets.classList.add("cards-slider__navbar--position-none");
6040
+ }
6041
+ else if (position === 1) {
6042
+ bullets.classList.add("cards-slider__navbar--position-top");
6043
+ }
6044
+ else if (position === 2) {
6045
+ bullets.classList.add("cards-slider__navbar--position-bottom");
6046
+ }
6047
+ else {
6048
+ // default
6049
+ bullets.classList.add("cards-slider__navbar--position-bottom");
6050
+ }
6051
+ bullets.dir = getLayoutDirection();
5880
6052
  for (let i = 0; i < count; ++i) {
5881
6053
  const bullet = document.createElement("div");
5882
- bullet.classList.add("cards-slider__bullet");
6054
+ bullet.classList.add("cards-slider__timeline", "touchable");
5883
6055
  bullet.setAttribute("data-index", String(i));
5884
6056
  bullet.onclick = (e) => {
5885
6057
  e.stopPropagation();
@@ -5893,56 +6065,57 @@ class Slider {
5893
6065
  }
5894
6066
  };
5895
6067
  const bulletFill = document.createElement("div");
5896
- bulletFill.classList.add("cards-slider__bullet-fill");
6068
+ bulletFill.classList.add("cards-slider__timeline-fill");
5897
6069
  bullet.append(bulletFill);
5898
6070
  bullets.appendChild(bullet);
5899
6071
  }
5900
- const onUpdateActiveIndex = (activeIndex) => {
5901
- if (activeIndex >= 0 && activeIndex < count) {
5902
- for (const bullet of bullets.querySelectorAll(".cards-slider__bullet--active")) {
5903
- bullet.classList.toggle("cards-slider__bullet--active");
5904
- }
5905
- bullets.querySelector(`.cards-slider__bullet[data-index="${activeIndex}"]`)?.classList.toggle("cards-slider__bullet--active");
5906
- }
5907
- };
5908
- const onUpdateTimelineProgress = (index, progress) => {
6072
+ // const onUpdateActiveIndex = (activeIndex: number) => {
6073
+ // if (activeIndex >= 0 && activeIndex < count) {
6074
+ // for (const bullet of bullets.querySelectorAll(".cards-slider__bullet--active")) {
6075
+ // bullet.classList.toggle("cards-slider__bullet--active");
6076
+ // }
6077
+ // bullets.querySelector(`.cards-slider__bullet[data-index="${activeIndex}"]`)?.classList.toggle("cards-slider__bullet--active");
6078
+ // }
6079
+ // };
6080
+ const onUpdateTimelineProgress = (index, progress, isActive) => {
5909
6081
  if (index >= 0 && index < count) {
5910
- const bullet = bullets.querySelector(`.cards-slider__bullet:nth-child(${index + 1}) .cards-slider__bullet-fill`);
5911
- if (bullet != null) {
5912
- // todo RTL
5913
- //need (in css) right: 100% instead of left -100%;
6082
+ const bullet = bullets.querySelector(`.cards-slider__timeline:nth-child(${index + 1})`);
6083
+ const bulletFill = bullet?.querySelector(".cards-slider__timeline-fill");
6084
+ bullet?.classList[isActive ? "add" : "remove"]("cards-slider__timeline--active");
6085
+ if (bulletFill != null) {
5914
6086
  // todo remove progress after slide changed?
5915
- bullet.style.setProperty("transform", `translateX(${progress}%)`);
5916
- // transform: `translateZ(0) translateX(${
5917
- // index < this.$props.index
5918
- // ? "100%"
5919
- // : index === this.$props.index
5920
- // ? `${this.$props.timePercent}%`
5921
- // : "0%"
5922
- // })`,
6087
+ if (this.config.getLayoutDirection() === "rtl") {
6088
+ progress = -1 * progress;
6089
+ }
6090
+ bulletFill.style.setProperty("transform", `translateX(${progress}%)`);
5923
6091
  }
5924
6092
  }
5925
6093
  };
5926
- return [bullets, onUpdateActiveIndex, onUpdateTimelineProgress];
6094
+ return [bullets, onUpdateTimelineProgress];
5927
6095
  }
5928
6096
  async showByIndex(newIndex) {
5929
6097
  const prevIndex = this.activeIndex;
5930
6098
  if (this.isAnimating)
5931
6099
  return prevIndex;
6100
+ if (newIndex === prevIndex)
6101
+ return prevIndex;
5932
6102
  if (prevIndex !== -1) {
5933
6103
  // skip for slider start
5934
6104
  this.config.onSlideLeft(this.slides[prevIndex].element, prevIndex);
5935
- this.config.onSlideStop();
6105
+ await this.config.onSlideStop();
5936
6106
  }
5937
6107
  const { index, loadingError } = await this.initAndRenderSlide(newIndex);
5938
6108
  if (loadingError) {
5939
6109
  // todo via updateTimeline ????
5940
6110
  this.config.onSlideLoadingError(index, loadingError);
5941
6111
  }
5942
- await this.slideTo(index);
5943
6112
  if (!loadingError) {
5944
6113
  this.onShowSlide(index);
5945
6114
  }
6115
+ await this.slideTo(index);
6116
+ if (!loadingError) {
6117
+ this.config.onSlideStart();
6118
+ }
5946
6119
  return newIndex;
5947
6120
  }
5948
6121
  async showNextSlide() {
@@ -5956,17 +6129,20 @@ class Slider {
5956
6129
  if (prevIndex !== -1) {
5957
6130
  // skip for slider start
5958
6131
  this.config.onSlideLeft(this.slides[prevIndex].element, prevIndex);
5959
- this.config.onSlideStop();
6132
+ await this.config.onSlideStop();
5960
6133
  }
5961
6134
  const { index, loadingError } = await this.initAndRenderSlide(newIndex);
5962
6135
  if (loadingError) {
5963
6136
  // todo via updateTimeline ????
5964
6137
  this.config.onSlideLoadingError(index, loadingError);
5965
6138
  }
5966
- await this.slideTo(index);
5967
6139
  if (!loadingError) {
5968
6140
  this.onShowSlide(index);
5969
6141
  }
6142
+ await this.slideTo(index);
6143
+ if (!loadingError) {
6144
+ this.config.onSlideStart();
6145
+ }
5970
6146
  return newIndex;
5971
6147
  }
5972
6148
  async initAndRenderSlide(index) {
@@ -6001,9 +6177,9 @@ class Slider {
6001
6177
  }
6002
6178
  }
6003
6179
  onShowSlide(index) {
6004
- this.updateBulletActiveIndex(index);
6180
+ // this.updateBulletActiveIndex(index);
6005
6181
  this.config.onShowSlide(this.slides[index].element, index);
6006
- this.config.onSlideStart();
6182
+ // this.config.onSlideStart();
6007
6183
  }
6008
6184
  onUpdateSizeMetrics(metrics) {
6009
6185
  // this.slideTo(this.activeIndex, 0);
@@ -6063,19 +6239,32 @@ class Slider {
6063
6239
  switch (action) {
6064
6240
  case "before_start" /* TIMELINE_ACTION.BEFORE_START */: {
6065
6241
  // switch timeline to active slide and wait for start (wait VOD loading)
6066
- console.log("TIMELINE_ACTION.BEFORE_START", { activeSlide: this.activeSlide, duration });
6242
+ // console.log("TIMELINE_ACTION.BEFORE_START", { activeSlide: this.activeSlide, duration });
6243
+ this.timelineController.onSlideBeforeStart(slideIndex);
6067
6244
  break;
6068
6245
  }
6069
6246
  case "start" /* TIMELINE_ACTION.START */: {
6070
6247
  this.config.onSlideDataResume();
6071
6248
  // also start after data waiting or pause
6072
- // window.setTimeout(() => {
6073
- // this.config.onSlideStop();
6074
- // this.config.onSlideTimerEnd();
6075
- // }, 10000);
6076
6249
  // destroy on IAM closing
6077
- console.log("TIMELINE_ACTION.START", { activeSlide: this.activeSlide, index: this.activeIndex, duration });
6078
- this.activeSlide?.timer.resume(duration);
6250
+ // console.log("TIMELINE_ACTION.START", {
6251
+ // activeSlide: this.activeSlide,
6252
+ // index: this.activeIndex,
6253
+ // duration,
6254
+ // });
6255
+ let resumeTimer = false;
6256
+ if (duration > 0) {
6257
+ // skip timer start for slide/layer with disabled timeline
6258
+ resumeTimer = true;
6259
+ }
6260
+ if (currentTime === duration) {
6261
+ // skip timer start for already ended layer timeline
6262
+ // skip timer start for already ended layer timeline
6263
+ resumeTimer = false;
6264
+ }
6265
+ if (resumeTimer) {
6266
+ this.activeSlide?.timer.resume(currentTime, duration);
6267
+ }
6079
6268
  break;
6080
6269
  }
6081
6270
  case "pause" /* TIMELINE_ACTION.PAUSE */: {
@@ -6083,7 +6272,7 @@ class Slider {
6083
6272
  this.config.onSlideDataWaiting();
6084
6273
  }
6085
6274
  this.activeSlide?.timer.pause();
6086
- console.log("TIMELINE_ACTION.PAUSE", { activeSlide: this.activeSlide, duration });
6275
+ // console.log("TIMELINE_ACTION.PAUSE", { activeSlide: this.activeSlide, duration });
6087
6276
  break;
6088
6277
  }
6089
6278
  case "stop" /* TIMELINE_ACTION.STOP */: {
@@ -6093,27 +6282,23 @@ class Slider {
6093
6282
  }
6094
6283
  this.activeSlide?.timer.stop();
6095
6284
  // todo нужен STOP когда вручную переключаем слайд на другой
6096
- console.log("TIMELINE_ACTION.STOP", { activeSlide: this.activeSlide, duration });
6285
+ // console.log("TIMELINE_ACTION.STOP", { activeSlide: this.activeSlide, duration });
6097
6286
  break;
6098
6287
  }
6099
6288
  }
6100
6289
  }
6101
- onSlideTimerUpdate(progress) {
6102
- this.updateTimelineProgress(this.activeIndex, progress);
6103
- }
6104
- onSlideTimerEnd() {
6105
- this.config.onSlideStop();
6290
+ // private onSlideTimerUpdate(progress: number) {
6291
+ // this.updateTimelineProgress(this.activeIndex, progress);
6292
+ // }
6293
+ async onSlideTimerEnd() {
6294
+ await this.config.onSlideStop();
6106
6295
  this.config.onSlideTimerEnd();
6107
6296
  }
6108
6297
  static get [Symbol.for("___CTOR_ARGS___")]() { return [`{
6109
6298
  slides: Array<T>;
6110
6299
  root: HTMLElement;
6111
- // isFullscreen: boolean;
6112
6300
  nonce?: string;
6113
- // viewport: Window;
6114
- // userResizeHandler?: (data: { viewportWidth: number; viewportHeight: number; fontSize: number }) => void;
6115
- // VODPlayer?: typeof VODPlayer;
6116
- // overlappingActionBarHeight?: number;
6301
+ navbarAppearance: NavbarAppearance;
6117
6302
  slideRender: SlideRender<T>;
6118
6303
  onSlideMounted: OnSlideMounted;
6119
6304
  onBeforeShowSlide: OnBeforeShowSlide;
@@ -6150,6 +6335,7 @@ class CardApi {
6150
6335
  activeSlide = null;
6151
6336
  slides = [];
6152
6337
  slidesMode = 0 /* SLIDES_MODE.SINGLE */;
6338
+ cardLoadingStateController = null;
6153
6339
  sizeMetrics = {
6154
6340
  fontSize: "0px",
6155
6341
  isFullscreen: false,
@@ -6325,7 +6511,10 @@ class CardApi {
6325
6511
  slider = null;
6326
6512
  async showSlides(slides, cardAppearance, index = 0) {
6327
6513
  this.slidesMode = 1 /* SLIDES_MODE.MULTIPLE */;
6328
- this.sdkApi.onCardLoadingStateChange(0 /* CARD_LOADING_STATE.LOADING */);
6514
+ if (this.cardLoadingStateController === null) {
6515
+ this.cardLoadingStateController = new CardLoadingStateController(this.sdkApi.onCardLoadingStateChange.bind(this.sdkApi));
6516
+ }
6517
+ this.cardLoadingStateController.onSetLoadStartState();
6329
6518
  slides.forEach((content, index) => {
6330
6519
  if (this.slides[index] == null) {
6331
6520
  const item = { content, resourcesReadyPromise: null };
@@ -6378,6 +6567,15 @@ class CardApi {
6378
6567
  this.activeSlide = this.slides[index].slide;
6379
6568
  return this.slides[index].slide.showSlide().then(_ => ({ moveToIndex: index }));
6380
6569
  }
6570
+ else {
6571
+ // quot - // TODO для виджета квест нужно при каждом показе слайда инициализировать виджет???
6572
+ // // пока вызов убран из за того что init жестко завязан на single slide mode
6573
+ // из-за того что перед показом нет приватного вызова SlideApi::_init пока что нужно руками вызывать
6574
+ // slide.activeLayer.timeline.triggerSlideLoadState();
6575
+ // для того чтобы запустить TIMELINE_ACTION.BEFORE_START что нужно для таймлайна слайдера
6576
+ // todo убрать в случае если будем вызывать new SlideApi перед каждым показом слайда
6577
+ this.slides[index].slide.activeLayer.timeline.triggerSlideLoadState();
6578
+ }
6381
6579
  this.activeSlide = this.slides[index].slide;
6382
6580
  // TODO handle moveToIndex
6383
6581
  // return resolve or reject with reason
@@ -6391,13 +6589,13 @@ class CardApi {
6391
6589
  // внутри слайдера - обрабатываем moveToIndex
6392
6590
  };
6393
6591
  const onBeforeLoadSlide = index => {
6394
- this.sdkApi.onCardLoadingStateChange(0 /* CARD_LOADING_STATE.LOADING */);
6592
+ this.cardLoadingStateController.onSetLoadStartState();
6395
6593
  };
6396
6594
  const onSlideLoadingError = (index, reason) => {
6397
- this.sdkApi.onCardLoadingStateChange(2 /* CARD_LOADING_STATE.LOADING_ERROR */, reason);
6595
+ this.cardLoadingStateController.onSetLoadErrorState(reason);
6398
6596
  };
6399
6597
  const onShowSlide = (slide, index) => {
6400
- this.sdkApi.onCardLoadingStateChange(1 /* CARD_LOADING_STATE.LOADED */);
6598
+ this.cardLoadingStateController.onSetLoadEndState();
6401
6599
  this.sdkApi.emitEvent("showSlide", { cardId: this.slides[index]?.slide?.slide.cardId ?? 0, index });
6402
6600
  // if (index === 0) {
6403
6601
  // this.activeSlide = slideApi;
@@ -6489,6 +6687,7 @@ class CardApi {
6489
6687
  canMediaMount: resourcesReadyPromise,
6490
6688
  })),
6491
6689
  nonce: this.config.nonce,
6690
+ navbarAppearance: cardAppearance.navbar ?? {},
6492
6691
  slideRender,
6493
6692
  onSlideMounted,
6494
6693
  onBeforeShowSlide,
@@ -6499,13 +6698,14 @@ class CardApi {
6499
6698
  getLayoutDirection: () => this.layoutDirection,
6500
6699
  onSlideTimerEnd: () => this.activeSlide.slideTimerEnd(),
6501
6700
  onSlideStart: () => {
6502
- this.sdkApi.onCardLoadingStateChange(1 /* CARD_LOADING_STATE.LOADED */);
6701
+ // return Promise.resolve({currentTime: 0});
6702
+ this.cardLoadingStateController.onSetLoadEndState();
6503
6703
  return this.activeSlide.slideStart({ muted: true });
6504
6704
  },
6505
6705
  onSlideStop: () => this.activeSlide.slideStop({ prepareForRestart: 1 /* ON_SLIDE_STOP_PREPARE_FOR_RESTART.PREPARE */ }),
6506
- onSlideDataWaiting: () => this.sdkApi.onCardLoadingStateChange(0 /* CARD_LOADING_STATE.LOADING */),
6507
- onSlideDataResume: () => this.sdkApi.onCardLoadingStateChange(1 /* CARD_LOADING_STATE.LOADED */),
6508
- onSlideDataError: () => this.sdkApi.onCardLoadingStateChange(2 /* CARD_LOADING_STATE.LOADING_ERROR */),
6706
+ onSlideDataWaiting: () => this.cardLoadingStateController.onSetLoadStartState(),
6707
+ onSlideDataResume: () => this.cardLoadingStateController.onSetLoadEndState(),
6708
+ onSlideDataError: () => this.cardLoadingStateController.onSetLoadEndState(),
6509
6709
  });
6510
6710
  await this.slider.showByIndex(index);
6511
6711
  // return await onShowActiveCard;
@@ -6579,6 +6779,15 @@ class CardApi {
6579
6779
  if (this.slidesMode === 1 /* SLIDES_MODE.MULTIPLE */ && result.canClickNext) {
6580
6780
  result.canClickNext = false; // handle nav click via CardsSlider, not via SDK
6581
6781
  const currentIndex = this.activeSlide.index;
6782
+ /**
6783
+ * business logic - avoid action on side slides click
6784
+ */
6785
+ if (currentIndex === 0 && navigationDirection === "backward") {
6786
+ return result;
6787
+ }
6788
+ if (currentIndex === this.slides.length - 1 && navigationDirection === "forward") {
6789
+ return result;
6790
+ }
6582
6791
  let index = navigationDirection === "forward" ? currentIndex + 1 : currentIndex - 1;
6583
6792
  if (index >= this.slides.length) {
6584
6793
  index = 0;