Skip to content

Commit

Permalink
feat(slider): use resize observer for slider reset
Browse files Browse the repository at this point in the history
  • Loading branch information
p-m-p committed Oct 6, 2023
1 parent 5846d5f commit cc175a2
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 45 deletions.
6 changes: 3 additions & 3 deletions packages/slider/src/box-slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class BoxSlider {
private isDestroyed: boolean
private transitionPromise?: Promise<void>

private get el() {
get el() {
if (this._el === undefined) {
throw new Error('Slider element is null')
}
Expand All @@ -35,15 +35,15 @@ class BoxSlider {

private get stateStore() {
if (this._stateStore === undefined) {
throw new Error('State store is null, are you trying ot interact with a destroyed slider?')
throw new Error('State store is null, are you trying to interact with a destroyed slider?')
}

return this._stateStore
}

private get effect() {
if (this._effect === undefined) {
throw new Error('Slide effect is null, are you trying ot interact with a destroyed slider?')
throw new Error('Slide effect is null, are you trying to interact with a destroyed slider?')
}

return this._effect
Expand Down
31 changes: 12 additions & 19 deletions packages/slider/src/effects/carousel-slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ export interface CarouselSliderOptions {
timingFunction?: string
}

const SLIDE_STYLES = ['height', 'left', 'position', 'top', 'tranform', 'transition', 'width', 'visibility', 'z-index']
const BOX_STYLES = ['height', 'overflow', 'position', 'width']
const SLIDE_STYLES = ['left', 'position', 'top', 'transform', 'transition', 'visibility', 'z-index']
const BOX_STYLES = ['overflow', 'position']

export class CarouselSlider implements Effect {
private readonly options: CarouselSliderOptions
private slideWidth!: string
private slideHeight!: string

constructor(options?: CarouselSliderOptions) {
this.options = {
Expand All @@ -24,16 +22,11 @@ export class CarouselSlider implements Effect {
}

initialize(el: HTMLElement, slides: HTMLElement[], stateStore: StateStore, options: BoxSliderOptions): void {
this.slideWidth = `${el.offsetWidth}px`
this.slideHeight = `${el.offsetHeight}px`

stateStore.storeStyles(slides, SLIDE_STYLES)
stateStore.storeStyles(el, BOX_STYLES)

applyCss(el, {
height: this.slideHeight,
overflow: 'hidden',
width: this.slideWidth,
})

if ('static inherit'.indexOf(getComputedStyle(el).position) !== -1) {
Expand All @@ -42,14 +35,12 @@ export class CarouselSlider implements Effect {

slides.forEach((slide, index) => {
applyCss(slide, {
height: this.slideHeight,
left: '0',
position: 'absolute',
top: '0',
transform: `translateX(${this.slideWidth})`,
transform: `translateX(${slide.offsetWidth}px)`,
transition: 'initial',
visibility: 'hidden',
width: this.slideWidth,
'z-index': '1',
})

Expand All @@ -64,12 +55,14 @@ export class CarouselSlider implements Effect {
}

transition(settings: TransitionSettings): Promise<void> {
const currentSlide = settings.slides[settings.currentIndex]
const nextSlide = settings.slides[settings.nextIndex]

return new Promise((resolve) => {
const currentSlide = settings.slides[settings.currentIndex]
const currentSlideWidth = `${currentSlide.offsetWidth}px`
const nextSlide = settings.slides[settings.nextIndex]
const nextSlideWidth = `${nextSlide.offsetWidth}px`

applyCss(nextSlide, {
transform: `translateX(${settings.isPrevious ? `-${this.slideWidth}` : this.slideWidth})`,
transform: `translateX(${settings.isPrevious ? '-' + nextSlideWidth : nextSlideWidth})`,
})

setTimeout(() => {
Expand All @@ -83,15 +76,15 @@ export class CarouselSlider implements Effect {
applyCss(currentSlide, {
transform: this.options.cover
? 'translateX(0px)'
: `translateX(${settings.isPrevious ? this.slideWidth : `-${this.slideWidth}`})`,
: `translateX(${settings.isPrevious ? currentSlideWidth : '-' + currentSlideWidth})`,
transition: this.options.cover ? 'initial' : `transform ${settings.speed}ms ${this.options.timingFunction}`,
visibility: 'visible',
'z-index': '1',
})

window.setTimeout(() => {
setTimeout(() => {
applyCss(currentSlide, {
transform: `translateX(${this.slideWidth})`,
transform: `translateX(${currentSlideWidth})`,
transition: 'initial',
visibility: 'hidden',
})
Expand Down
15 changes: 1 addition & 14 deletions packages/slider/src/effects/cube-slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,7 @@ export interface CubeSliderOptions {
}

const SLIDE_STYLES = ['left', 'position', 'top', 'transform', 'z-index']
const BOX_STYLES = [
'height',
'left',
'overflow',
'position',
'top',
'transform',
'transform-style',
'transition',
'width',
'z-index',
]
const BOX_STYLES = ['left', 'overflow', 'position', 'top', 'transform', 'transform-style', 'transition', 'z-index']
const VIEWPORT_STYLES = ['overflow', 'perspective', 'position']

class CubeSlider implements Effect {
Expand Down Expand Up @@ -59,12 +48,10 @@ class CubeSlider implements Effect {
)

applyCss(el, {
height: `${height}px`,
left: '0',
overflow: 'visible',
position: 'absolute',
top: '0',
width: `${width}px`,
})

// ensure parent is positioned to hold the box
Expand Down
15 changes: 9 additions & 6 deletions packages/slider/src/responder.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import type BoxSlider from './box-slider'
import BoxSlider from './box-slider'

let boxSliders: BoxSlider[] = []
let resizeDebounceTimer: number
let resizeObserver: ResizeObserver

if (typeof window !== 'undefined') {
window.addEventListener('resize', () => {
window.clearTimeout(resizeDebounceTimer)
resizeDebounceTimer = window.setTimeout(() => boxSliders.forEach((b) => b.reset()), 200)
if (typeof ResizeObserver !== 'undefined') {
resizeObserver = new ResizeObserver((sliderElements) => {
sliderElements.forEach((sliderEl) => boxSliders.find((bs) => bs.el === sliderEl.target)?.reset())
})
}

export const responder = {
add(boxSlider: BoxSlider): void {
boxSliders.push(boxSlider)
resizeObserver?.observe(boxSlider.el)
},
remove(boxSlider: BoxSlider): void {
resizeObserver?.unobserve(boxSlider.el)
boxSliders = boxSliders.filter((b) => b !== boxSlider)
},
}

export default responder
7 changes: 4 additions & 3 deletions packages/slider/src/state-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export class StateStore {
}

storeStyles(elements: HTMLElement[] | HTMLElement, styles: string[]) {
this.applyToElements(elements, (el, elementStore) =>
styles.forEach((p: string) => (elementStore.styles[p] = el.style.getPropertyValue(p))),
)
this.applyToElements(elements, (el, elementStore) => {
const computedStyles = getComputedStyle(el)
styles.forEach((p: string) => (elementStore.styles[p] = computedStyles.getPropertyValue(p)))
})
}

storeAttributes(elements: HTMLElement[] | HTMLElement, attributes: string[]) {
Expand Down

0 comments on commit cc175a2

Please sign in to comment.