lazer-slider 1.0.5 → 1.0.7
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/README.md +0 -1
- package/dist/index.cjs +240 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +240 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -6,6 +6,10 @@ type EasingFunction = (t: number) => number;
|
|
|
6
6
|
* Direction of slider navigation
|
|
7
7
|
*/
|
|
8
8
|
type SliderDirection = 'prev' | 'next';
|
|
9
|
+
/**
|
|
10
|
+
* Direction of marquee scroll
|
|
11
|
+
*/
|
|
12
|
+
type MarqueeDirection = 'left' | 'right';
|
|
9
13
|
/**
|
|
10
14
|
* Parameters passed to scroll start callback
|
|
11
15
|
*/
|
|
@@ -64,6 +68,12 @@ interface SliderSettings {
|
|
|
64
68
|
autoplayInterval?: number;
|
|
65
69
|
/** Pause autoplay on hover/touch (default: true) */
|
|
66
70
|
pauseOnHover?: boolean;
|
|
71
|
+
/** Enable marquee mode (continuous scroll, overrides autoplay/loop) */
|
|
72
|
+
marquee?: boolean;
|
|
73
|
+
/** Marquee scroll speed in pixels per second (default: 50) */
|
|
74
|
+
marqueeSpeed?: number;
|
|
75
|
+
/** Marquee scroll direction (default: 'left') */
|
|
76
|
+
marqueeDirection?: MarqueeDirection;
|
|
67
77
|
/** Custom easing function for smooth scroll animation */
|
|
68
78
|
easing?: EasingFunction;
|
|
69
79
|
/** Callback fired when scroll animation starts */
|
|
@@ -97,6 +107,12 @@ interface SliderState {
|
|
|
97
107
|
autoplayIntervalId: ReturnType<typeof setInterval> | null;
|
|
98
108
|
/** Whether autoplay is currently paused */
|
|
99
109
|
autoplayPaused: boolean;
|
|
110
|
+
/** Animation frame ID for marquee */
|
|
111
|
+
marqueeAnimationId: number | null;
|
|
112
|
+
/** Whether marquee is currently paused */
|
|
113
|
+
marqueePaused: boolean;
|
|
114
|
+
/** Last timestamp for marquee animation (for delta time calculation) */
|
|
115
|
+
marqueeLastTimestamp: number;
|
|
100
116
|
}
|
|
101
117
|
/**
|
|
102
118
|
* Drag state for drag-to-scroll functionality
|
|
@@ -164,4 +180,4 @@ declare const easeOutQuad: EasingFunction;
|
|
|
164
180
|
*/
|
|
165
181
|
declare const linear: EasingFunction;
|
|
166
182
|
|
|
167
|
-
export { type DragState, type EasingFunction, type ScrollParams, type ScrollStartParams, type Slider, type SliderDirection, type SliderSettings, type SliderState, createSlider, easeInOutCubic, easeOutCubic, easeOutExpo, easeOutQuad, linear };
|
|
183
|
+
export { type DragState, type EasingFunction, type MarqueeDirection, type ScrollParams, type ScrollStartParams, type Slider, type SliderDirection, type SliderSettings, type SliderState, createSlider, easeInOutCubic, easeOutCubic, easeOutExpo, easeOutQuad, linear };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,10 @@ type EasingFunction = (t: number) => number;
|
|
|
6
6
|
* Direction of slider navigation
|
|
7
7
|
*/
|
|
8
8
|
type SliderDirection = 'prev' | 'next';
|
|
9
|
+
/**
|
|
10
|
+
* Direction of marquee scroll
|
|
11
|
+
*/
|
|
12
|
+
type MarqueeDirection = 'left' | 'right';
|
|
9
13
|
/**
|
|
10
14
|
* Parameters passed to scroll start callback
|
|
11
15
|
*/
|
|
@@ -64,6 +68,12 @@ interface SliderSettings {
|
|
|
64
68
|
autoplayInterval?: number;
|
|
65
69
|
/** Pause autoplay on hover/touch (default: true) */
|
|
66
70
|
pauseOnHover?: boolean;
|
|
71
|
+
/** Enable marquee mode (continuous scroll, overrides autoplay/loop) */
|
|
72
|
+
marquee?: boolean;
|
|
73
|
+
/** Marquee scroll speed in pixels per second (default: 50) */
|
|
74
|
+
marqueeSpeed?: number;
|
|
75
|
+
/** Marquee scroll direction (default: 'left') */
|
|
76
|
+
marqueeDirection?: MarqueeDirection;
|
|
67
77
|
/** Custom easing function for smooth scroll animation */
|
|
68
78
|
easing?: EasingFunction;
|
|
69
79
|
/** Callback fired when scroll animation starts */
|
|
@@ -97,6 +107,12 @@ interface SliderState {
|
|
|
97
107
|
autoplayIntervalId: ReturnType<typeof setInterval> | null;
|
|
98
108
|
/** Whether autoplay is currently paused */
|
|
99
109
|
autoplayPaused: boolean;
|
|
110
|
+
/** Animation frame ID for marquee */
|
|
111
|
+
marqueeAnimationId: number | null;
|
|
112
|
+
/** Whether marquee is currently paused */
|
|
113
|
+
marqueePaused: boolean;
|
|
114
|
+
/** Last timestamp for marquee animation (for delta time calculation) */
|
|
115
|
+
marqueeLastTimestamp: number;
|
|
100
116
|
}
|
|
101
117
|
/**
|
|
102
118
|
* Drag state for drag-to-scroll functionality
|
|
@@ -164,4 +180,4 @@ declare const easeOutQuad: EasingFunction;
|
|
|
164
180
|
*/
|
|
165
181
|
declare const linear: EasingFunction;
|
|
166
182
|
|
|
167
|
-
export { type DragState, type EasingFunction, type ScrollParams, type ScrollStartParams, type Slider, type SliderDirection, type SliderSettings, type SliderState, createSlider, easeInOutCubic, easeOutCubic, easeOutExpo, easeOutQuad, linear };
|
|
183
|
+
export { type DragState, type EasingFunction, type MarqueeDirection, type ScrollParams, type ScrollStartParams, type Slider, type SliderDirection, type SliderSettings, type SliderState, createSlider, easeInOutCubic, easeOutCubic, easeOutExpo, easeOutQuad, linear };
|
package/dist/index.js
CHANGED
|
@@ -234,6 +234,108 @@ var cleanupDrag = (state) => {
|
|
|
234
234
|
}
|
|
235
235
|
};
|
|
236
236
|
|
|
237
|
+
// src/core/marquee.ts
|
|
238
|
+
var createMarqueeState = () => ({
|
|
239
|
+
initialized: false,
|
|
240
|
+
clonedSlides: []
|
|
241
|
+
});
|
|
242
|
+
var setupMarqueeClones = (settings, marqueeState) => {
|
|
243
|
+
if (marqueeState.initialized) return;
|
|
244
|
+
settings.slides.forEach((slide) => {
|
|
245
|
+
const clone = slide.cloneNode(true);
|
|
246
|
+
clone.setAttribute("data-lazer-marquee-clone", "true");
|
|
247
|
+
clone.setAttribute("aria-hidden", "true");
|
|
248
|
+
settings.feed.appendChild(clone);
|
|
249
|
+
marqueeState.clonedSlides.push(clone);
|
|
250
|
+
});
|
|
251
|
+
marqueeState.initialized = true;
|
|
252
|
+
};
|
|
253
|
+
var cleanupMarqueeClones = (marqueeState) => {
|
|
254
|
+
if (!marqueeState.initialized) return;
|
|
255
|
+
marqueeState.clonedSlides.forEach((clone) => {
|
|
256
|
+
clone.remove();
|
|
257
|
+
});
|
|
258
|
+
marqueeState.clonedSlides = [];
|
|
259
|
+
marqueeState.initialized = false;
|
|
260
|
+
};
|
|
261
|
+
var handleMarqueeLoop = (settings) => {
|
|
262
|
+
const direction = settings.marqueeDirection ?? "left";
|
|
263
|
+
const halfWidth = settings.feed.scrollWidth / 2;
|
|
264
|
+
if (direction === "left") {
|
|
265
|
+
if (settings.feed.scrollLeft >= halfWidth) {
|
|
266
|
+
settings.feed.scrollLeft = settings.feed.scrollLeft - halfWidth;
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
if (settings.feed.scrollLeft <= 0) {
|
|
270
|
+
settings.feed.scrollLeft = halfWidth;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
var startMarquee = (settings, state) => {
|
|
275
|
+
if (state.marqueeAnimationId) return;
|
|
276
|
+
const speed = settings.marqueeSpeed ?? 50;
|
|
277
|
+
const direction = settings.marqueeDirection ?? "left";
|
|
278
|
+
const directionMultiplier = direction === "left" ? 1 : -1;
|
|
279
|
+
if (direction === "right") {
|
|
280
|
+
settings.feed.scrollLeft = settings.feed.scrollWidth / 2;
|
|
281
|
+
}
|
|
282
|
+
const animate = (timestamp) => {
|
|
283
|
+
if (state.marqueePaused) {
|
|
284
|
+
state.marqueeLastTimestamp = timestamp;
|
|
285
|
+
state.marqueeAnimationId = requestAnimationFrame(animate);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const deltaTime = state.marqueeLastTimestamp ? (timestamp - state.marqueeLastTimestamp) / 1e3 : 0;
|
|
289
|
+
state.marqueeLastTimestamp = timestamp;
|
|
290
|
+
const movement = speed * deltaTime * directionMultiplier;
|
|
291
|
+
settings.feed.scrollLeft += movement;
|
|
292
|
+
handleMarqueeLoop(settings);
|
|
293
|
+
state.marqueeAnimationId = requestAnimationFrame(animate);
|
|
294
|
+
};
|
|
295
|
+
state.marqueeAnimationId = requestAnimationFrame(animate);
|
|
296
|
+
};
|
|
297
|
+
var stopMarquee = (state) => {
|
|
298
|
+
if (state.marqueeAnimationId) {
|
|
299
|
+
cancelAnimationFrame(state.marqueeAnimationId);
|
|
300
|
+
state.marqueeAnimationId = null;
|
|
301
|
+
}
|
|
302
|
+
state.marqueeLastTimestamp = 0;
|
|
303
|
+
};
|
|
304
|
+
var pauseMarquee = (state) => {
|
|
305
|
+
state.marqueePaused = true;
|
|
306
|
+
};
|
|
307
|
+
var resumeMarquee = (state) => {
|
|
308
|
+
state.marqueePaused = false;
|
|
309
|
+
};
|
|
310
|
+
var setupMarquee = (settings, state, marqueeState) => {
|
|
311
|
+
if (!settings.marquee) return;
|
|
312
|
+
setupMarqueeClones(settings, marqueeState);
|
|
313
|
+
startMarquee(settings, state);
|
|
314
|
+
};
|
|
315
|
+
var attachMarqueeEventListeners = (settings, state, signal) => {
|
|
316
|
+
if (!settings.marquee || settings.pauseOnHover === false) return;
|
|
317
|
+
settings.feed.addEventListener(
|
|
318
|
+
"mouseenter",
|
|
319
|
+
() => pauseMarquee(state),
|
|
320
|
+
{ signal }
|
|
321
|
+
);
|
|
322
|
+
settings.feed.addEventListener(
|
|
323
|
+
"mouseleave",
|
|
324
|
+
() => resumeMarquee(state),
|
|
325
|
+
{ signal }
|
|
326
|
+
);
|
|
327
|
+
settings.feed.addEventListener(
|
|
328
|
+
"touchstart",
|
|
329
|
+
() => pauseMarquee(state),
|
|
330
|
+
{ passive: true, signal }
|
|
331
|
+
);
|
|
332
|
+
settings.feed.addEventListener(
|
|
333
|
+
"touchend",
|
|
334
|
+
() => resumeMarquee(state),
|
|
335
|
+
{ signal }
|
|
336
|
+
);
|
|
337
|
+
};
|
|
338
|
+
|
|
237
339
|
// src/core/slider.ts
|
|
238
340
|
var ANIMATION = {
|
|
239
341
|
MIN_DURATION: 400,
|
|
@@ -260,9 +362,19 @@ var createSlider = (settings) => {
|
|
|
260
362
|
scrollEndTimeout: null,
|
|
261
363
|
abortController: new AbortController(),
|
|
262
364
|
autoplayIntervalId: null,
|
|
263
|
-
autoplayPaused: false
|
|
365
|
+
autoplayPaused: false,
|
|
366
|
+
marqueeAnimationId: null,
|
|
367
|
+
marqueePaused: false,
|
|
368
|
+
marqueeLastTimestamp: 0
|
|
264
369
|
};
|
|
265
370
|
let dragState = null;
|
|
371
|
+
const loopState = {
|
|
372
|
+
initialized: false,
|
|
373
|
+
clonedSlides: [],
|
|
374
|
+
realSlides: [...settings.slides],
|
|
375
|
+
clonesPerSide: 0
|
|
376
|
+
};
|
|
377
|
+
const marqueeState = createMarqueeState();
|
|
266
378
|
const easing = settings.easing ?? easeOutExpo;
|
|
267
379
|
const getFeedRect = () => {
|
|
268
380
|
const currentWidth = settings.feed.clientWidth;
|
|
@@ -278,6 +390,71 @@ var createSlider = (settings) => {
|
|
|
278
390
|
const isDesktop = () => {
|
|
279
391
|
return window.matchMedia(DESKTOP_BREAKPOINT).matches;
|
|
280
392
|
};
|
|
393
|
+
const getLoopClonesCount = () => {
|
|
394
|
+
const perView = isDesktop() ? settings.desktopSlidesPerView : settings.mobileSlidesPerView;
|
|
395
|
+
if (!perView || perView === "auto") {
|
|
396
|
+
return 1;
|
|
397
|
+
}
|
|
398
|
+
return Math.ceil(perView);
|
|
399
|
+
};
|
|
400
|
+
const setupLoopClones = () => {
|
|
401
|
+
if (!settings.loop || loopState.initialized) return;
|
|
402
|
+
const realSlides = loopState.realSlides;
|
|
403
|
+
const clonesCount = getLoopClonesCount();
|
|
404
|
+
loopState.clonesPerSide = clonesCount;
|
|
405
|
+
for (let i = realSlides.length - clonesCount; i < realSlides.length; i++) {
|
|
406
|
+
const slide = realSlides[i];
|
|
407
|
+
if (!slide) continue;
|
|
408
|
+
const clone = slide.cloneNode(true);
|
|
409
|
+
clone.setAttribute("data-lazer-clone", "prepend");
|
|
410
|
+
clone.setAttribute("aria-hidden", "true");
|
|
411
|
+
settings.feed.insertBefore(clone, settings.feed.firstChild);
|
|
412
|
+
loopState.clonedSlides.push(clone);
|
|
413
|
+
}
|
|
414
|
+
for (let i = 0; i < clonesCount; i++) {
|
|
415
|
+
const slide = realSlides[i];
|
|
416
|
+
if (!slide) continue;
|
|
417
|
+
const clone = slide.cloneNode(true);
|
|
418
|
+
clone.setAttribute("data-lazer-clone", "append");
|
|
419
|
+
clone.setAttribute("aria-hidden", "true");
|
|
420
|
+
settings.feed.appendChild(clone);
|
|
421
|
+
loopState.clonedSlides.push(clone);
|
|
422
|
+
}
|
|
423
|
+
requestAnimationFrame(() => {
|
|
424
|
+
const firstRealSlide = realSlides[0];
|
|
425
|
+
if (firstRealSlide) {
|
|
426
|
+
settings.feed.scrollLeft = firstRealSlide.offsetLeft;
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
loopState.initialized = true;
|
|
430
|
+
};
|
|
431
|
+
const handleLoopReposition = (direction) => {
|
|
432
|
+
if (!settings.loop || !loopState.initialized) return;
|
|
433
|
+
const realSlides = loopState.realSlides;
|
|
434
|
+
const totalRealSlides = realSlides.length;
|
|
435
|
+
if (direction === "next") {
|
|
436
|
+
const firstRealSlide = realSlides[0];
|
|
437
|
+
if (firstRealSlide) {
|
|
438
|
+
settings.feed.scrollLeft = firstRealSlide.offsetLeft;
|
|
439
|
+
}
|
|
440
|
+
state.currentSlideIndex = 0;
|
|
441
|
+
} else {
|
|
442
|
+
const lastRealSlide = realSlides[totalRealSlides - 1];
|
|
443
|
+
if (lastRealSlide) {
|
|
444
|
+
settings.feed.scrollLeft = lastRealSlide.offsetLeft;
|
|
445
|
+
}
|
|
446
|
+
state.currentSlideIndex = totalRealSlides - 1;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
const cleanupLoopClones = () => {
|
|
450
|
+
if (!loopState.initialized) return;
|
|
451
|
+
loopState.clonedSlides.forEach((clone) => {
|
|
452
|
+
clone.remove();
|
|
453
|
+
});
|
|
454
|
+
loopState.clonedSlides = [];
|
|
455
|
+
loopState.initialized = false;
|
|
456
|
+
loopState.clonesPerSide = 0;
|
|
457
|
+
};
|
|
281
458
|
const applySlideWidths = () => {
|
|
282
459
|
const perView = isDesktop() ? settings.desktopSlidesPerView : settings.mobileSlidesPerView;
|
|
283
460
|
const gap = settings.slideGap ?? 0;
|
|
@@ -347,14 +524,14 @@ var createSlider = (settings) => {
|
|
|
347
524
|
};
|
|
348
525
|
const updateCurrentSlideIndex = () => {
|
|
349
526
|
const feedRect = getFeedRect();
|
|
350
|
-
const
|
|
351
|
-
const viewportVisibleSlides =
|
|
527
|
+
const slidesToCheck = loopState.initialized ? loopState.realSlides : getVisibleSlides();
|
|
528
|
+
const viewportVisibleSlides = slidesToCheck.filter((slide) => {
|
|
352
529
|
const slideRect = slide.getBoundingClientRect();
|
|
353
530
|
const tolerance = 20;
|
|
354
531
|
return slideRect.right > feedRect.left + tolerance && slideRect.left < feedRect.right - tolerance;
|
|
355
532
|
});
|
|
356
533
|
if (viewportVisibleSlides.length && viewportVisibleSlides[0]) {
|
|
357
|
-
const newIndex =
|
|
534
|
+
const newIndex = slidesToCheck.indexOf(viewportVisibleSlides[0]);
|
|
358
535
|
if (newIndex !== -1) {
|
|
359
536
|
state.currentSlideIndex = newIndex;
|
|
360
537
|
settings.onScroll?.({
|
|
@@ -364,7 +541,7 @@ var createSlider = (settings) => {
|
|
|
364
541
|
}
|
|
365
542
|
}
|
|
366
543
|
};
|
|
367
|
-
const smoothScrollTo = (target, customEasing = easing) => {
|
|
544
|
+
const smoothScrollTo = (target, customEasing = easing, onComplete) => {
|
|
368
545
|
const start = settings.feed.scrollLeft;
|
|
369
546
|
const distance = Math.abs(target - start);
|
|
370
547
|
const duration = Math.min(
|
|
@@ -381,6 +558,7 @@ var createSlider = (settings) => {
|
|
|
381
558
|
requestAnimationFrame(animateScroll);
|
|
382
559
|
} else {
|
|
383
560
|
settings.feed.scrollLeft = target;
|
|
561
|
+
onComplete?.();
|
|
384
562
|
}
|
|
385
563
|
};
|
|
386
564
|
requestAnimationFrame(animateScroll);
|
|
@@ -401,34 +579,51 @@ var createSlider = (settings) => {
|
|
|
401
579
|
smoothScrollTo(settings.slides[index].offsetLeft);
|
|
402
580
|
};
|
|
403
581
|
const handleNavButtonClick = (direction) => {
|
|
404
|
-
const
|
|
582
|
+
const realSlides = loopState.initialized ? loopState.realSlides : getVisibleSlides();
|
|
405
583
|
const slidesToScroll = isDesktop() ? settings.desktopSlidesPerScroll ?? 1 : settings.mobileSlidesPerScroll ?? 1;
|
|
406
|
-
const
|
|
584
|
+
const totalRealSlides = realSlides.length;
|
|
407
585
|
updateCurrentSlideIndex();
|
|
586
|
+
let targetSlide;
|
|
587
|
+
let needsReposition = false;
|
|
408
588
|
if (direction === "prev") {
|
|
409
|
-
if (settings.loop && state.currentSlideIndex === 0) {
|
|
410
|
-
|
|
589
|
+
if (settings.loop && loopState.initialized && state.currentSlideIndex === 0) {
|
|
590
|
+
const prependedClones = loopState.clonedSlides.filter(
|
|
591
|
+
(clone) => clone.getAttribute("data-lazer-clone") === "prepend"
|
|
592
|
+
);
|
|
593
|
+
targetSlide = prependedClones[prependedClones.length - 1];
|
|
594
|
+
needsReposition = true;
|
|
411
595
|
} else {
|
|
412
596
|
state.currentSlideIndex = Math.max(0, state.currentSlideIndex - slidesToScroll);
|
|
597
|
+
targetSlide = realSlides[state.currentSlideIndex];
|
|
413
598
|
}
|
|
414
599
|
} else {
|
|
415
|
-
if (settings.loop && state.currentSlideIndex >=
|
|
416
|
-
|
|
600
|
+
if (settings.loop && loopState.initialized && state.currentSlideIndex >= totalRealSlides - 1) {
|
|
601
|
+
const appendedClones = loopState.clonedSlides.filter(
|
|
602
|
+
(clone) => clone.getAttribute("data-lazer-clone") === "append"
|
|
603
|
+
);
|
|
604
|
+
targetSlide = appendedClones[0];
|
|
605
|
+
needsReposition = true;
|
|
417
606
|
} else {
|
|
418
607
|
state.currentSlideIndex = Math.min(
|
|
419
|
-
|
|
608
|
+
totalRealSlides - 1,
|
|
420
609
|
state.currentSlideIndex + slidesToScroll
|
|
421
610
|
);
|
|
611
|
+
targetSlide = realSlides[state.currentSlideIndex];
|
|
422
612
|
}
|
|
423
613
|
}
|
|
424
|
-
const targetSlide = visibleSlides[state.currentSlideIndex];
|
|
425
614
|
if (!targetSlide) return;
|
|
426
615
|
settings.onScrollStart?.({
|
|
427
616
|
currentScroll: settings.feed.scrollLeft,
|
|
428
617
|
target: targetSlide,
|
|
429
618
|
direction
|
|
430
619
|
});
|
|
431
|
-
|
|
620
|
+
if (needsReposition) {
|
|
621
|
+
smoothScrollTo(targetSlide.offsetLeft, easing, () => {
|
|
622
|
+
handleLoopReposition(direction);
|
|
623
|
+
});
|
|
624
|
+
} else {
|
|
625
|
+
smoothScrollTo(targetSlide.offsetLeft);
|
|
626
|
+
}
|
|
432
627
|
};
|
|
433
628
|
const updateScrollPosition = () => {
|
|
434
629
|
updateScrollbarPosition();
|
|
@@ -528,6 +723,7 @@ var createSlider = (settings) => {
|
|
|
528
723
|
{ signal }
|
|
529
724
|
);
|
|
530
725
|
}
|
|
726
|
+
attachMarqueeEventListeners(settings, state, signal);
|
|
531
727
|
};
|
|
532
728
|
const startAutoplay = () => {
|
|
533
729
|
if (state.autoplayIntervalId) return;
|
|
@@ -551,9 +747,9 @@ var createSlider = (settings) => {
|
|
|
551
747
|
state.autoplayPaused = false;
|
|
552
748
|
};
|
|
553
749
|
const goToIndex = (index) => {
|
|
554
|
-
const
|
|
555
|
-
const safeIndex = Math.max(0, Math.min(index,
|
|
556
|
-
const targetSlide =
|
|
750
|
+
const slides = loopState.initialized ? loopState.realSlides : getVisibleSlides();
|
|
751
|
+
const safeIndex = Math.max(0, Math.min(index, slides.length - 1));
|
|
752
|
+
const targetSlide = slides[safeIndex];
|
|
557
753
|
if (!targetSlide) return;
|
|
558
754
|
state.currentSlideIndex = safeIndex;
|
|
559
755
|
updateActiveThumb(settings.thumbs, safeIndex);
|
|
@@ -567,6 +763,7 @@ var createSlider = (settings) => {
|
|
|
567
763
|
};
|
|
568
764
|
const unload = () => {
|
|
569
765
|
stopAutoplay();
|
|
766
|
+
stopMarquee(state);
|
|
570
767
|
state.abortController.abort();
|
|
571
768
|
window.removeEventListener("resize", handleWindowResize);
|
|
572
769
|
if (state.updateThumbTimeout) {
|
|
@@ -578,22 +775,43 @@ var createSlider = (settings) => {
|
|
|
578
775
|
if (dragState) {
|
|
579
776
|
cleanupDrag(dragState);
|
|
580
777
|
}
|
|
778
|
+
cleanupLoopClones();
|
|
779
|
+
cleanupMarqueeClones(marqueeState);
|
|
581
780
|
state.cachedFeedRect = null;
|
|
582
781
|
};
|
|
583
782
|
initAria(settings);
|
|
584
783
|
applySlideWidths();
|
|
784
|
+
if (settings.marquee) {
|
|
785
|
+
setupMarquee(settings, state, marqueeState);
|
|
786
|
+
} else {
|
|
787
|
+
setupLoopClones();
|
|
788
|
+
if (settings.autoplay) {
|
|
789
|
+
startAutoplay();
|
|
790
|
+
}
|
|
791
|
+
}
|
|
585
792
|
updateControlsVisibility();
|
|
586
793
|
attachEventListeners();
|
|
587
794
|
updateScrollbar();
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
795
|
+
const play = () => {
|
|
796
|
+
if (settings.marquee) {
|
|
797
|
+
startMarquee(settings, state);
|
|
798
|
+
} else if (settings.autoplay) {
|
|
799
|
+
startAutoplay();
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
const pause = () => {
|
|
803
|
+
if (settings.marquee) {
|
|
804
|
+
stopMarquee(state);
|
|
805
|
+
} else {
|
|
806
|
+
stopAutoplay();
|
|
807
|
+
}
|
|
808
|
+
};
|
|
591
809
|
return {
|
|
592
810
|
goToIndex,
|
|
593
811
|
refresh,
|
|
594
812
|
unload,
|
|
595
|
-
play
|
|
596
|
-
pause
|
|
813
|
+
play,
|
|
814
|
+
pause,
|
|
597
815
|
next: () => handleNavButtonClick("next"),
|
|
598
816
|
prev: () => handleNavButtonClick("prev")
|
|
599
817
|
};
|