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