mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
backport SL-2220
This commit is contained in:
@@ -102,6 +102,7 @@ export default class WaCarousel extends WebAwesomeElement {
|
||||
private dragStartPosition: [number, number] = [-1, -1];
|
||||
private readonly localize = new LocalizeController(this);
|
||||
private mutationObserver: MutationObserver;
|
||||
private pendingSlideChange = false;
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
@@ -285,6 +286,9 @@ export default class WaCarousel extends WebAwesomeElement {
|
||||
@eventOptions({ passive: true })
|
||||
private handleScroll() {
|
||||
this.scrolling = true;
|
||||
if (!this.pendingSlideChange) {
|
||||
this.synchronizeSlides();
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal Synchronizes the slides with the IntersectionObserver API. */
|
||||
@@ -302,18 +306,29 @@ export default class WaCarousel extends WebAwesomeElement {
|
||||
|
||||
const firstIntersecting = entries.find(entry => entry.isIntersecting);
|
||||
|
||||
if (firstIntersecting) {
|
||||
if (this.loop && firstIntersecting.target.hasAttribute('data-clone')) {
|
||||
const clonePosition = Number(firstIntersecting.target.getAttribute('data-clone'));
|
||||
// Scrolls to the original slide without animating, so the user won't notice that the position has changed
|
||||
this.goToSlide(clonePosition, 'instant');
|
||||
} else {
|
||||
const slides = this.getSlides();
|
||||
if (!firstIntersecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the current index based on the first visible slide
|
||||
const slideIndex = slides.indexOf(firstIntersecting.target as WaCarouselItem);
|
||||
// Set the index to the first "snappable" slide
|
||||
this.activeSlide = Math.ceil(slideIndex / this.slidesPerMove) * this.slidesPerMove;
|
||||
const slidesWithClones = this.getSlides({ excludeClones: false });
|
||||
const slidesCount = this.getSlides().length;
|
||||
|
||||
// Update the current index based on the first visible slide
|
||||
const slideIndex = slidesWithClones.indexOf(firstIntersecting.target as WaCarouselItem);
|
||||
// Normalize the index to ignore clones
|
||||
const normalizedIndex = this.loop ? slideIndex - this.slidesPerPage : slideIndex;
|
||||
|
||||
if (firstIntersecting) {
|
||||
// Set the index to the closest "snappable" slide
|
||||
this.activeSlide =
|
||||
(Math.ceil(normalizedIndex / this.slidesPerMove) * this.slidesPerMove + slidesCount) % slidesCount;
|
||||
|
||||
if (!this.scrolling) {
|
||||
if (this.loop && firstIntersecting.target.hasAttribute('data-clone')) {
|
||||
const clonePosition = Number(firstIntersecting.target.getAttribute('data-clone'));
|
||||
// Scrolls to the original slide without animating, so the user won't notice that the position has changed
|
||||
this.goToSlide(clonePosition, 'instant');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -334,6 +349,8 @@ export default class WaCarousel extends WebAwesomeElement {
|
||||
this.synchronizeSlides();
|
||||
|
||||
this.scrolling = false;
|
||||
this.pendingSlideChange = false;
|
||||
this.synchronizeSlides();
|
||||
}
|
||||
|
||||
private isCarouselItem(node: Node): node is WaCarouselItem {
|
||||
@@ -403,7 +420,7 @@ export default class WaCarousel extends WebAwesomeElement {
|
||||
}
|
||||
|
||||
@watch('activeSlide')
|
||||
handelSlideChange() {
|
||||
handleSlideChange() {
|
||||
const slides = this.getSlides();
|
||||
slides.forEach((slide, i) => {
|
||||
slide.classList.toggle('--is-active', i === this.activeSlide);
|
||||
@@ -508,11 +525,14 @@ export default class WaCarousel extends WebAwesomeElement {
|
||||
const nextLeft = nextSlideRect.left - scrollContainerRect.left;
|
||||
const nextTop = nextSlideRect.top - scrollContainerRect.top;
|
||||
|
||||
scrollContainer.scrollTo({
|
||||
left: nextLeft + scrollContainer.scrollLeft,
|
||||
top: nextTop + scrollContainer.scrollTop,
|
||||
behavior
|
||||
});
|
||||
if (nextLeft || nextTop) {
|
||||
this.pendingSlideChange = true;
|
||||
scrollContainer.scrollTo({
|
||||
left: nextLeft + scrollContainer.scrollLeft,
|
||||
top: nextTop + scrollContainer.scrollTop,
|
||||
behavior
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
Reference in New Issue
Block a user