react-riyils 1.0.1 → 2.0.0

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.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, useState, useRef, useEffect, createContext, useLayoutEffect, createElement as createElement$1 } from 'react';
1
+ import React, { forwardRef, useState, useRef, useEffect, createContext, useLayoutEffect, createElement as createElement$1, useMemo, useCallback } from 'react';
2
2
 
3
3
  /**
4
4
  * SSR Window 5.0.1
@@ -428,9 +428,6 @@ function elementOuterSize(el, size, includeMargins) {
428
428
  return el[size === 'width' ? 'offsetWidth' : 'offsetHeight'] + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-right' : 'margin-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-left' : 'margin-bottom'));
429
429
  }
430
430
  }
431
- function makeElementsArray(el) {
432
- return (Array.isArray(el) ? el : [el]).filter(e => !!e);
433
- }
434
431
  function getRotateFix(swiper) {
435
432
  return v => {
436
433
  if (Math.abs(v) > 0 && swiper.browser && swiper.browser.need3dFix && Math.abs(v) % 90 === 0) {
@@ -5030,6 +5027,366 @@ const SwiperSlide = /*#__PURE__*/forwardRef(({
5030
5027
  });
5031
5028
  SwiperSlide.displayName = 'SwiperSlide';
5032
5029
 
5030
+ function Virtual({
5031
+ swiper,
5032
+ extendParams,
5033
+ on,
5034
+ emit
5035
+ }) {
5036
+ extendParams({
5037
+ virtual: {
5038
+ enabled: false,
5039
+ slides: [],
5040
+ cache: true,
5041
+ slidesPerViewAutoSlideSize: 320,
5042
+ renderSlide: null,
5043
+ renderExternal: null,
5044
+ renderExternalUpdate: true,
5045
+ addSlidesBefore: 0,
5046
+ addSlidesAfter: 0
5047
+ }
5048
+ });
5049
+ let cssModeTimeout;
5050
+ const document = getDocument();
5051
+ swiper.virtual = {
5052
+ cache: {},
5053
+ from: undefined,
5054
+ to: undefined,
5055
+ slides: [],
5056
+ offset: 0,
5057
+ slidesGrid: []
5058
+ };
5059
+ const tempDOM = document.createElement('div');
5060
+ function renderSlide(slide, index) {
5061
+ const params = swiper.params.virtual;
5062
+ if (params.cache && swiper.virtual.cache[index]) {
5063
+ return swiper.virtual.cache[index];
5064
+ }
5065
+ // eslint-disable-next-line
5066
+ let slideEl;
5067
+ if (params.renderSlide) {
5068
+ slideEl = params.renderSlide.call(swiper, slide, index);
5069
+ if (typeof slideEl === 'string') {
5070
+ setInnerHTML(tempDOM, slideEl);
5071
+ slideEl = tempDOM.children[0];
5072
+ }
5073
+ } else if (swiper.isElement) {
5074
+ slideEl = createElement('swiper-slide');
5075
+ } else {
5076
+ slideEl = createElement('div', swiper.params.slideClass);
5077
+ }
5078
+ slideEl.setAttribute('data-swiper-slide-index', index);
5079
+ if (!params.renderSlide) {
5080
+ setInnerHTML(slideEl, slide);
5081
+ }
5082
+ if (params.cache) {
5083
+ swiper.virtual.cache[index] = slideEl;
5084
+ }
5085
+ return slideEl;
5086
+ }
5087
+ function update(force, beforeInit, forceActiveIndex) {
5088
+ const {
5089
+ slidesPerGroup,
5090
+ centeredSlides,
5091
+ slidesPerView,
5092
+ loop: isLoop,
5093
+ initialSlide
5094
+ } = swiper.params;
5095
+ if (beforeInit && !isLoop && initialSlide > 0) {
5096
+ return;
5097
+ }
5098
+ const {
5099
+ addSlidesBefore,
5100
+ addSlidesAfter,
5101
+ slidesPerViewAutoSlideSize
5102
+ } = swiper.params.virtual;
5103
+ const {
5104
+ from: previousFrom,
5105
+ to: previousTo,
5106
+ slides,
5107
+ slidesGrid: previousSlidesGrid,
5108
+ offset: previousOffset
5109
+ } = swiper.virtual;
5110
+ if (!swiper.params.cssMode) {
5111
+ swiper.updateActiveIndex();
5112
+ }
5113
+ const activeIndex = typeof forceActiveIndex === 'undefined' ? swiper.activeIndex || 0 : forceActiveIndex;
5114
+ let offsetProp;
5115
+ if (swiper.rtlTranslate) offsetProp = 'right';else offsetProp = swiper.isHorizontal() ? 'left' : 'top';
5116
+ let slidesPerViewNumeric;
5117
+ if (slidesPerView === 'auto') {
5118
+ if (slidesPerViewAutoSlideSize) {
5119
+ let swiperSize = swiper.size;
5120
+ if (!swiperSize) {
5121
+ swiperSize = swiper.isHorizontal() ? swiper.el.getBoundingClientRect().width : swiper.el.getBoundingClientRect().height;
5122
+ }
5123
+ slidesPerViewNumeric = Math.max(1, Math.ceil(swiperSize / slidesPerViewAutoSlideSize));
5124
+ } else {
5125
+ slidesPerViewNumeric = 1;
5126
+ }
5127
+ } else {
5128
+ slidesPerViewNumeric = slidesPerView;
5129
+ }
5130
+ let slidesAfter;
5131
+ let slidesBefore;
5132
+ if (centeredSlides) {
5133
+ slidesAfter = Math.floor(slidesPerViewNumeric / 2) + slidesPerGroup + addSlidesAfter;
5134
+ slidesBefore = Math.floor(slidesPerViewNumeric / 2) + slidesPerGroup + addSlidesBefore;
5135
+ } else {
5136
+ slidesAfter = slidesPerViewNumeric + (slidesPerGroup - 1) + addSlidesAfter;
5137
+ slidesBefore = (isLoop ? slidesPerViewNumeric : slidesPerGroup) + addSlidesBefore;
5138
+ }
5139
+ let from = activeIndex - slidesBefore;
5140
+ let to = activeIndex + slidesAfter;
5141
+ if (!isLoop) {
5142
+ from = Math.max(from, 0);
5143
+ to = Math.min(to, slides.length - 1);
5144
+ }
5145
+ let offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);
5146
+ if (isLoop && activeIndex >= slidesBefore) {
5147
+ from -= slidesBefore;
5148
+ if (!centeredSlides) offset += swiper.slidesGrid[0];
5149
+ } else if (isLoop && activeIndex < slidesBefore) {
5150
+ from = -slidesBefore;
5151
+ if (centeredSlides) offset += swiper.slidesGrid[0];
5152
+ }
5153
+ Object.assign(swiper.virtual, {
5154
+ from,
5155
+ to,
5156
+ offset,
5157
+ slidesGrid: swiper.slidesGrid,
5158
+ slidesBefore,
5159
+ slidesAfter
5160
+ });
5161
+ function onRendered() {
5162
+ swiper.updateSlides();
5163
+ swiper.updateProgress();
5164
+ swiper.updateSlidesClasses();
5165
+ emit('virtualUpdate');
5166
+ }
5167
+ if (previousFrom === from && previousTo === to && !force) {
5168
+ if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
5169
+ swiper.slides.forEach(slideEl => {
5170
+ slideEl.style[offsetProp] = `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`;
5171
+ });
5172
+ }
5173
+ swiper.updateProgress();
5174
+ emit('virtualUpdate');
5175
+ return;
5176
+ }
5177
+ if (swiper.params.virtual.renderExternal) {
5178
+ swiper.params.virtual.renderExternal.call(swiper, {
5179
+ offset,
5180
+ from,
5181
+ to,
5182
+ slides: function getSlides() {
5183
+ const slidesToRender = [];
5184
+ for (let i = from; i <= to; i += 1) {
5185
+ slidesToRender.push(slides[i]);
5186
+ }
5187
+ return slidesToRender;
5188
+ }()
5189
+ });
5190
+ if (swiper.params.virtual.renderExternalUpdate) {
5191
+ onRendered();
5192
+ } else {
5193
+ emit('virtualUpdate');
5194
+ }
5195
+ return;
5196
+ }
5197
+ const prependIndexes = [];
5198
+ const appendIndexes = [];
5199
+ const getSlideIndex = index => {
5200
+ let slideIndex = index;
5201
+ if (index < 0) {
5202
+ slideIndex = slides.length + index;
5203
+ } else if (slideIndex >= slides.length) {
5204
+ // eslint-disable-next-line
5205
+ slideIndex = slideIndex - slides.length;
5206
+ }
5207
+ return slideIndex;
5208
+ };
5209
+ if (force) {
5210
+ swiper.slides.filter(el => el.matches(`.${swiper.params.slideClass}, swiper-slide`)).forEach(slideEl => {
5211
+ slideEl.remove();
5212
+ });
5213
+ } else {
5214
+ for (let i = previousFrom; i <= previousTo; i += 1) {
5215
+ if (i < from || i > to) {
5216
+ const slideIndex = getSlideIndex(i);
5217
+ swiper.slides.filter(el => el.matches(`.${swiper.params.slideClass}[data-swiper-slide-index="${slideIndex}"], swiper-slide[data-swiper-slide-index="${slideIndex}"]`)).forEach(slideEl => {
5218
+ slideEl.remove();
5219
+ });
5220
+ }
5221
+ }
5222
+ }
5223
+ const loopFrom = isLoop ? -slides.length : 0;
5224
+ const loopTo = isLoop ? slides.length * 2 : slides.length;
5225
+ for (let i = loopFrom; i < loopTo; i += 1) {
5226
+ if (i >= from && i <= to) {
5227
+ const slideIndex = getSlideIndex(i);
5228
+ if (typeof previousTo === 'undefined' || force) {
5229
+ appendIndexes.push(slideIndex);
5230
+ } else {
5231
+ if (i > previousTo) appendIndexes.push(slideIndex);
5232
+ if (i < previousFrom) prependIndexes.push(slideIndex);
5233
+ }
5234
+ }
5235
+ }
5236
+ appendIndexes.forEach(index => {
5237
+ swiper.slidesEl.append(renderSlide(slides[index], index));
5238
+ });
5239
+ if (isLoop) {
5240
+ for (let i = prependIndexes.length - 1; i >= 0; i -= 1) {
5241
+ const index = prependIndexes[i];
5242
+ swiper.slidesEl.prepend(renderSlide(slides[index], index));
5243
+ }
5244
+ } else {
5245
+ prependIndexes.sort((a, b) => b - a);
5246
+ prependIndexes.forEach(index => {
5247
+ swiper.slidesEl.prepend(renderSlide(slides[index], index));
5248
+ });
5249
+ }
5250
+ elementChildren(swiper.slidesEl, '.swiper-slide, swiper-slide').forEach(slideEl => {
5251
+ slideEl.style[offsetProp] = `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`;
5252
+ });
5253
+ onRendered();
5254
+ }
5255
+ function appendSlide(slides) {
5256
+ if (typeof slides === 'object' && 'length' in slides) {
5257
+ for (let i = 0; i < slides.length; i += 1) {
5258
+ if (slides[i]) swiper.virtual.slides.push(slides[i]);
5259
+ }
5260
+ } else {
5261
+ swiper.virtual.slides.push(slides);
5262
+ }
5263
+ update(true);
5264
+ }
5265
+ function prependSlide(slides) {
5266
+ const activeIndex = swiper.activeIndex;
5267
+ let newActiveIndex = activeIndex + 1;
5268
+ let numberOfNewSlides = 1;
5269
+ if (Array.isArray(slides)) {
5270
+ for (let i = 0; i < slides.length; i += 1) {
5271
+ if (slides[i]) swiper.virtual.slides.unshift(slides[i]);
5272
+ }
5273
+ newActiveIndex = activeIndex + slides.length;
5274
+ numberOfNewSlides = slides.length;
5275
+ } else {
5276
+ swiper.virtual.slides.unshift(slides);
5277
+ }
5278
+ if (swiper.params.virtual.cache) {
5279
+ const cache = swiper.virtual.cache;
5280
+ const newCache = {};
5281
+ Object.keys(cache).forEach(cachedIndex => {
5282
+ const cachedEl = cache[cachedIndex];
5283
+ const cachedElIndex = cachedEl.getAttribute('data-swiper-slide-index');
5284
+ if (cachedElIndex) {
5285
+ cachedEl.setAttribute('data-swiper-slide-index', parseInt(cachedElIndex, 10) + numberOfNewSlides);
5286
+ }
5287
+ newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = cachedEl;
5288
+ });
5289
+ swiper.virtual.cache = newCache;
5290
+ }
5291
+ update(true);
5292
+ swiper.slideTo(newActiveIndex, 0);
5293
+ }
5294
+ function removeSlide(slidesIndexes) {
5295
+ if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) return;
5296
+ let activeIndex = swiper.activeIndex;
5297
+ if (Array.isArray(slidesIndexes)) {
5298
+ for (let i = slidesIndexes.length - 1; i >= 0; i -= 1) {
5299
+ if (swiper.params.virtual.cache) {
5300
+ delete swiper.virtual.cache[slidesIndexes[i]];
5301
+ // shift cache indexes
5302
+ Object.keys(swiper.virtual.cache).forEach(key => {
5303
+ if (key > slidesIndexes) {
5304
+ swiper.virtual.cache[key - 1] = swiper.virtual.cache[key];
5305
+ swiper.virtual.cache[key - 1].setAttribute('data-swiper-slide-index', key - 1);
5306
+ delete swiper.virtual.cache[key];
5307
+ }
5308
+ });
5309
+ }
5310
+ swiper.virtual.slides.splice(slidesIndexes[i], 1);
5311
+ if (slidesIndexes[i] < activeIndex) activeIndex -= 1;
5312
+ activeIndex = Math.max(activeIndex, 0);
5313
+ }
5314
+ } else {
5315
+ if (swiper.params.virtual.cache) {
5316
+ delete swiper.virtual.cache[slidesIndexes];
5317
+ // shift cache indexes
5318
+ Object.keys(swiper.virtual.cache).forEach(key => {
5319
+ if (key > slidesIndexes) {
5320
+ swiper.virtual.cache[key - 1] = swiper.virtual.cache[key];
5321
+ swiper.virtual.cache[key - 1].setAttribute('data-swiper-slide-index', key - 1);
5322
+ delete swiper.virtual.cache[key];
5323
+ }
5324
+ });
5325
+ }
5326
+ swiper.virtual.slides.splice(slidesIndexes, 1);
5327
+ if (slidesIndexes < activeIndex) activeIndex -= 1;
5328
+ activeIndex = Math.max(activeIndex, 0);
5329
+ }
5330
+ update(true);
5331
+ swiper.slideTo(activeIndex, 0);
5332
+ }
5333
+ function removeAllSlides() {
5334
+ swiper.virtual.slides = [];
5335
+ if (swiper.params.virtual.cache) {
5336
+ swiper.virtual.cache = {};
5337
+ }
5338
+ update(true);
5339
+ swiper.slideTo(0, 0);
5340
+ }
5341
+ on('beforeInit', () => {
5342
+ if (!swiper.params.virtual.enabled) return;
5343
+ let domSlidesAssigned;
5344
+ if (typeof swiper.passedParams.virtual.slides === 'undefined') {
5345
+ const slides = [...swiper.slidesEl.children].filter(el => el.matches(`.${swiper.params.slideClass}, swiper-slide`));
5346
+ if (slides && slides.length) {
5347
+ swiper.virtual.slides = [...slides];
5348
+ domSlidesAssigned = true;
5349
+ slides.forEach((slideEl, slideIndex) => {
5350
+ slideEl.setAttribute('data-swiper-slide-index', slideIndex);
5351
+ swiper.virtual.cache[slideIndex] = slideEl;
5352
+ slideEl.remove();
5353
+ });
5354
+ }
5355
+ }
5356
+ if (!domSlidesAssigned) {
5357
+ swiper.virtual.slides = swiper.params.virtual.slides;
5358
+ }
5359
+ swiper.classNames.push(`${swiper.params.containerModifierClass}virtual`);
5360
+ swiper.params.watchSlidesProgress = true;
5361
+ swiper.originalParams.watchSlidesProgress = true;
5362
+ update(false, true);
5363
+ });
5364
+ on('setTranslate', () => {
5365
+ if (!swiper.params.virtual.enabled) return;
5366
+ if (swiper.params.cssMode && !swiper._immediateVirtual) {
5367
+ clearTimeout(cssModeTimeout);
5368
+ cssModeTimeout = setTimeout(() => {
5369
+ update();
5370
+ }, 100);
5371
+ } else {
5372
+ update();
5373
+ }
5374
+ });
5375
+ on('init update resize', () => {
5376
+ if (!swiper.params.virtual.enabled) return;
5377
+ if (swiper.params.cssMode) {
5378
+ setCSSProperty(swiper.wrapperEl, '--swiper-virtual-size', `${swiper.virtualSize}px`);
5379
+ }
5380
+ });
5381
+ Object.assign(swiper.virtual, {
5382
+ appendSlide,
5383
+ prependSlide,
5384
+ removeSlide,
5385
+ removeAllSlides,
5386
+ update
5387
+ });
5388
+ }
5389
+
5033
5390
  /* eslint-disable consistent-return */
