kopia lustrzana https://github.com/shoelace-style/shoelace
fix(carousel): remove check for scrolling (#1862)
rodzic
dafb35c6e2
commit
7e38e93ab2
|
@ -476,7 +476,7 @@ export default class SlCarousel extends ShoelaceElement {
|
||||||
this.scrollToSlide(nextSlide, prefersReducedMotion() ? 'auto' : behavior);
|
this.scrollToSlide(nextSlide, prefersReducedMotion() ? 'auto' : behavior);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async scrollToSlide(slide: HTMLElement, behavior: ScrollBehavior = 'smooth') {
|
private scrollToSlide(slide: HTMLElement, behavior: ScrollBehavior = 'smooth') {
|
||||||
const scrollContainer = this.scrollContainer;
|
const scrollContainer = this.scrollContainer;
|
||||||
const scrollContainerRect = scrollContainer.getBoundingClientRect();
|
const scrollContainerRect = scrollContainer.getBoundingClientRect();
|
||||||
const nextSlideRect = slide.getBoundingClientRect();
|
const nextSlideRect = slide.getBoundingClientRect();
|
||||||
|
@ -484,16 +484,11 @@ export default class SlCarousel extends ShoelaceElement {
|
||||||
const nextLeft = nextSlideRect.left - scrollContainerRect.left;
|
const nextLeft = nextSlideRect.left - scrollContainerRect.left;
|
||||||
const nextTop = nextSlideRect.top - scrollContainerRect.top;
|
const nextTop = nextSlideRect.top - scrollContainerRect.top;
|
||||||
|
|
||||||
// If the slide is already in view, don't need to scroll
|
scrollContainer.scrollTo({
|
||||||
if (nextLeft !== scrollContainer.scrollLeft || nextTop !== scrollContainer.scrollTop) {
|
left: nextLeft + scrollContainer.scrollLeft,
|
||||||
scrollContainer.scrollTo({
|
top: nextTop + scrollContainer.scrollTop,
|
||||||
left: nextLeft + scrollContainer.scrollLeft,
|
behavior
|
||||||
top: nextTop + scrollContainer.scrollTop,
|
});
|
||||||
behavior
|
|
||||||
});
|
|
||||||
|
|
||||||
await waitForEvent(scrollContainer, 'scrollend');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import '../../../dist/shoelace.js';
|
import '../../../dist/shoelace.js';
|
||||||
import { clickOnElement, dragElement, moveMouseOnElement } from '../../internal/test.js';
|
import { clickOnElement, dragElement, moveMouseOnElement } from '../../internal/test.js';
|
||||||
import { expect, fixture, html, oneEvent } from '@open-wc/testing';
|
import { expect, fixture, html, nextFrame, oneEvent } from '@open-wc/testing';
|
||||||
import { map } from 'lit/directives/map.js';
|
import { map } from 'lit/directives/map.js';
|
||||||
import { range } from 'lit/directives/range.js';
|
import { range } from 'lit/directives/range.js';
|
||||||
import { resetMouse } from '@web/test-runner-commands';
|
import { resetMouse } from '@web/test-runner-commands';
|
||||||
|
@ -8,10 +8,16 @@ import sinon from 'sinon';
|
||||||
import type SlCarousel from './carousel.js';
|
import type SlCarousel from './carousel.js';
|
||||||
|
|
||||||
describe('<sl-carousel>', () => {
|
describe('<sl-carousel>', () => {
|
||||||
|
const sandbox = sinon.createSandbox();
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await resetMouse();
|
await resetMouse();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
it('should render a carousel with default configuration', async () => {
|
it('should render a carousel with default configuration', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const el = await fixture(html`
|
const el = await fixture(html`
|
||||||
|
@ -34,15 +40,11 @@ describe('<sl-carousel>', () => {
|
||||||
let clock: sinon.SinonFakeTimers;
|
let clock: sinon.SinonFakeTimers;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
clock = sinon.useFakeTimers({
|
clock = sandbox.useFakeTimers({
|
||||||
now: new Date()
|
now: new Date()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
clock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should scroll forwards every `autoplay-interval` milliseconds', async () => {
|
it('should scroll forwards every `autoplay-interval` milliseconds', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const el = await fixture<SlCarousel>(html`
|
const el = await fixture<SlCarousel>(html`
|
||||||
|
@ -52,7 +54,7 @@ describe('<sl-carousel>', () => {
|
||||||
<sl-carousel-item>Node 3</sl-carousel-item>
|
<sl-carousel-item>Node 3</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
sinon.stub(el, 'next');
|
sandbox.stub(el, 'next');
|
||||||
|
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
|
@ -73,7 +75,7 @@ describe('<sl-carousel>', () => {
|
||||||
<sl-carousel-item>Node 3</sl-carousel-item>
|
<sl-carousel-item>Node 3</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
sinon.stub(el, 'next');
|
sandbox.stub(el, 'next');
|
||||||
|
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
|
@ -96,7 +98,7 @@ describe('<sl-carousel>', () => {
|
||||||
<sl-carousel-item>Node 3</sl-carousel-item>
|
<sl-carousel-item>Node 3</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
sinon.stub(el, 'next');
|
sandbox.stub(el, 'next');
|
||||||
|
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
|
@ -183,7 +185,7 @@ describe('<sl-carousel>', () => {
|
||||||
<sl-carousel-item>Node 3</sl-carousel-item>
|
<sl-carousel-item>Node 3</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
sinon.stub(el, 'goToSlide');
|
sandbox.stub(el, 'goToSlide');
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -473,7 +475,7 @@ describe('<sl-carousel>', () => {
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
const nextButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--next')!;
|
const nextButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--next')!;
|
||||||
sinon.stub(el, 'next');
|
sandbox.stub(el, 'next');
|
||||||
|
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
|
@ -496,7 +498,7 @@ describe('<sl-carousel>', () => {
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
const nextButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--next')!;
|
const nextButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--next')!;
|
||||||
sinon.stub(el, 'next');
|
sandbox.stub(el, 'next');
|
||||||
|
|
||||||
el.goToSlide(2, 'auto');
|
el.goToSlide(2, 'auto');
|
||||||
await oneEvent(el.scrollContainer, 'scrollend');
|
await oneEvent(el.scrollContainer, 'scrollend');
|
||||||
|
@ -560,7 +562,7 @@ describe('<sl-carousel>', () => {
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
const previousButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--previous')!;
|
const previousButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--previous')!;
|
||||||
sinon.stub(el, 'previous');
|
sandbox.stub(el, 'previous');
|
||||||
|
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
|
@ -584,7 +586,7 @@ describe('<sl-carousel>', () => {
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const previousButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--previous')!;
|
const previousButton: HTMLElement = el.shadowRoot!.querySelector('.carousel__navigation-button--previous')!;
|
||||||
sinon.stub(el, 'previous');
|
sandbox.stub(el, 'previous');
|
||||||
await el.updateComplete;
|
await el.updateComplete;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -632,19 +634,27 @@ describe('<sl-carousel>', () => {
|
||||||
it('should scroll the carousel to the next slide', async () => {
|
it('should scroll the carousel to the next slide', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const el = await fixture<SlCarousel>(html`
|
const el = await fixture<SlCarousel>(html`
|
||||||
<sl-carousel slides-per-page="2" slides-per-move="2">
|
<sl-carousel>
|
||||||
<sl-carousel-item>Node 1</sl-carousel-item>
|
<sl-carousel-item>Node 1</sl-carousel-item>
|
||||||
<sl-carousel-item>Node 2</sl-carousel-item>
|
<sl-carousel-item>Node 2</sl-carousel-item>
|
||||||
<sl-carousel-item>Node 3</sl-carousel-item>
|
<sl-carousel-item>Node 3</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
sinon.stub(el, 'goToSlide');
|
sandbox.spy(el, 'goToSlide');
|
||||||
await el.updateComplete;
|
const expectedCarouselItem: HTMLElement = el.querySelector('sl-carousel-item:nth-child(2)')!;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
el.next();
|
el.next();
|
||||||
|
await oneEvent(el.scrollContainer, 'scrollend');
|
||||||
|
await el.updateComplete;
|
||||||
|
|
||||||
expect(el.goToSlide).to.have.been.calledWith(2);
|
const containerRect = el.scrollContainer.getBoundingClientRect();
|
||||||
|
const itemRect = expectedCarouselItem.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(el.goToSlide).to.have.been.calledWith(1);
|
||||||
|
expect(itemRect.top).to.be.equal(containerRect.top);
|
||||||
|
expect(itemRect.left).to.be.equal(containerRect.left);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -652,19 +662,32 @@ describe('<sl-carousel>', () => {
|
||||||
it('should scroll the carousel to the previous slide', async () => {
|
it('should scroll the carousel to the previous slide', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const el = await fixture<SlCarousel>(html`
|
const el = await fixture<SlCarousel>(html`
|
||||||
<sl-carousel slides-per-page="2" slides-per-move="2">
|
<sl-carousel>
|
||||||
<sl-carousel-item>Node 1</sl-carousel-item>
|
<sl-carousel-item>Node 1</sl-carousel-item>
|
||||||
<sl-carousel-item>Node 2</sl-carousel-item>
|
<sl-carousel-item>Node 2</sl-carousel-item>
|
||||||
<sl-carousel-item>Node 3</sl-carousel-item>
|
<sl-carousel-item>Node 3</sl-carousel-item>
|
||||||
</sl-carousel>
|
</sl-carousel>
|
||||||
`);
|
`);
|
||||||
sinon.stub(el, 'goToSlide');
|
const expectedCarouselItem: HTMLElement = el.querySelector('sl-carousel-item:nth-child(1)')!;
|
||||||
await el.updateComplete;
|
|
||||||
|
el.goToSlide(1);
|
||||||
|
|
||||||
|
await oneEvent(el.scrollContainer, 'scrollend');
|
||||||
|
await nextFrame();
|
||||||
|
|
||||||
|
sandbox.spy(el, 'goToSlide');
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
el.previous();
|
el.previous();
|
||||||
|
await oneEvent(el.scrollContainer, 'scrollend');
|
||||||
|
|
||||||
expect(el.goToSlide).to.have.been.calledWith(-2);
|
const containerRect = el.scrollContainer.getBoundingClientRect();
|
||||||
|
const itemRect = expectedCarouselItem.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(el.goToSlide).to.have.been.calledWith(0);
|
||||||
|
expect(itemRect.top).to.be.equal(containerRect.top);
|
||||||
|
expect(itemRect.left).to.be.equal(containerRect.left);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue