diff --git a/.changeset/shaggy-swans-fail.md b/.changeset/shaggy-swans-fail.md new file mode 100644 index 00000000..2066444e --- /dev/null +++ b/.changeset/shaggy-swans-fail.md @@ -0,0 +1,6 @@ +--- +'@boxslider/components': minor +'@boxslider/slider': minor +--- + +Core slider no longer throws error if initialized without slides and calling any transition method will not update the state or attempt to transition. Invalid calls to next or prev etc will return an immediately resolved promise. diff --git a/packages/components/src/SliderControls/SliderControls.ts b/packages/components/src/SliderControls/SliderControls.ts index 57e3f4ac..78f821c4 100644 --- a/packages/components/src/SliderControls/SliderControls.ts +++ b/packages/components/src/SliderControls/SliderControls.ts @@ -45,6 +45,7 @@ export default class SliderControls #sliderElement!: SliderElement #mutationObserver: MutationObserver #hasBeenInteractedWith = false + #sliderEventListeners: Record = {} constructor() { super() @@ -147,13 +148,45 @@ export default class SliderControls }) this.#setPlayBtnState() - this.#sliderElement.addEventListener('play', () => - this.#setPlayBtnState(), + + if (this.#sliderEventListeners.play) { + this.#sliderElement.removeEventListener( + 'play', + this.#sliderEventListeners.play, + ) + } + + if (this.#sliderEventListeners.reset) { + this.#sliderElement.removeEventListener( + 'reset', + this.#sliderEventListeners.reset, + ) + } + + if (this.#sliderEventListeners.pause) { + this.#sliderElement.removeEventListener( + 'pause', + this.#sliderEventListeners.pause, + ) + } + + this.#sliderEventListeners.play = () => this.#setPlayBtnState() + this.#sliderElement.addEventListener( + 'play', + this.#sliderEventListeners.play, + ) + + this.#sliderEventListeners.pause = () => this.#setPlayBtnState() + this.#sliderElement.addEventListener( + 'pause', + this.#sliderEventListeners.pause, ) - this.#sliderElement.addEventListener('pause', () => - this.#setPlayBtnState(), + + this.#sliderEventListeners.reset = () => this.#init() + this.#sliderElement.addEventListener( + 'reset', + this.#sliderEventListeners.reset, ) - this.#sliderElement.addEventListener('reset', () => this.#init()) this.#addIndexPips() this.#sliderElement.addEventListener( diff --git a/packages/components/src/main.ts b/packages/components/src/main.ts index 25a77b2e..22875b43 100644 --- a/packages/components/src/main.ts +++ b/packages/components/src/main.ts @@ -45,16 +45,12 @@ class CustomSlider extends Slider { customElements.define('custom-slider', CustomSlider) document.querySelector('#app')!.innerHTML = ` - + +
-
Slide One
-
Slide Two
-
Slide Three
-
Slide Four
-
Slide Five
@@ -134,9 +130,16 @@ document.querySelector('#app')!.innerHTML = `
` -setTimeout(() => { - document.getElementById('add-slides')!.addEventListener('click', () => { - const custom = document.getElementById('custom') - custom!.innerHTML += '
Slide Six
' - }) -}, 1000) +let slides = 0 + +document.getElementById('add-slides')!.addEventListener('click', () => { + slides += 1 + const custom = document.getElementById('custom') + custom!.innerHTML += `
Slide ${slides}
` +}) + +document.getElementById('remove-slides')!.addEventListener('click', () => { + const custom = document.getElementById('custom') + custom!.removeChild(document.getElementById(`slide-${slides}`)!) + slides -= 1 +}) diff --git a/packages/slider/src/box-slider.ts b/packages/slider/src/box-slider.ts index 5014c21d..e3284c8d 100644 --- a/packages/slider/src/box-slider.ts +++ b/packages/slider/src/box-slider.ts @@ -109,16 +109,10 @@ export default class BoxSlider { } this._activeIndex = this.options.startIndex this.init(effect) - - if (this.slides.length < this.activeIndex) { - this.destroy() - throw new Error( - `Start index option is out of bounds - slides=${this.slides.length} start=${this.activeIndex}`, - ) - } - this.applyEventListeners() + responder.add(this) + this.emit('init') } @@ -284,6 +278,10 @@ export default class BoxSlider { this.slides = this.getSlides() this.stateStore.storeAttributes([this.el, ...this.slides], ['style']) + if (this.activeIndex >= this.slides.length) { + this._activeIndex = 0 + } + this.effect.initialize( this.el, this.slides, @@ -336,17 +334,18 @@ export default class BoxSlider { } private transitionTo(nextIndex: number, backwards: boolean): Promise { - return new Promise((resolve, reject) => { - if (this.isDestroyed || nextIndex === this.activeIndex) { - return resolve() - } + return new Promise((resolve) => { + this.stopAutoScroll() - if (nextIndex < 0 || nextIndex >= this.slides.length) { - return reject(new Error(`${nextIndex} is not a valid slide index`)) + if ( + this.isDestroyed || + nextIndex === this.activeIndex || + nextIndex < 0 || + nextIndex >= this.slides.length + ) { + return resolve() } - this.stopAutoScroll() - const settings = { el: this.el, slides: this.slides,