5034
5391
  function Keyboard({
5035
5392
  swiper,
@@ -5532,228 +5889,6 @@ function Mousewheel({
5532
5889
  });
5533
5890
  }
5534
5891
 
5535
- function createElementIfNotDefined(swiper, originalParams, params, checkProps) {
5536
- if (swiper.params.createElements) {
5537
- Object.keys(checkProps).forEach(key => {
5538
- if (!params[key] && params.auto === true) {
5539
- let element = elementChildren(swiper.el, `.${checkProps[key]}`)[0];
5540
- if (!element) {
5541
- element = createElement('div', checkProps[key]);
5542
- element.className = checkProps[key];
5543
- swiper.el.append(element);
5544
- }
5545
- params[key] = element;
5546
- originalParams[key] = element;
5547
- }
5548
- });
5549
- }
5550
- return params;
5551
- }
5552
-
5553
- const arrowSvg = `<svg class="swiper-navigation-icon" width="11" height="20" viewBox="0 0 11 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.38296 20.0762C0.111788 19.805 0.111788 19.3654 0.38296 19.0942L9.19758 10.2796L0.38296 1.46497C0.111788 1.19379 0.111788 0.754138 0.38296 0.482966C0.654131 0.211794 1.09379 0.211794 1.36496 0.482966L10.4341 9.55214C10.8359 9.9539 10.8359 10.6053 10.4341 11.007L1.36496 20.0762C1.09379 20.3474 0.654131 20.3474 0.38296 20.0762Z" fill="currentColor"/></svg>`;
5554
- function Navigation({
5555
- swiper,
5556
- extendParams,
5557
- on,
5558
- emit
5559
- }) {
5560
- extendParams({
5561
- navigation: {
5562
- nextEl: null,
5563
- prevEl: null,
5564
- addIcons: true,
5565
- hideOnClick: false,
5566
- disabledClass: 'swiper-button-disabled',
5567
- hiddenClass: 'swiper-button-hidden',
5568
- lockClass: 'swiper-button-lock',
5569
- navigationDisabledClass: 'swiper-navigation-disabled'
5570
- }
5571
- });
5572
- swiper.navigation = {
5573
- nextEl: null,
5574
- prevEl: null,
5575
- arrowSvg
5576
- };
5577
- function getEl(el) {
5578
- let res;
5579
- if (el && typeof el === 'string' && swiper.isElement) {
5580
- res = swiper.el.querySelector(el) || swiper.hostEl.querySelector(el);
5581
- if (res) return res;
5582
- }
5583
- if (el) {
5584
- if (typeof el === 'string') res = [...document.querySelectorAll(el)];
5585
- if (swiper.params.uniqueNavElements && typeof el === 'string' && res && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
5586
- res = swiper.el.querySelector(el);
5587
- } else if (res && res.length === 1) {
5588
- res = res[0];
5589
- }
5590
- }
5591
- if (el && !res) return el;
5592
- // if (Array.isArray(res) && res.length === 1) res = res[0];
5593
- return res;
5594
- }
5595
- function toggleEl(el, disabled) {
5596
- const params = swiper.params.navigation;
5597
- el = makeElementsArray(el);
5598
- el.forEach(subEl => {
5599
- if (subEl) {
5600
- subEl.classList[disabled ? 'add' : 'remove'](...params.disabledClass.split(' '));
5601
- if (subEl.tagName === 'BUTTON') subEl.disabled = disabled;
5602
- if (swiper.params.watchOverflow && swiper.enabled) {
5603
- subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass);
5604
- }
5605
- }
5606
- });
5607
- }
5608
- function update() {
5609
- // Update Navigation Buttons
5610
- const {
5611
- nextEl,
5612
- prevEl
5613
- } = swiper.navigation;
5614
- if (swiper.params.loop) {
5615
- toggleEl(prevEl, false);
5616
- toggleEl(nextEl, false);
5617
- return;
5618
- }
5619
- toggleEl(prevEl, swiper.isBeginning && !swiper.params.rewind);
5620
- toggleEl(nextEl, swiper.isEnd && !swiper.params.rewind);
5621
- }
5622
- function onPrevClick(e) {
5623
- e.preventDefault();
5624
- if (swiper.isBeginning && !swiper.params.loop && !swiper.params.rewind) return;
5625
- swiper.slidePrev();
5626
- emit('navigationPrev');
5627
- }
5628
- function onNextClick(e) {
5629
- e.preventDefault();
5630
- if (swiper.isEnd && !swiper.params.loop && !swiper.params.rewind) return;
5631
- swiper.slideNext();
5632
- emit('navigationNext');
5633
- }
5634
- function init() {
5635
- const params = swiper.params.navigation;
5636
- swiper.params.navigation = createElementIfNotDefined(swiper, swiper.originalParams.navigation, swiper.params.navigation, {
5637
- nextEl: 'swiper-button-next',
5638
- prevEl: 'swiper-button-prev'
5639
- });
5640
- if (!(params.nextEl || params.prevEl)) return;
5641
- let nextEl = getEl(params.nextEl);
5642
- let prevEl = getEl(params.prevEl);
5643
- Object.assign(swiper.navigation, {
5644
- nextEl,
5645
- prevEl
5646
- });
5647
- nextEl = makeElementsArray(nextEl);
5648
- prevEl = makeElementsArray(prevEl);
5649
- const initButton = (el, dir) => {
5650
- if (el) {
5651
- if (params.addIcons && el.matches('.swiper-button-next,.swiper-button-prev') && !el.querySelector('svg')) {
5652
- const tempEl = document.createElement('div');
5653
- setInnerHTML(tempEl, arrowSvg);
5654
- el.appendChild(tempEl.querySelector('svg'));
5655
- tempEl.remove();
5656
- }
5657
- el.addEventListener('click', dir === 'next' ? onNextClick : onPrevClick);
5658
- }
5659
- if (!swiper.enabled && el) {
5660
- el.classList.add(...params.lockClass.split(' '));
5661
- }
5662
- };
5663
- nextEl.forEach(el => initButton(el, 'next'));
5664
- prevEl.forEach(el => initButton(el, 'prev'));
5665
- }
5666
- function destroy() {
5667
- let {
5668
- nextEl,
5669
- prevEl
5670
- } = swiper.navigation;
5671
- nextEl = makeElementsArray(nextEl);
5672
- prevEl = makeElementsArray(prevEl);
5673
- const destroyButton = (el, dir) => {
5674
- el.removeEventListener('click', dir === 'next' ? onNextClick : onPrevClick);
5675
- el.classList.remove(...swiper.params.navigation.disabledClass.split(' '));
5676
- };
5677
- nextEl.forEach(el => destroyButton(el, 'next'));
5678
- prevEl.forEach(el => destroyButton(el, 'prev'));
5679
- }
5680
- on('init', () => {
5681
- if (swiper.params.navigation.enabled === false) {
5682
- // eslint-disable-next-line
5683
- disable();
5684
- } else {
5685
- init();
5686
- update();
5687
- }
5688
- });
5689
- on('toEdge fromEdge lock unlock', () => {
5690
- update();
5691
- });
5692
- on('destroy', () => {
5693
- destroy();
5694
- });
5695
- on('enable disable', () => {
5696
- let {
5697
- nextEl,
5698
- prevEl
5699
- } = swiper.navigation;
5700
- nextEl = makeElementsArray(nextEl);
5701
- prevEl = makeElementsArray(prevEl);
5702
- if (swiper.enabled) {
5703
- update();
5704
- return;
5705
- }
5706
- [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.add(swiper.params.navigation.lockClass));
5707
- });
5708
- on('click', (_s, e) => {
5709
- let {
5710
- nextEl,
5711
- prevEl
5712
- } = swiper.navigation;
5713
- nextEl = makeElementsArray(nextEl);
5714
- prevEl = makeElementsArray(prevEl);
5715
- const targetEl = e.target;
5716
- let targetIsButton = prevEl.includes(targetEl) || nextEl.includes(targetEl);
5717
- if (swiper.isElement && !targetIsButton) {
5718
- const path = e.path || e.composedPath && e.composedPath();
5719
- if (path) {
5720
- targetIsButton = path.find(pathEl => nextEl.includes(pathEl) || prevEl.includes(pathEl));
5721
- }
5722
- }
5723
- if (swiper.params.navigation.hideOnClick && !targetIsButton) {
5724
- if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
5725
- let isHidden;
5726
- if (nextEl.length) {
5727
- isHidden = nextEl[0].classList.contains(swiper.params.navigation.hiddenClass);
5728
- } else if (prevEl.length) {
5729
- isHidden = prevEl[0].classList.contains(swiper.params.navigation.hiddenClass);
5730
- }
5731
- if (isHidden === true) {
5732
- emit('navigationShow');
5733
- } else {
5734
- emit('navigationHide');
5735
- }
5736
- [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.toggle(swiper.params.navigation.hiddenClass));
5737
- }
5738
- });
5739
- const enable = () => {
5740
- swiper.el.classList.remove(...swiper.params.navigation.navigationDisabledClass.split(' '));
5741
- init();
5742
- update();
5743
- };
5744
- const disable = () => {
5745
- swiper.el.classList.add(...swiper.params.navigation.navigationDisabledClass.split(' '));
5746
- destroy();
5747
- };
5748
- Object.assign(swiper.navigation, {
5749
- enable,
5750
- disable,
5751
- update,
5752
- init,
5753
- destroy
5754
- });
5755
- }
5756
-
5757
5892
  function effectInit(params) {
5758
5893
  const {
5759
5894
  effect,
@@ -6045,8 +6180,11 @@ const createLucideIcon = (iconName, iconNode) => {
6045
6180
  */
6046
6181
 
6047
6182
 
6048
- const __iconNode$4 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
6049
- const ChevronDown = createLucideIcon("chevron-down", __iconNode$4);
6183
+ const __iconNode$8 = [
6184
+ ["path", { d: "m11 17-5-5 5-5", key: "13zhaf" }],
6185
+ ["path", { d: "m18 17-5-5 5-5", key: "h8a8et" }]
6186
+ ];
6187
+ const ChevronsLeft = createLucideIcon("chevrons-left", __iconNode$8);
6050
6188
 
6051
6189
  /**
6052
6190
  * @license lucide-react v0.562.0 - ISC
@@ -6056,7 +6194,49 @@ const ChevronDown = createLucideIcon("chevron-down", __iconNode$4);
6056
6194
  */
6057
6195
 
6058
6196
 
6059
- const __iconNode$3 = [
6197
+ const __iconNode$7 = [
6198
+ ["path", { d: "m6 17 5-5-5-5", key: "xnjwq" }],
6199
+ ["path", { d: "m13 17 5-5-5-5", key: "17xmmf" }]
6200
+ ];
6201
+ const ChevronsRight = createLucideIcon("chevrons-right", __iconNode$7);
6202
+
6203
+ /**
6204
+ * @license lucide-react v0.562.0 - ISC
6205
+ *
6206
+ * This source code is licensed under the ISC license.
6207
+ * See the LICENSE file in the root directory of this source tree.
6208
+ */
6209
+
6210
+
6211
+ const __iconNode$6 = [
6212
+ ["path", { d: "m17 11-5-5-5 5", key: "e8nh98" }],
6213
+ ["path", { d: "m17 18-5-5-5 5", key: "2avn1x" }]
6214
+ ];
6215
+ const ChevronsUp = createLucideIcon("chevrons-up", __iconNode$6);
6216
+
6217
+ /**
6218
+ * @license lucide-react v0.562.0 - ISC
6219
+ *
6220
+ * This source code is licensed under the ISC license.
6221
+ * See the LICENSE file in the root directory of this source tree.
6222
+ */
6223
+
6224
+
6225
+ const __iconNode$5 = [
6226
+ ["rect", { x: "14", y: "3", width: "5", height: "18", rx: "1", key: "kaeet6" }],
6227
+ ["rect", { x: "5", y: "3", width: "5", height: "18", rx: "1", key: "1wsw3u" }]
6228
+ ];
6229
+ const Pause = createLucideIcon("pause", __iconNode$5);
6230
+
6231
+ /**
6232
+ * @license lucide-react v0.562.0 - ISC
6233
+ *
6234
+ * This source code is licensed under the ISC license.
6235
+ * See the LICENSE file in the root directory of this source tree.
6236
+ */
6237
+
6238
+
6239
+ const __iconNode$4 = [
6060
6240
  [
6061
6241
  "path",
6062
6242
  {
@@ -6065,7 +6245,7 @@ const __iconNode$3 = [
6065
6245
  }
6066
6246
  ]
6067
6247
  ];
6068
- const Play = createLucideIcon("play", __iconNode$3);
6248
+ const Play = createLucideIcon("play", __iconNode$4);
6069
6249
 
6070
6250
  /**
6071
6251
  * @license lucide-react v0.562.0 - ISC
@@ -6075,7 +6255,7 @@ const Play = createLucideIcon("play", __iconNode$3);
6075
6255
  */
6076
6256
 
6077
6257
 
6078
- const __iconNode$2 = [
6258
+ const __iconNode$3 = [
6079
6259
  [
6080
6260
  "path",
6081
6261
  {
@@ -6086,7 +6266,7 @@ const __iconNode$2 = [
6086
6266
  ["path", { d: "M16 9a5 5 0 0 1 0 6", key: "1q6k2b" }],
6087
6267
  ["path", { d: "M19.364 18.364a9 9 0 0 0 0-12.728", key: "ijwkga" }]
6088
6268
  ];
6089
- const Volume2 = createLucideIcon("volume-2", __iconNode$2);
6269
+ const Volume2 = createLucideIcon("volume-2", __iconNode$3);
6090
6270
 
6091
6271
  /**
6092
6272
  * @license lucide-react v0.562.0 - ISC
@@ -6096,7 +6276,7 @@ const Volume2 = createLucideIcon("volume-2", __iconNode$2);
6096
6276
  */
6097
6277
 
6098
6278
 
6099
- const __iconNode$1 = [
6279
+ const __iconNode$2 = [
6100
6280
  [
6101
6281
  "path",
6102
6282
  {
@@ -6107,7 +6287,7 @@ const __iconNode$1 = [
6107
6287
  ["line", { x1: "22", x2: "16", y1: "9", y2: "15", key: "1ewh16" }],
6108
6288
  ["line", { x1: "16", x2: "22", y1: "9", y2: "15", key: "5ykzw1" }]
6109
6289
  ];
6110
- const VolumeX = createLucideIcon("volume-x", __iconNode$1);
6290
+ const VolumeX = createLucideIcon("volume-x", __iconNode$2);
6111
6291
 
6112
6292
  /**
6113
6293
  * @license lucide-react v0.562.0 - ISC
@@ -6117,601 +6297,404 @@ const VolumeX = createLucideIcon("volume-x", __iconNode$1);
6117
6297
  */
6118
6298
 
6119
6299
 
6120
- const __iconNode = [
6300
+ const __iconNode$1 = [
6121
6301
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
6122
6302
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
6123
6303
  ];
6124
- const X = createLucideIcon("x", __iconNode);
6304
+ const X = createLucideIcon("x", __iconNode$1);
6305
+
6306
+ /**
6307
+ * @license lucide-react v0.562.0 - ISC
6308
+ *
6309
+ * This source code is licensed under the ISC license.
6310
+ * See the LICENSE file in the root directory of this source tree.
6311
+ */
6312
+
6313
+
6314
+ const __iconNode = [
6315
+ [
6316
+ "path",
6317
+ {
6318
+ d: "M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",
6319
+ key: "1xq2db"
6320
+ }
6321
+ ]
6322
+ ];
6323
+ const Zap = createLucideIcon("zap", __iconNode);
6125
6324
 
6126
- const defaultTranslations = {
6127
- swipe: 'Swipe',
6325
+ const defaultRiyilsTranslations = {
6128
6326
  close: 'Close',
6129
- mute: 'Mute',
6130
- unmute: 'Unmute',
6131
- speedIndicator: '2x',
6132
- videoViewer: 'Video viewer',
6133
- videoInteractionArea: 'Video interaction area',
6327
+ speedIndicator: '2x Speed',
6328
+ forward: '10s Forward',
6329
+ rewind: '10s Rewind',
6134
6330
  };
6135
- function RiyilsViewer({ videos, initialIndex = 0, onClose, onVideoChange, translations = defaultTranslations, progressBarColor = '#FF0000', }) {
6331
+ const DOUBLE_TAP_DELAY = 300;
6332
+ const LONG_PRESS_DELAY = 500;
6333
+ const SEEK_TIME = 10;
6334
+ const ANIMATION_DURATION = 600;
6335
+ const SCROLL_HINT_DURATION = 1000;
6336
+ function useLockBodyScroll() {
6337
+ useEffect(() => {
6338
+ const body = globalThis.document.body;
6339
+ const originalStyle = globalThis.getComputedStyle(body).overflow;
6340
+ const originalOverscroll = body.style.overscrollBehavior;
6341
+ body.style.overflow = 'hidden';
6342
+ body.style.overscrollBehavior = 'none';
6343
+ return () => {
6344
+ body.style.overflow = originalStyle;
6345
+ body.style.overscrollBehavior = originalOverscroll;
6346
+ };
6347
+ }, []);
6348
+ }
6349
+ function RiyilsViewer({ videos, initialIndex = 0, onClose, onVideoChange, translations = {}, progressBarColor = '#fff', }) {
6350
+ useLockBodyScroll();
6351
+ const t = useMemo(() => (Object.assign(Object.assign({}, defaultRiyilsTranslations), translations)), [translations]);
6136
6352
  const [currentIndex, setCurrentIndex] = useState(initialIndex);
6137
- const [isPaused, setIsPaused] = useState(false);
6138
6353
  const [isMuted, setIsMuted] = useState(true);
6139
- const [videoProgress, setVideoProgress] = useState(0);
6140
- const [isLoading, setIsLoading] = useState({});
6354
+ const [progress, setProgress] = useState(0);
6141
6355
  const [isSpeedUp, setIsSpeedUp] = useState(false);
6142
- const [showSwipeTip, setShowSwipeTip] = useState(true);
6356
+ const [isPlaying, setIsPlaying] = useState(true);
6357
+ const [seekFeedback, setSeekFeedback] = useState(null);
6358
+ const [showPlayPauseIcon, setShowPlayPauseIcon] = useState(false);
6359
+ const [showScrollHint, setShowScrollHint] = useState(false);
6143
6360
  const swiperRef = useRef(null);
6144
- const videoRefs = useRef([]);
6145
- const lastTapRef = useRef(0);
6146
- const holdTimeoutRef = useRef(null);
6361
+ const activeVideoRef = useRef(null);
6362
+ const containerRef = useRef(null);
6363
+ const longPressTimer = useRef(null);
6364
+ const doubleTapTimer = useRef(null);
6365
+ const lastTapTime = useRef(0);
6366
+ const longPressTriggered = useRef(false);
6147
6367
  useEffect(() => {
6148
- const currentVideoElement = videoRefs.current[currentIndex];
6149
- if (!currentVideoElement)
6368
+ const container = containerRef.current;
6369
+ if (!container)
6150
6370
  return;
6151
- const updateProgress = () => {
6152
- const progress = (currentVideoElement.currentTime / currentVideoElement.duration) * 100;
6153
- setVideoProgress(progress || 0);
6371
+ const handleContextMenu = (e) => {
6372
+ e.preventDefault();
6373
+ e.stopPropagation();
6154
6374
  };
6155
- currentVideoElement.addEventListener('timeupdate', updateProgress, { passive: true });
6375
+ container.addEventListener('contextmenu', handleContextMenu);
6156
6376
  return () => {
6157
- currentVideoElement.removeEventListener('timeupdate', updateProgress);
6377
+ container.removeEventListener('contextmenu', handleContextMenu);
6158
6378
  };
6159
- }, [currentIndex]);
6379
+ }, []);
6160
6380
  useEffect(() => {
6161
- onVideoChange === null || onVideoChange === void 0 ? void 0 : onVideoChange(currentIndex);
6162
- }, [currentIndex, onVideoChange]);
6381
+ const video = activeVideoRef.current;
6382
+ if (!video)
6383
+ return;
6384
+ if (isPlaying) {
6385
+ const playPromise = video.play();
6386
+ if (playPromise !== undefined) {
6387
+ playPromise.catch(() => {
6388
+ setIsPlaying(false);
6389
+ });
6390
+ }
6391
+ }
6392
+ else {
6393
+ video.pause();
6394
+ }
6395
+ }, [currentIndex, isPlaying]);
6163
6396
  useEffect(() => {
6164
- setShowSwipeTip(true);
6397
+ const video = activeVideoRef.current;
6398
+ if (video) {
6399
+ video.muted = isMuted;
6400
+ video.playbackRate = isSpeedUp ? 2 : 1;
6401
+ }
6402
+ }, [isMuted, isSpeedUp, currentIndex]);
6403
+ useEffect(() => {
6404
+ setShowScrollHint(true);
6165
6405
  const timer = setTimeout(() => {
6166
- setShowSwipeTip(false);
6167
- }, 3000);
6406
+ setShowScrollHint(false);
6407
+ }, SCROLL_HINT_DURATION);
6168
6408
  return () => clearTimeout(timer);
6169
6409
  }, [currentIndex]);
6170
6410
  useEffect(() => {
6171
- videoRefs.current.forEach((video, index) => {
6172
- if (video) {
6173
- if (index === currentIndex && !isPaused) {
6174
- video.playbackRate = isSpeedUp ? 2 : 1;
6175
- video.play().catch(() => { });
6176
- }
6177
- else {
6178
- video.pause();
6179
- }
6411
+ if (swiperRef.current) {
6412
+ swiperRef.current.virtual.update(true);
6413
+ swiperRef.current.update();
6414
+ if (swiperRef.current.keyboard) {
6415
+ swiperRef.current.keyboard.enable();
6180
6416
  }
6417
+ }
6418
+ }, [videos.length]);
6419
+ const handleTimeUpdate = useCallback((e) => {
6420
+ const vid = e.currentTarget;
6421
+ if (vid.duration) {
6422
+ setProgress((vid.currentTime / vid.duration) * 100);
6423
+ }
6424
+ }, []);
6425
+ const handleTouchStart = useCallback(() => {
6426
+ longPressTriggered.current = false;
6427
+ longPressTimer.current = setTimeout(() => {
6428
+ setIsSpeedUp(true);
6429
+ longPressTriggered.current = true;
6430
+ }, LONG_PRESS_DELAY);
6431
+ }, []);
6432
+ const handleTouchEnd = useCallback(() => {
6433
+ if (longPressTimer.current) {
6434
+ clearTimeout(longPressTimer.current);
6435
+ }
6436
+ setIsSpeedUp(false);
6437
+ }, []);
6438
+ const handleSeek = useCallback((seconds) => {
6439
+ const video = activeVideoRef.current;
6440
+ if (!video)
6441
+ return;
6442
+ video.currentTime = Math.min(Math.max(video.currentTime + seconds, 0), video.duration);
6443
+ setSeekFeedback(seconds > 0 ? 'forward' : 'rewind');
6444
+ setTimeout(() => setSeekFeedback(null), ANIMATION_DURATION);
6445
+ }, []);
6446
+ const togglePlay = useCallback(() => {
6447
+ setIsPlaying(prev => {
6448
+ const newState = !prev;
6449
+ setShowPlayPauseIcon(true);
6450
+ setTimeout(() => setShowPlayPauseIcon(false), ANIMATION_DURATION);
6451
+ return newState;
6181
6452
  });
6182
- }, [currentIndex, isPaused, isSpeedUp]);
6453
+ }, []);
6454
+ const handleZoneClick = useCallback((zone, e) => {
6455
+ e.preventDefault();
6456
+ e.stopPropagation();
6457
+ if (longPressTriggered.current) {
6458
+ longPressTriggered.current = false;
6459
+ return;
6460
+ }
6461
+ const now = Date.now();
6462
+ const timeDiff = now - lastTapTime.current;
6463
+ if (timeDiff < DOUBLE_TAP_DELAY && timeDiff > 0) {
6464
+ if (doubleTapTimer.current) {
6465
+ clearTimeout(doubleTapTimer.current);
6466
+ }
6467
+ if (zone === 'right') {
6468
+ handleSeek(SEEK_TIME);
6469
+ }
6470
+ else if (zone === 'left') {
6471
+ handleSeek(-SEEK_TIME);
6472
+ }
6473
+ else {
6474
+ togglePlay();
6475
+ }
6476
+ lastTapTime.current = 0;
6477
+ }
6478
+ else {
6479
+ lastTapTime.current = now;
6480
+ doubleTapTimer.current = setTimeout(() => {
6481
+ togglePlay();
6482
+ lastTapTime.current = 0;
6483
+ }, DOUBLE_TAP_DELAY);
6484
+ }
6485
+ }, [handleSeek, togglePlay]);
6486
+ const handleMuteToggle = useCallback((e) => {
6487
+ e.stopPropagation();
6488
+ setIsMuted(prev => !prev);
6489
+ }, []);
6183
6490
  useEffect(() => {
6184
6491
  const handleKeyDown = (e) => {
6185
- switch (e.key) {
6492
+ if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
6493
+ return;
6494
+ }
6495
+ switch (e.code) {
6186
6496
  case 'Escape':
6187
6497
  e.preventDefault();
6188
- onClose === null || onClose === void 0 ? void 0 : onClose();
6498
+ onClose();
6189
6499
  break;
6190
- case ' ':
6500
+ case 'Space':
6191
6501
  e.preventDefault();
6192
- setIsPaused((prev) => !prev);
6502
+ togglePlay();
6193
6503
  break;
6194
- case 'm':
6195
- case 'M':
6504
+ case 'KeyM':
6196
6505
  e.preventDefault();
6197
6506
  setIsMuted((prev) => !prev);
6198
6507
  break;
6199
6508
  }
6200
6509
  };
6201
6510
  globalThis.addEventListener('keydown', handleKeyDown);
6202
- return () => globalThis.removeEventListener('keydown', handleKeyDown);
6203
- }, [onClose]);
6204
- const handleSlideChange = (swiper) => {
6205
- setCurrentIndex(swiper.activeIndex);
6206
- setVideoProgress(0);
6207
- };
6208
- const handleVideoClick = () => {
6209
- const now = Date.now();
6210
- const timeSinceLastTap = now - lastTapRef.current;
6211
- if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {
6212
- setIsPaused((prev) => !prev);
6213
- lastTapRef.current = 0;
6214
- }
6215
- else {
6216
- lastTapRef.current = now;
6217
- }
6218
- };
6219
- const handleTouchStart = (e, index) => {
6220
- const touch = e.touches[0];
6221
- const target = e.currentTarget;
6222
- const rect = target.getBoundingClientRect();
6223
- const x = touch.clientX - rect.left;
6224
- const width = rect.width;
6225
- if (x > width * 0.6 && index === currentIndex) {
6226
- holdTimeoutRef.current = setTimeout(() => {
6227
- setIsSpeedUp(true);
6228
- }, 100);
6229
- }
6230
- };
6231
- const clearSpeedUp = () => {
6232
- if (holdTimeoutRef.current) {
6233
- clearTimeout(holdTimeoutRef.current);
6234
- holdTimeoutRef.current = null;
6235
- }
6236
- setIsSpeedUp(false);
6237
- };
6238
- const handleTouchEnd = clearSpeedUp;
6239
- const handleMouseDown = (e, index) => {
6240
- const target = e.currentTarget;
6241
- const rect = target.getBoundingClientRect();
6242
- const x = e.clientX - rect.left;
6243
- const width = rect.width;
6244
- if (x > width * 0.6 && index === currentIndex) {
6245
- holdTimeoutRef.current = setTimeout(() => {
6246
- setIsSpeedUp(true);
6247
- }, 100);
6248
- }
6249
- };
6250
- const handleMouseUp = clearSpeedUp;
6251
- const goToNextVideo = () => {
6252
- var _a;
6253
- if (currentIndex < videos.length - 1) {
6254
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.slideNext();
6255
- }
6256
- else {
6257
- onClose === null || onClose === void 0 ? void 0 : onClose();
6511
+ return () => {
6512
+ globalThis.removeEventListener('keydown', handleKeyDown);
6513
+ };
6514
+ }, [onClose, togglePlay]);
6515
+ const handleSlideChange = useCallback((s) => {
6516
+ setCurrentIndex(s.activeIndex);
6517
+ setProgress(0);
6518
+ setIsPlaying(true);
6519
+ setSeekFeedback(null);
6520
+ if (onVideoChange) {
6521
+ onVideoChange(s.activeIndex);
6258
6522
  }
6259
- };
6260
- return (React.createElement("dialog", { open: true, className: "react-riyils-viewer", onContextMenu: (e) => e.preventDefault(), "aria-label": translations.videoViewer, style: {
6261
- touchAction: 'pan-y',
6262
- WebkitTapHighlightColor: 'transparent',
6263
- userSelect: 'none',
6264
- WebkitUserSelect: 'none',
6265
- overscrollBehavior: 'none',
6266
- } },
6267
- React.createElement(Swiper, { modules: [Keyboard, Mousewheel], direction: "vertical", slidesPerView: 1, speed: 500, threshold: 5, touchRatio: 1, touchAngle: 45, followFinger: true, shortSwipes: true, longSwipes: true, longSwipesRatio: 0.5, longSwipesMs: 300, preventInteractionOnTransition: false, keyboard: { enabled: true }, mousewheel: { forceToAxis: true, sensitivity: 1 }, initialSlide: initialIndex, onSwiper: (swiper) => {
6268
- swiperRef.current = swiper;
6269
- }, onSlideChange: handleSlideChange, onReachEnd: () => {
6270
- setTimeout(() => {
6271
- onClose === null || onClose === void 0 ? void 0 : onClose();
6272
- }, 300);
6273
- }, style: { width: '100%', height: '100%' } }, videos.map((video, index) => {
6274
- const isActive = index === currentIndex;
6275
- return (React.createElement(SwiperSlide, { key: video.id },
6276
- React.createElement("section", { className: "react-riyils-viewer__section", "aria-label": `Video ${index + 1} of ${videos.length}` },
6277
- React.createElement("button", { type: "button", className: "react-riyils-viewer__interaction-area", onTouchStart: (e) => handleTouchStart(e, index), onTouchEnd: handleTouchEnd, onMouseDown: (e) => handleMouseDown(e, index), onMouseUp: handleMouseUp, onMouseLeave: handleMouseUp, onContextMenu: (e) => e.preventDefault(), "aria-label": translations.videoInteractionArea }),
6278
- React.createElement("video", { ref: (el) => {
6279
- videoRefs.current[index] = el;
6280
- }, src: video.videoUrl, "aria-label": `Video ${index + 1}`, onClick: handleVideoClick, onContextMenu: (e) => e.preventDefault(), className: "react-riyils-viewer__video", playsInline: true, muted: isMuted, preload: Math.abs(index - currentIndex) <= 1 ? 'auto' : 'metadata', onLoadStart: () => {
6281
- setIsLoading(prev => (Object.assign(Object.assign({}, prev), { [index]: true })));
6282
- }, onLoadedData: () => {
6283
- setIsLoading(prev => (Object.assign(Object.assign({}, prev), { [index]: false })));
6284
- }, onWaiting: () => {
6285
- setIsLoading(prev => (Object.assign(Object.assign({}, prev), { [index]: true })));
6286
- }, onCanPlay: () => {
6287
- setIsLoading(prev => (Object.assign(Object.assign({}, prev), { [index]: false })));
6288
- }, onEnded: (e) => {
6289
- if (isActive) {
6290
- const target = e.target;
6291
- if (target.currentTime >= target.duration - 0.1) {
6292
- goToNextVideo();
6293
- }
6294
- }
6295
- }, onTimeUpdate: (e) => {
6296
- if (isActive) {
6297
- const target = e.target;
6298
- setVideoProgress((target.currentTime / target.duration) * 100);
6299
- }
6300
- } },
6301
- React.createElement("track", { kind: "captions" })),
6302
- isLoading[index] && isActive && (React.createElement("div", { className: "react-riyils-viewer__loading" },
6303
- React.createElement("div", { className: "react-riyils-viewer__loading-spinner" }))),
6304
- isPaused && isActive && (React.createElement("div", { className: "react-riyils-viewer__pause-indicator" },
6305
- React.createElement("div", { className: "react-riyils-viewer__pause-icon" },
6306
- React.createElement("div", { className: "react-riyils-viewer__pause-bars", style: { borderLeftColor: 'rgba(255, 255, 255, 0.9)', borderRightColor: 'rgba(255, 255, 255, 0.9)' } })))),
6307
- isSpeedUp && isActive && (React.createElement("div", { className: "react-riyils-viewer__speed-indicator" },
6308
- React.createElement("div", { className: "react-riyils-viewer__speed-badge" },
6309
- React.createElement("span", { className: "react-riyils-viewer__speed-text" }, translations.speedIndicator)))))));
6310
- })),
6311
- React.createElement("div", { className: "react-riyils-viewer__overlay" },
6312
- React.createElement("div", { className: "react-riyils-viewer__header" },
6313
- React.createElement("div", { className: "react-riyils-viewer__header-content" },
6314
- React.createElement("div", { className: "react-riyils-viewer__progress-wrapper" },
6315
- React.createElement("div", { className: "react-riyils-viewer__progress-track", style: { backgroundColor: `${progressBarColor}30` } },
6316
- React.createElement("div", { className: "react-riyils-viewer__progress-bar", style: { width: `${videoProgress}%`, backgroundColor: progressBarColor } }))),
6317
- React.createElement("button", { onClick: onClose, className: "react-riyils-viewer__close-button", "aria-label": translations.close },
6318
- React.createElement(X, { className: "react-riyils-viewer__close-icon" })))),
6319
- currentIndex === 0 && showSwipeTip && (React.createElement("div", { className: "react-riyils-viewer__swipe-tip" },
6320
- React.createElement("div", { className: "react-riyils-viewer__swipe-tip-content" },
6321
- React.createElement("p", { className: "react-riyils-viewer__swipe-tip-text" }, translations.swipe),
6322
- React.createElement("div", { className: "react-riyils-viewer__swipe-tip-icon-wrapper" },
6323
- React.createElement(ChevronDown, { className: "react-riyils-viewer__swipe-tip-icon react-riyils-viewer__swipe-tip-icon--1" }),
6324
- React.createElement(ChevronDown, { className: "react-riyils-viewer__swipe-tip-icon react-riyils-viewer__swipe-tip-icon--2" }),
6325
- React.createElement(ChevronDown, { className: "react-riyils-viewer__swipe-tip-icon react-riyils-viewer__swipe-tip-icon--3" }))))),
6326
- showSwipeTip && currentIndex > 0 && (React.createElement("div", { className: "react-riyils-viewer__swipe-tip" },
6327
- React.createElement("div", { className: "react-riyils-viewer__swipe-tip-content" },
6328
- React.createElement("p", { className: "react-riyils-viewer__swipe-tip-text" }, translations.swipe),
6329
- React.createElement("div", { className: "react-riyils-viewer__swipe-tip-icon-wrapper" },
6330
- React.createElement(ChevronDown, { className: "react-riyils-viewer__swipe-tip-icon react-riyils-viewer__swipe-tip-icon--1" }),
6331
- React.createElement(ChevronDown, { className: "react-riyils-viewer__swipe-tip-icon react-riyils-viewer__swipe-tip-icon--2" }),
6332
- React.createElement(ChevronDown, { className: "react-riyils-viewer__swipe-tip-icon react-riyils-viewer__swipe-tip-icon--3" }))))),
6333
- React.createElement("div", { className: "react-riyils-viewer__mute-button-wrapper" },
6334
- React.createElement("button", { onClick: () => setIsMuted(!isMuted), className: "react-riyils-viewer__mute-button", "aria-label": isMuted ? translations.unmute : translations.mute }, isMuted ? (React.createElement(VolumeX, { className: "react-riyils-viewer__mute-icon" })) : (React.createElement(Volume2, { className: "react-riyils-viewer__mute-icon" })))))));
6523
+ }, [onVideoChange]);
6524
+ const preventDefaultMenu = useCallback((e) => {
6525
+ e.preventDefault();
6526
+ e.stopPropagation();
6527
+ return false;
6528
+ }, []);
6529
+ return (React.createElement("div", { ref: containerRef, className: "react-riyils-viewer", style: { WebkitTouchCallout: 'none' } },
6530
+ React.createElement("div", { className: "react-riyils-viewer__gradient-top" }),
6531
+ React.createElement("div", { className: "react-riyils-viewer__close-container" },
6532
+ React.createElement("button", { type: "button", onClick: onClose, className: "react-riyils-viewer__btn react-riyils-viewer__btn-close", "aria-label": t.close },
6533
+ React.createElement(X, { size: 24, strokeWidth: 2.5 }))),
6534
+ React.createElement(Swiper, { modules: [Keyboard, Mousewheel, Virtual], direction: "vertical", initialSlide: initialIndex, onSwiper: (s) => (swiperRef.current = s), onSlideChange: handleSlideChange, className: "h-full w-full", style: { height: '100%', width: '100%' }, threshold: 10, speed: 400, keyboard: { enabled: true }, mousewheel: { enabled: true, thresholdDelta: 50 }, virtual: { enabled: true, addSlidesBefore: 1, addSlidesAfter: 2 } }, videos.map((video, index) => (React.createElement(SwiperSlide, { key: video.id, virtualIndex: index, className: "react-riyils-viewer__slide" }, index === currentIndex ? (React.createElement(React.Fragment, null,
6535
+ React.createElement("fieldset", { className: "react-riyils-viewer__gesture-grid", onContextMenu: preventDefaultMenu, tabIndex: -1, style: { border: 0, margin: 0, padding: 0 } },
6536
+ React.createElement("button", { type: "button", className: "react-riyils-viewer__gesture-zone", onClick: (e) => handleZoneClick('left', e), "aria-label": t.rewind }),
6537
+ React.createElement("button", { type: "button", className: "react-riyils-viewer__gesture-zone", onClick: (e) => handleZoneClick('center', e), "aria-label": isPlaying ? 'Pause' : 'Play' }),
6538
+ React.createElement("button", { type: "button", className: "react-riyils-viewer__gesture-zone", onClick: (e) => handleZoneClick('right', e), onTouchStart: handleTouchStart, onTouchEnd: handleTouchEnd, onMouseDown: handleTouchStart, onMouseUp: handleTouchEnd, "aria-label": t.forward })),
6539
+ React.createElement("div", { className: `react-riyils-viewer__feedback-speed ${isSpeedUp ? 'visible' : ''}` },
6540
+ React.createElement(Zap, { size: 16, fill: "currentColor", className: "text-yellow-400" }),
6541
+ React.createElement("span", null, t.speedIndicator)),
6542
+ !isPlaying && (React.createElement("div", { className: "react-riyils-viewer__feedback-center" },
6543
+ React.createElement("div", { className: "react-riyils-viewer__feedback-icon animate-in" },
6544
+ React.createElement(Play, { size: 32, fill: "white" })))),
6545
+ isPlaying && showPlayPauseIcon && (React.createElement("div", { className: "react-riyils-viewer__feedback-center" },
6546
+ React.createElement("div", { className: "react-riyils-viewer__feedback-icon animate-out" },
6547
+ React.createElement(Pause, { size: 32, fill: "white" })))),
6548
+ seekFeedback && (React.createElement("div", { className: `react-riyils-viewer__feedback-seek ${seekFeedback === 'forward' ? 'right' : 'left'}` },
6549
+ React.createElement("div", { className: "react-riyils-viewer__seek-circle" },
6550
+ seekFeedback === 'forward' ? React.createElement(ChevronsRight, { size: 32 }) : React.createElement(ChevronsLeft, { size: 32 }),
6551
+ React.createElement("span", { className: "react-riyils-viewer__seek-text" }, "10s")))),
6552
+ React.createElement("video", { ref: activeVideoRef, src: video.videoUrl, className: "react-riyils-viewer__video", playsInline: true, loop: true, muted: isMuted, autoPlay: true, poster: video.thumbnailUrl, onTimeUpdate: handleTimeUpdate, onContextMenu: preventDefaultMenu, disablePictureInPicture: true, disableRemotePlayback: true, "aria-label": `Video ${video.id}` },
6553
+ React.createElement("track", { kind: "captions", src: video.captionUrl || '', label: "English" })))) : (React.createElement("div", { className: "react-riyils-viewer__slide" },
6554
+ React.createElement("div", { className: "react-riyils-viewer__loader" }))))))),
6555
+ React.createElement("div", { className: "react-riyils-viewer__scroll-hint", style: {
6556
+ position: 'absolute',
6557
+ bottom: '80px',
6558
+ left: '50%',
6559
+ transform: 'translateX(-50%)',
6560
+ zIndex: 45,
6561
+ pointerEvents: 'none',
6562
+ opacity: showScrollHint ? 1 : 0,
6563
+ transition: 'opacity 0.5s ease-in-out',
6564
+ display: 'flex',
6565
+ flexDirection: 'column',
6566
+ alignItems: 'center',
6567
+ animation: showScrollHint ? 'rr-bounce 1s infinite' : 'none',
6568
+ } },
6569
+ React.createElement(ChevronsUp, { size: 32, color: "rgba(255, 255, 255, 0.7)" })),
6570
+ React.createElement("div", { className: "react-riyils-viewer__gradient-bottom" },
6571
+ React.createElement("div", { className: "react-riyils-viewer__controls-row" },
6572
+ React.createElement("button", { type: "button", onClick: handleMuteToggle, className: "react-riyils-viewer__btn react-riyils-viewer__btn-mute" }, isMuted ? React.createElement(VolumeX, { size: 24 }) : React.createElement(Volume2, { size: 24 }))),
6573
+ React.createElement("div", { className: "react-riyils-viewer__progress-container" },
6574
+ React.createElement("div", { className: "react-riyils-viewer__progress-fill", style: { width: `${progress}%`, background: progressBarColor } }))),
6575
+ React.createElement("style", null, `
6576
+ @keyframes rr-bounce {
6577
+ 0%, 100% { transform: translateX(-50%) translateY(0); }
6578
+ 50% { transform: translateX(-50%) translateY(-10px); }
6579
+ }
6580
+ `)));
6335
6581
  }
6336
6582
 
6337
6583
  const defaultReactRiyilsTranslations = {
6338
- watchFullVideo: 'Watch Full Video',
6339
- videoProgress: 'Video progress',
6340
- };
6341
- const VIDEO_DURATION_LIMIT = 10;
6342
- const PRELOAD_DISTANCE = 1;
6343
- const CONTAINER_HEIGHT_MOBILE = 380;
6344
- const CONTAINER_HEIGHT_DESKTOP = 500;
6345
- const PREVIEW_DURATION = 2;
6346
- const getPreloadStrategy = (index, activeIndex, preloadDist) => {
6347
- if (index <= 3)
6348
- return 'auto';
6349
- const distance = Math.abs(index - activeIndex);
6350
- if (distance <= preloadDist)
6351
- return 'auto';
6352
- if (distance <= 2)
6353
- return 'metadata';
6354
- return 'none';
6355
- };
6356
- const handleVideoPlayWithFallback = (video, hasInteracted, setHasInteracted) => {
6357
- video.play().catch((error) => {
6358
- console.warn('Video play failed:', error);
6359
- if (!hasInteracted) {
6360
- const playOnInteraction = () => {
6361
- video.play().catch(() => { });
6362
- setHasInteracted(true);
6363
- document.removeEventListener('touchstart', playOnInteraction);
6364
- document.removeEventListener('click', playOnInteraction);
6365
- };
6366
- document.addEventListener('touchstart', playOnInteraction, { once: true });
6367
- document.addEventListener('click', playOnInteraction, { once: true });
6368
- }
6369
- });
6584
+ ctaButton: 'Watch Full Video',
6585
+ carouselAriaLabel: 'Video stories',
6586
+ slideActiveAriaLabel: 'Watch full video',
6587
+ slideInactiveAriaLabel: 'Go to slide',
6370
6588
  };
6371
- const safePlayVideo = (video) => {
6372
- video.play().catch((error) => console.warn('Video preload failed:', error));
6373
- };
6374
- function ReactRiyils({ videos, currentIndex, onVideoClick, onVideoChange, translations = defaultReactRiyilsTranslations, containerHeightMobile = CONTAINER_HEIGHT_MOBILE, containerHeightDesktop = CONTAINER_HEIGHT_DESKTOP, progressBarColor = '#3B82F6', videoDurationLimit = VIDEO_DURATION_LIMIT, preloadDistance = PRELOAD_DISTANCE, previewDuration = PREVIEW_DURATION, autoPlay = true, }) {
6375
- const swiperRef = useRef(null);
6376
- const videoRefs = useRef([]);
6377
- const containerRef = useRef(null);
6378
- const [activeIndex, setActiveIndex] = useState(currentIndex);
6379
- const [isLoading, setIsLoading] = useState({});
6380
- const [hasInteracted, setHasInteracted] = useState(false);
6381
- const wheelTimeoutRef = useRef(null);
6382
- const isWheelScrollingRef = useRef(false);
6383
- const dynamicStretch = Math.round(containerHeightDesktop / 9);
6384
- const setVideoLoading = (index, loading) => {
6385
- setIsLoading(prev => (Object.assign(Object.assign({}, prev), { [index]: loading })));
6386
- };
6387
- const handleVideoLoadedData = (e, index) => {
6388
- setVideoLoading(index, false);
6389
- const videoEl = e.target;
6390
- const distance = Math.abs(index - activeIndex);
6391
- if (videoEl.readyState >= 2) {
6392
- if (index === activeIndex) {
6393
- videoEl.style.opacity = '1';
6394
- videoEl.loop = true;
6395
- videoEl.currentTime = 0;
6396
- if (autoPlay) {
6397
- handleVideoPlayWithFallback(videoEl, hasInteracted, setHasInteracted);
6398
- }
6399
- }
6400
- else if (distance <= preloadDistance) {
6401
- videoEl.style.opacity = '0.95';
6402
- videoEl.loop = false;
6403
- videoEl.currentTime = 0;
6404
- if (autoPlay) {
6405
- safePlayVideo(videoEl);
6406
- }
6407
- }
6408
- }
6409
- };
6410
- useEffect(() => {
6411
- if (swiperRef.current && currentIndex !== activeIndex) {
6412
- swiperRef.current.slideTo(currentIndex, 400);
6413
- }
6414
- }, [currentIndex, activeIndex]);
6589
+ const SlideItem = React.memo(({ video, isVisualActive, index, onVideoClick, t, shouldLoad }) => {
6590
+ const videoRef = useRef(null);
6415
6591
  useEffect(() => {
6416
- const handleResize = () => {
6417
- if (swiperRef.current) {
6418
- swiperRef.current.update();
6419
- swiperRef.current.slideTo(activeIndex, 0);
6592
+ const el = videoRef.current;
6593
+ if (!el)
6594
+ return;
6595
+ const handleTimeUpdate = () => {
6596
+ if (!isVisualActive) {
6597
+ if (el.currentTime >= 2) {
6598
+ el.currentTime = 0;
6599
+ el.play().catch(() => { });
6600
+ }
6420
6601
  }
6421
6602
  };
6422
- window.addEventListener('resize', handleResize);
6423
- const timer = setTimeout(() => {
6424
- if (swiperRef.current) {
6425
- swiperRef.current.update();
6426
- swiperRef.current.slideTo(currentIndex, 0);
6427
- }
6428
- }, 100);
6429
- if (containerRef.current) {
6430
- const style = containerRef.current.style;
6431
- style.touchAction = 'pan-y pan-x';
6432
- style.webkitTapHighlightColor = 'transparent';
6433
- style.userSelect = 'none';
6434
- style.webkitUserSelect = 'none';
6435
- const handleWheel = (e) => {
6436
- var _a, _b;
6437
- if (isWheelScrollingRef.current) {
6438
- e.preventDefault();
6439
- e.stopPropagation();
6440
- return;
6441
- }
6442
- if (Math.abs(e.deltaX) < 30)
6443
- return;
6444
- e.preventDefault();
6445
- e.stopPropagation();
6446
- isWheelScrollingRef.current = true;
6447
- if (e.deltaX > 0) {
6448
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.slideNext();
6449
- }
6450
- else if (e.deltaX < 0) {
6451
- (_b = swiperRef.current) === null || _b === void 0 ? void 0 : _b.slidePrev();
6452
- }
6453
- if (wheelTimeoutRef.current) {
6454
- clearTimeout(wheelTimeoutRef.current);
6455
- }
6456
- wheelTimeoutRef.current = setTimeout(() => {
6457
- isWheelScrollingRef.current = false;
6458
- }, 1000);
6459
- };
6460
- containerRef.current.addEventListener('wheel', handleWheel, { passive: false });
6461
- return () => {
6462
- var _a;
6463
- window.removeEventListener('resize', handleResize);
6464
- clearTimeout(timer);
6465
- if (wheelTimeoutRef.current)
6466
- clearTimeout(wheelTimeoutRef.current);
6467
- (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('wheel', handleWheel);
6468
- };
6603
+ el.addEventListener('timeupdate', handleTimeUpdate);
6604
+ if (isVisualActive) {
6605
+ el.currentTime = 0;
6606
+ el.play().catch(() => { });
6607
+ }
6608
+ else if (shouldLoad) {
6609
+ el.muted = true;
6610
+ el.currentTime = 0;
6469
6611
  }
6470
6612
  return () => {
6471
- window.removeEventListener('resize', handleResize);
6472
- clearTimeout(timer);
6473
- };
6474
- }, []);
6475
- useEffect(() => {
6476
- const videos = videoRefs.current;
6477
- return () => {
6478
- videos.forEach(video => {
6479
- if (video) {
6480
- video.pause();
6481
- video.removeAttribute('src');
6482
- video.load();
6483
- }
6484
- });
6613
+ el.removeEventListener('timeupdate', handleTimeUpdate);
6485
6614
  };
6486
- }, []);
6615
+ }, [isVisualActive, shouldLoad]);
6616
+ return (React.createElement("button", { type: "button", className: "react-riyils__slide-button", onClick: () => onVideoClick(index), "aria-label": isVisualActive ? t.slideActiveAriaLabel : t.slideInactiveAriaLabel },
6617
+ React.createElement("div", { className: `react-riyils__card ${isVisualActive ? 'active' : ''}` },
6618
+ React.createElement("video", { ref: videoRef, src: shouldLoad ? video.videoUrl : undefined, muted: true, playsInline: true, loop: isVisualActive, className: "react-riyils__video", preload: shouldLoad ? "auto" : "metadata" }),
6619
+ isVisualActive && (React.createElement("div", { className: "react-riyils__cta-container" },
6620
+ React.createElement("span", { className: "react-riyils__cta-button" },
6621
+ React.createElement(Play, { size: 14, fill: "currentColor" }),
6622
+ t.ctaButton))))));
6623
+ });
6624
+ SlideItem.displayName = 'SlideItem';
6625
+ function ReactRiyils({ videos, currentIndex = 0, onVideoClick, onVideoChange, translations = {}, containerHeightMobile, containerHeightDesktop, autoPlay = true, }) {
6626
+ const swiperRef = useRef(null);
6627
+ const [activeIndex, setActiveIndex] = useState(currentIndex);
6628
+ const t = useMemo(() => (Object.assign(Object.assign({}, defaultReactRiyilsTranslations), translations)), [translations]);
6629
+ const containerStyle = useMemo(() => ({
6630
+ '--container-height-mobile': containerHeightMobile ? `${containerHeightMobile}px` : undefined,
6631
+ '--container-height-desktop': containerHeightDesktop ? `${containerHeightDesktop}px` : undefined,
6632
+ }), [containerHeightMobile, containerHeightDesktop]);
6487
6633
  useEffect(() => {
6488
- const timer = setTimeout(() => {
6489
- videoRefs.current.forEach((video, index) => {
6490
- if (!video)
6491
- return;
6492
- const distance = Math.abs(index - activeIndex);
6493
- if (index === activeIndex) {
6494
- video.style.opacity = '1';
6495
- video.loop = true;
6496
- if (video.readyState >= 2) {
6497
- video.currentTime = 0;
6498
- if (autoPlay) {
6499
- handleVideoPlayWithFallback(video, hasInteracted, setHasInteracted);
6500
- }
6634
+ const swiper = swiperRef.current;
6635
+ if (swiper && !swiper.destroyed) {
6636
+ if (swiper.activeIndex !== currentIndex) {
6637
+ swiper.slideTo(currentIndex, 0);
6638
+ }
6639
+ swiper.update();
6640
+ const timer = setTimeout(() => {
6641
+ if (!swiper.destroyed) {
6642
+ swiper.updateSize();
6643
+ swiper.updateSlides();
6644
+ swiper.updateProgress();
6645
+ if (swiper.virtual) {
6646
+ swiper.virtual.update(true);
6501
6647
  }
6502
- }
6503
- else if (distance <= preloadDistance) {
6504
- video.style.opacity = '0.95';
6505
- video.loop = false;
6506
- if (video.readyState >= 2) {
6507
- video.currentTime = 0;
6508
- if (autoPlay) {
6509
- safePlayVideo(video);
6510
- }
6648
+ if (swiper.activeIndex !== currentIndex) {
6649
+ swiper.slideTo(currentIndex, 0);
6511
6650
  }
6512
6651
  }
6513
- });
6514
- }, 100);
6515
- return () => clearTimeout(timer);
6516
- }, [activeIndex, hasInteracted]);
6517
- const handleSlideChange = (swiper) => {
6518
- const activeIdx = swiper.activeIndex;
6519
- setActiveIndex(activeIdx);
6520
- onVideoChange(activeIdx);
6521
- videoRefs.current.forEach((video, index) => {
6522
- if (!video)
6523
- return;
6524
- const distance = Math.abs(index - activeIdx);
6525
- if (index === activeIdx) {
6526
- video.style.opacity = '1';
6527
- video.loop = true;
6528
- if (video.readyState >= 2) {
6529
- video.currentTime = 0;
6530
- video.play().catch((error) => console.warn('Video play failed:', error));
6531
- }
6532
- }
6533
- else if (distance <= PRELOAD_DISTANCE) {
6534
- video.style.opacity = '0.95';
6535
- video.loop = false;
6536
- if (video.readyState >= 2) {
6537
- video.currentTime = 0;
6538
- video.play().catch((error) => console.warn('Video preload failed:', error));
6539
- }
6540
- }
6541
- else {
6542
- video.pause();
6543
- video.currentTime = 0;
6544
- video.loop = false;
6545
- }
6546
- });
6547
- };
6548
- const handleTimeUpdate = (e, index) => {
6549
- var _a, _b;
6550
- const target = e.currentTarget;
6551
- const isActive = ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.activeIndex) === index;
6552
- const distance = Math.abs(index - activeIndex);
6553
- if (isActive) {
6554
- if (target.currentTime >= videoDurationLimit) {
6555
- target.currentTime = 0;
6556
- target.pause();
6557
- (_b = swiperRef.current) === null || _b === void 0 ? void 0 : _b.slideNext();
6558
- }
6652
+ }, 100);
6653
+ return () => clearTimeout(timer);
6559
6654
  }
6560
- else if (distance <= preloadDistance && target.currentTime >= previewDuration) {
6561
- target.currentTime = 0;
6562
- target.play().catch((error) => console.warn('Preview video replay failed:', error));
6655
+ }, [currentIndex]);
6656
+ useEffect(() => {
6657
+ if (!swiperRef.current || swiperRef.current.destroyed)
6658
+ return;
6659
+ swiperRef.current.update();
6660
+ if (swiperRef.current.virtual) {
6661
+ swiperRef.current.virtual.update(true);
6563
6662
  }
6564
- };
6565
- return (React.createElement("section", { ref: containerRef, className: "react-riyils__container", "data-height-mobile": true, "data-height-desktop": true, "aria-label": "Video carousel", style: {
6566
- '--container-height-mobile': `${containerHeightMobile}px`,
6567
- '--container-height-desktop': `${containerHeightDesktop}px`,
6568
- } },
6569
- React.createElement(Swiper, { modules: [Navigation, Keyboard, EffectCoverflow, Mousewheel], onSwiper: (swiper) => {
6570
- swiperRef.current = swiper;
6571
- }, onSlideChange: handleSlideChange, className: "react-riyils", slidesPerView: "auto", slidesPerGroup: 1, centeredSlides: true, centerInsufficientSlides: true, spaceBetween: 0, loop: false, initialSlide: currentIndex, speed: 800, threshold: 10, touchRatio: 1, touchAngle: 45, followFinger: true, shortSwipes: true, longSwipes: true, longSwipesRatio: 0.3, longSwipesMs: 300, preventInteractionOnTransition: true, touchStartPreventDefault: false, cssMode: false, keyboard: { enabled: true }, navigation: false, mousewheel: false, effect: "coverflow", resistance: true, resistanceRatio: 0, coverflowEffect: {
6663
+ }, [videos.length]);
6664
+ const handleSlideChange = useCallback((swiper) => {
6665
+ requestAnimationFrame(() => {
6666
+ if (swiper.activeIndex !== currentIndex) {
6667
+ setActiveIndex(swiper.activeIndex);
6668
+ onVideoChange(swiper.activeIndex);
6669
+ }
6670
+ });
6671
+ }, [onVideoChange, currentIndex]);
6672
+ return (React.createElement("section", { className: "react-riyils__container", style: containerStyle, "aria-label": t.carouselAriaLabel },
6673
+ React.createElement(Swiper, { modules: [Keyboard, Mousewheel, EffectCoverflow, Virtual], observer: true, observeParents: true, watchSlidesProgress: true, initialSlide: currentIndex, virtual: {
6674
+ addSlidesBefore: 4,
6675
+ addSlidesAfter: 5,
6676
+ enabled: true,
6677
+ cache: false
6678
+ }, effect: "coverflow", coverflowEffect: {
6572
6679
  rotate: 0,
6573
- stretch: dynamicStretch,
6680
+ stretch: -15,
6574
6681
  depth: 100,
6575
- modifier: 1,
6576
- slideShadows: false,
6577
- }, breakpoints: {
6578
- 640: {
6579
- spaceBetween: 0,
6580
- },
6581
- 768: {
6582
- spaceBetween: 0,
6583
- },
6584
- }, style: {
6585
- height: '100%',
6586
- padding: '0',
6587
- } }, videos.map((video, index) => {
6588
- return (React.createElement(SwiperSlide, { key: video.id }, ({ isActive: slideActive }) => {
6589
- return (React.createElement("button", { type: "button", className: `react-riyils__slide-button ${slideActive ? '' : 'react-riyils__slide-button--inactive'}`, onClick: () => {
6590
- var _a;
6591
- if (slideActive) {
6592
- onVideoClick(index);
6593
- }
6594
- else {
6595
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.slideTo(index);
6596
- }
6597
- }, onKeyDown: (e) => {
6598
- var _a;
6599
- if (e.key === 'Enter' || e.key === ' ') {
6600
- e.preventDefault();
6601
- if (slideActive) {
6602
- onVideoClick(index);
6603
- }
6604
- else {
6605
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.slideTo(index);
6606
- }
6682
+ modifier: 2.5,
6683
+ slideShadows: true,
6684
+ }, onSwiper: (s) => {
6685
+ swiperRef.current = s;
6686
+ }, onSlideChange: handleSlideChange, slidesPerView: "auto", centeredSlides: true, grabCursor: true, keyboard: { enabled: true }, mousewheel: { forceToAxis: true }, className: "react-riyils" }, videos.map((video, index) => {
6687
+ const isSelected = index === activeIndex;
6688
+ const distance = Math.abs(index - activeIndex);
6689
+ const shouldLoad = distance < 4;
6690
+ return (React.createElement(SwiperSlide, { key: video.id, virtualIndex: index },
6691
+ React.createElement(SlideItem, { video: video, index: index, isVisualActive: isSelected, onVideoClick: isSelected ? onVideoClick : () => {
6692
+ if (swiperRef.current && !swiperRef.current.destroyed) {
6693
+ swiperRef.current.slideTo(index);
6607
6694
  }
6608
- }, onContextMenu: (e) => e.preventDefault(), "aria-label": `Video ${index + 1}` },
6609
- React.createElement("div", { className: `react-riyils__video-container ${slideActive
6610
- ? 'react-riyils__video-container--active'
6611
- : 'react-riyils__video-container--inactive'}` },
6612
- React.createElement("video", { ref: (el) => {
6613
- videoRefs.current[index] = el;
6614
- }, src: video.videoUrl, className: "react-riyils__video", muted: true, playsInline: true, onContextMenu: (e) => e.preventDefault(), preload: getPreloadStrategy(index, activeIndex, preloadDistance), "aria-label": `Video ${index + 1}`, onLoadStart: () => setVideoLoading(index, true), onLoadedData: (e) => handleVideoLoadedData(e, index), onWaiting: () => setVideoLoading(index, true), onCanPlay: () => setVideoLoading(index, false), onTimeUpdate: (e) => handleTimeUpdate(e, index) }),
6615
- isLoading[index] && slideActive && (React.createElement("div", { className: "react-riyils__loading" },
6616
- React.createElement("div", { className: "react-riyils__spinner" }))),
6617
- !slideActive && (React.createElement(React.Fragment, null,
6618
- React.createElement("div", { className: "react-riyils__overlay-gradient" }),
6619
- React.createElement("div", { className: "react-riyils__overlay-blur" }))),
6620
- slideActive && (React.createElement("div", { className: "react-riyils__cta-container" },
6621
- React.createElement("button", { onClick: (e) => {
6622
- e.stopPropagation();
6623
- onVideoClick(index);
6624
- }, "aria-label": translations.watchFullVideo, className: "react-riyils__cta-button" },
6625
- React.createElement("div", { className: "react-riyils__cta-badge" },
6626
- React.createElement(Play, { className: "react-riyils__cta-icon", fill: "currentColor", strokeWidth: 0 }),
6627
- React.createElement("span", { className: "react-riyils__cta-text" }, translations.watchFullVideo))))))));
6628
- }));
6695
+ }, t: t, shouldLoad: isSelected || shouldLoad })));
6629
6696
  }))));
6630
6697
  }
6631
- // Custom Hooks
6632
- function useVideoPreload(videoRefs, activeIndex, preloadDistance = PRELOAD_DISTANCE) {
6633
- useEffect(() => {
6634
- videoRefs.current.forEach((video, index) => {
6635
- if (!video)
6636
- return;
6637
- const distance = Math.abs(index - activeIndex);
6638
- if (distance <= preloadDistance) {
6639
- video.preload = 'auto';
6640
- }
6641
- else if (distance <= 2) {
6642
- video.preload = 'metadata';
6643
- }
6644
- else {
6645
- video.preload = 'none';
6646
- }
6647
- });
6648
- }, [activeIndex, preloadDistance, videoRefs]);
6649
- }
6650
- function useVideoControls(videoElement, isActive, autoPlay = true) {
6651
- const [isPlaying, setIsPlaying] = useState(false);
6652
- const [progress, setProgress] = useState(0);
6653
- useEffect(() => {
6654
- if (!videoElement)
6655
- return;
6656
- const handlePlay = () => setIsPlaying(true);
6657
- const handlePause = () => setIsPlaying(false);
6658
- const handleTimeUpdate = () => {
6659
- const prog = (videoElement.currentTime / videoElement.duration) * 100;
6660
- setProgress(prog || 0);
6661
- };
6662
- videoElement.addEventListener('play', handlePlay);
6663
- videoElement.addEventListener('pause', handlePause);
6664
- videoElement.addEventListener('timeupdate', handleTimeUpdate);
6665
- if (isActive && autoPlay && videoElement.paused) {
6666
- videoElement.play().catch(() => { });
6667
- }
6668
- else if (!isActive && !videoElement.paused) {
6669
- videoElement.pause();
6670
- }
6671
- return () => {
6672
- videoElement.removeEventListener('play', handlePlay);
6673
- videoElement.removeEventListener('pause', handlePause);
6674
- videoElement.removeEventListener('timeupdate', handleTimeUpdate);
6675
- };
6676
- }, [videoElement, isActive, autoPlay]);
6677
- const play = () => videoElement === null || videoElement === void 0 ? void 0 : videoElement.play().catch(() => { });
6678
- const pause = () => videoElement === null || videoElement === void 0 ? void 0 : videoElement.pause();
6679
- const togglePlay = () => (isPlaying ? pause() : play());
6680
- const seek = (time) => {
6681
- if (videoElement)
6682
- videoElement.currentTime = time;
6683
- };
6684
- return { isPlaying, progress, play, pause, togglePlay, seek };
6685
- }
6686
- function useSwiperControl(initialIndex = 0) {
6687
- const swiperRef = useRef(null);
6688
- const [currentIndex, setCurrentIndex] = useState(initialIndex);
6689
- const goToSlide = (index, speed) => {
6690
- var _a;
6691
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.slideTo(index, speed);
6692
- };
6693
- const nextSlide = () => {
6694
- var _a;
6695
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.slideNext();
6696
- };
6697
- const prevSlide = () => {
6698
- var _a;
6699
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.slidePrev();
6700
- };
6701
- const updateSlider = () => {
6702
- var _a;
6703
- (_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.update();
6704
- };
6705
- return {
6706
- swiperRef,
6707
- currentIndex,
6708
- setCurrentIndex,
6709
- goToSlide,
6710
- nextSlide,
6711
- prevSlide,
6712
- updateSlider,
6713
- };
6714
- }
6715
6698
 
6716
- export { CONTAINER_HEIGHT_DESKTOP, CONTAINER_HEIGHT_MOBILE, PRELOAD_DISTANCE, PREVIEW_DURATION, ReactRiyils, RiyilsViewer, VIDEO_DURATION_LIMIT, defaultReactRiyilsTranslations, getPreloadStrategy, handleVideoPlayWithFallback, safePlayVideo, useSwiperControl, useVideoControls, useVideoPreload };
6699
+ export { ReactRiyils, RiyilsViewer, defaultReactRiyilsTranslations, defaultRiyilsTranslations };
6717
6700
  //# sourceMappingURL=index.esm.js.map