diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.jsx
index 5168112ca..b18c4132c 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.jsx
@@ -24,11 +24,11 @@ export const useDotButton = (
)
const onInit = useCallback((emblaApi) => {
- setScrollSnaps(emblaApi.scrollSnapList())
+ setScrollSnaps(emblaApi.snapList())
}, [])
const onSelect = useCallback((emblaApi) => {
- setSelectedIndex(emblaApi.selectedScrollSnap())
+ setSelectedIndex(emblaApi.selectedSnap())
}, [])
useEffect(() => {
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.jsx
index d9090e434..d2e8c6065 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.jsx
@@ -5,8 +5,8 @@ export const useSelectedSnapDisplay = (emblaApi) => {
const [snapCount, setSnapCount] = useState(0)
const updateScrollSnapState = useCallback((emblaApi) => {
- setSnapCount(emblaApi.scrollSnapList().length)
- setSelectedSnap(emblaApi.selectedScrollSnap())
+ setSnapCount(emblaApi.snapList().length)
+ setSelectedSnap(emblaApi.selectedSnap())
}, [])
useEffect(() => {
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselDotButton.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselDotButton.jsx
index 3a54891c9..f5b6ee359 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselDotButton.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselDotButton.jsx
@@ -14,11 +14,11 @@ export const useDotButton = (emblaApi, onButtonClick) => {
)
const onInit = useCallback((emblaApi) => {
- setScrollSnaps(emblaApi.scrollSnapList())
+ setScrollSnaps(emblaApi.snapList())
}, [])
const onSelect = useCallback((emblaApi) => {
- setSelectedIndex(emblaApi.selectedScrollSnap())
+ setSelectedIndex(emblaApi.selectedSnap())
}, [])
useEffect(() => {
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselSelectedSnapDisplay.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselSelectedSnapDisplay.jsx
index d9090e434..d2e8c6065 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselSelectedSnapDisplay.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/EmblaCarouselSelectedSnapDisplay.jsx
@@ -5,8 +5,8 @@ export const useSelectedSnapDisplay = (emblaApi) => {
const [snapCount, setSnapCount] = useState(0)
const updateScrollSnapState = useCallback((emblaApi) => {
- setSnapCount(emblaApi.scrollSnapList().length)
- setSelectedSnap(emblaApi.selectedScrollSnap())
+ setSnapCount(emblaApi.snapList().length)
+ setSelectedSnap(emblaApi.selectedSnap())
}, [])
useEffect(() => {
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/IosPicker/EmblaCarouselIosPickerItem.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/IosPicker/EmblaCarouselIosPickerItem.jsx
index 5854b7ec7..e6e9f4816 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/IosPicker/EmblaCarouselIosPickerItem.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/IosPicker/EmblaCarouselIosPickerItem.jsx
@@ -18,7 +18,7 @@ const isInView = (wheelLocation, slidePosition) =>
const setSlideStyles = (emblaApi, index, loop, slideCount, totalRadius) => {
const slideNode = emblaApi.slideNodes()[index]
const wheelLocation = emblaApi.scrollProgress() * totalRadius
- const positionDefault = emblaApi.scrollSnapList()[index] * totalRadius
+ const positionDefault = emblaApi.snapList()[index] * totalRadius
const positionLoopStart = positionDefault + totalRadius
const positionLoopEnd = positionDefault - totalRadius
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Opacity/EmblaCarousel.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Opacity/EmblaCarousel.jsx
index f9398934d..0440fe732 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Opacity/EmblaCarousel.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Opacity/EmblaCarousel.jsx
@@ -29,7 +29,7 @@ const EmblaCarousel = (props) => {
} = usePrevNextButtons(emblaApi)
const setTweenFactor = useCallback((emblaApi) => {
- tweenFactor.current = TWEEN_FACTOR_BASE * emblaApi.scrollSnapList().length
+ tweenFactor.current = TWEEN_FACTOR_BASE * emblaApi.snapList().length
}, [])
const tweenOpacity = useCallback((emblaApi, eventName) => {
@@ -38,7 +38,7 @@ const EmblaCarousel = (props) => {
const slidesInView = emblaApi.slidesInView()
const isScrollEvent = eventName === 'scroll'
- emblaApi.scrollSnapList().forEach((scrollSnap, snapIndex) => {
+ emblaApi.snapList().forEach((scrollSnap, snapIndex) => {
let diffToTarget = scrollSnap - scrollProgress
const slidesInSnap = engine.slideRegistry[snapIndex]
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Parallax/EmblaCarousel.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Parallax/EmblaCarousel.jsx
index c37a536a0..53b5269e8 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Parallax/EmblaCarousel.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Parallax/EmblaCarousel.jsx
@@ -33,7 +33,7 @@ const EmblaCarousel = (props) => {
}, [])
const setTweenFactor = useCallback((emblaApi) => {
- tweenFactor.current = TWEEN_FACTOR_BASE * emblaApi.scrollSnapList().length
+ tweenFactor.current = TWEEN_FACTOR_BASE * emblaApi.snapList().length
}, [])
const tweenParallax = useCallback((emblaApi, eventName) => {
@@ -42,7 +42,7 @@ const EmblaCarousel = (props) => {
const slidesInView = emblaApi.slidesInView()
const isScrollEvent = eventName === 'scroll'
- emblaApi.scrollSnapList().forEach((scrollSnap, snapIndex) => {
+ emblaApi.snapList().forEach((scrollSnap, snapIndex) => {
let diffToTarget = scrollSnap - scrollProgress
const slidesInSnap = engine.slideRegistry[snapIndex]
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Scale/EmblaCarousel.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Scale/EmblaCarousel.jsx
index 632352e8a..4136eb364 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Scale/EmblaCarousel.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Scale/EmblaCarousel.jsx
@@ -35,7 +35,7 @@ const EmblaCarousel = (props) => {
}, [])
const setTweenFactor = useCallback((emblaApi) => {
- tweenFactor.current = TWEEN_FACTOR_BASE * emblaApi.scrollSnapList().length
+ tweenFactor.current = TWEEN_FACTOR_BASE * emblaApi.snapList().length
}, [])
const tweenScale = useCallback((emblaApi, eventName) => {
@@ -44,7 +44,7 @@ const EmblaCarousel = (props) => {
const slidesInView = emblaApi.slidesInView()
const isScrollEvent = eventName === 'scroll'
- emblaApi.scrollSnapList().forEach((scrollSnap, snapIndex) => {
+ emblaApi.snapList().forEach((scrollSnap, snapIndex) => {
let diffToTarget = scrollSnap - scrollProgress
const slidesInSnap = engine.slideRegistry[snapIndex]
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Thumbs/EmblaCarousel.jsx b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Thumbs/EmblaCarousel.jsx
index 242e2dd8e..2fe3628dc 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Thumbs/EmblaCarousel.jsx
+++ b/packages/embla-carousel-docs/src/components/Sandbox/React/SandboxFilesDist/Thumbs/EmblaCarousel.jsx
@@ -21,8 +21,8 @@ const EmblaCarousel = (props) => {
const onSelect = useCallback(() => {
if (!emblaMainApi || !emblaThumbsApi) return
- setSelectedIndex(emblaMainApi.selectedScrollSnap())
- emblaThumbsApi.scrollToSnap(emblaMainApi.selectedScrollSnap())
+ setSelectedIndex(emblaMainApi.selectedSnap())
+ emblaThumbsApi.scrollToSnap(emblaMainApi.selectedSnap())
}, [emblaMainApi, emblaThumbsApi, setSelectedIndex])
useEffect(() => {
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.js
index d80ac83b5..30ac51329 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselDotButton.js
@@ -9,7 +9,7 @@ export const addDotBtnsAndClickHandlers = (
const addDotBtnsWithClickHandlers = () => {
dotsNode.innerHTML = emblaApi
- .scrollSnapList()
+ .snapList()
.map(() => '')
.join('')
@@ -27,8 +27,8 @@ export const addDotBtnsAndClickHandlers = (
}
const toggleDotBtnsActive = () => {
- const previous = emblaApi.previousScrollSnap()
- const selected = emblaApi.selectedScrollSnap()
+ const previous = emblaApi.previousSnap()
+ const selected = emblaApi.selectedSnap()
dotNodes[previous].classList.remove('embla__dot--selected')
dotNodes[selected].classList.add('embla__dot--selected')
}
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.js
index 652f2365e..05ec6662c 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/CarouselGenerator/EmblaCarouselSelectedSnapDisplay.js
@@ -1,7 +1,7 @@
export const updateSelectedSnapDisplay = (emblaApi, snapDisplay) => {
const updateSnapDisplay = (emblaApi) => {
- const selectedSnap = emblaApi.selectedScrollSnap()
- const snapCount = emblaApi.scrollSnapList().length
+ const selectedSnap = emblaApi.selectedSnap()
+ const snapCount = emblaApi.snapList().length
snapDisplay.innerHTML = `${selectedSnap + 1} / ${snapCount}`
}
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/EmblaCarouselDotButton.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/EmblaCarouselDotButton.js
index 3d8935226..e365e90d0 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/EmblaCarouselDotButton.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/EmblaCarouselDotButton.js
@@ -3,7 +3,7 @@ export const addDotBtnsAndClickHandlers = (emblaApi, dotsNode) => {
const addDotBtnsWithClickHandlers = () => {
dotsNode.innerHTML = emblaApi
- .scrollSnapList()
+ .snapList()
.map(() => '')
.join('')
@@ -18,8 +18,8 @@ export const addDotBtnsAndClickHandlers = (emblaApi, dotsNode) => {
}
const toggleDotBtnsActive = () => {
- const previous = emblaApi.previousScrollSnap()
- const selected = emblaApi.selectedScrollSnap()
+ const previous = emblaApi.previousSnap()
+ const selected = emblaApi.selectedSnap()
dotNodes[previous].classList.remove('embla__dot--selected')
dotNodes[selected].classList.add('embla__dot--selected')
}
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/IosPicker/EmblaCarouselIosPicker.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/IosPicker/EmblaCarouselIosPicker.js
index a810587ae..d63874598 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/IosPicker/EmblaCarouselIosPicker.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/IosPicker/EmblaCarouselIosPicker.js
@@ -17,7 +17,7 @@ const slideIsInView = (wheelLocation, slidePosition) =>
const rotateSlide = (emblaApi, index, loop, slideCount, totalRadius) => {
const slideNode = emblaApi.slideNodes()[index]
const wheelLocation = emblaApi.scrollProgress() * totalRadius
- const positionDefault = emblaApi.scrollSnapList()[index] * totalRadius
+ const positionDefault = emblaApi.snapList()[index] * totalRadius
const positionLoopStart = positionDefault + totalRadius
const positionLoopEnd = positionDefault - totalRadius
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Opacity/EmblaCarouselTweenOpacity.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Opacity/EmblaCarouselTweenOpacity.js
index 8e1deb61f..a51e65f18 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Opacity/EmblaCarouselTweenOpacity.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Opacity/EmblaCarouselTweenOpacity.js
@@ -5,7 +5,7 @@ const numberWithinRange = (number, min, max) =>
Math.min(Math.max(number, min), max)
const setTweenFactor = (emblaApi) => {
- tweenFactor = TWEEN_FACTOR_BASE * emblaApi.scrollSnapList().length
+ tweenFactor = TWEEN_FACTOR_BASE * emblaApi.snapList().length
}
const tweenOpacity = (emblaApi, eventName) => {
@@ -14,7 +14,7 @@ const tweenOpacity = (emblaApi, eventName) => {
const slidesInView = emblaApi.slidesInView()
const isScrollEvent = eventName === 'scroll'
- emblaApi.scrollSnapList().forEach((scrollSnap, snapIndex) => {
+ emblaApi.snapList().forEach((scrollSnap, snapIndex) => {
let diffToTarget = scrollSnap - scrollProgress
const slidesInSnap = engine.slideRegistry[snapIndex]
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Parallax/EmblaCarouselTweenParallax.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Parallax/EmblaCarouselTweenParallax.js
index a94e13687..4a365670c 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Parallax/EmblaCarouselTweenParallax.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Parallax/EmblaCarouselTweenParallax.js
@@ -9,7 +9,7 @@ const setTweenNodes = (emblaApi) => {
}
const setTweenFactor = (emblaApi) => {
- tweenFactor = TWEEN_FACTOR_BASE * emblaApi.scrollSnapList().length
+ tweenFactor = TWEEN_FACTOR_BASE * emblaApi.snapList().length
}
const tweenParallax = (emblaApi, eventName) => {
@@ -18,7 +18,7 @@ const tweenParallax = (emblaApi, eventName) => {
const slidesInView = emblaApi.slidesInView()
const isScrollEvent = eventName === 'scroll'
- emblaApi.scrollSnapList().forEach((scrollSnap, snapIndex) => {
+ emblaApi.snapList().forEach((scrollSnap, snapIndex) => {
let diffToTarget = scrollSnap - scrollProgress
const slidesInSnap = engine.slideRegistry[snapIndex]
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Scale/EmblaCarouselTweenScale.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Scale/EmblaCarouselTweenScale.js
index 4ef01798b..0d0ba5e9a 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Scale/EmblaCarouselTweenScale.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Scale/EmblaCarouselTweenScale.js
@@ -12,7 +12,7 @@ const setTweenNodes = (emblaApi) => {
}
const setTweenFactor = (emblaApi) => {
- tweenFactor = TWEEN_FACTOR_BASE * emblaApi.scrollSnapList().length
+ tweenFactor = TWEEN_FACTOR_BASE * emblaApi.snapList().length
}
const tweenScale = (emblaApi, eventName) => {
@@ -21,7 +21,7 @@ const tweenScale = (emblaApi, eventName) => {
const slidesInView = emblaApi.slidesInView()
const isScrollEvent = eventName === 'scroll'
- emblaApi.scrollSnapList().forEach((scrollSnap, snapIndex) => {
+ emblaApi.snapList().forEach((scrollSnap, snapIndex) => {
let diffToTarget = scrollSnap - scrollProgress
const slidesInSnap = engine.slideRegistry[snapIndex]
diff --git a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Thumbs/EmblaCarouselThumbsButton.js b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Thumbs/EmblaCarouselThumbsButton.js
index bf03a5c3f..7e4e1b35d 100644
--- a/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Thumbs/EmblaCarouselThumbsButton.js
+++ b/packages/embla-carousel-docs/src/components/Sandbox/Vanilla/SandboxFilesDist/Thumbs/EmblaCarouselThumbsButton.js
@@ -20,9 +20,9 @@ export const addToggleThumbBtnsActive = (emblaApiMain, emblaApiThumb) => {
const slidesThumbs = emblaApiThumb.slideNodes()
const toggleThumbBtnsState = () => {
- emblaApiThumb.scrollToSnap(emblaApiMain.selectedScrollSnap())
- const previous = emblaApiMain.previousScrollSnap()
- const selected = emblaApiMain.selectedScrollSnap()
+ emblaApiThumb.scrollToSnap(emblaApiMain.selectedSnap())
+ const previous = emblaApiMain.previousSnap()
+ const selected = emblaApiMain.selectedSnap()
slidesThumbs[previous].classList.remove('embla-thumbs__slide--selected')
slidesThumbs[selected].classList.add('embla-thumbs__slide--selected')
}
@@ -31,7 +31,7 @@ export const addToggleThumbBtnsActive = (emblaApiMain, emblaApiThumb) => {
emblaApiThumb.on('init', toggleThumbBtnsState)
return () => {
- const selected = emblaApiMain.selectedScrollSnap()
+ const selected = emblaApiMain.selectedSnap()
slidesThumbs[selected].classList.remove('embla-thumbs__slide--selected')
}
}
diff --git a/packages/embla-carousel/src/components/Animations.ts b/packages/embla-carousel/src/components/Animations.ts
index bf86c3be6..f73e63600 100644
--- a/packages/embla-carousel/src/components/Animations.ts
+++ b/packages/embla-carousel/src/components/Animations.ts
@@ -6,7 +6,7 @@ export type AnimationsUpdateType = (engine: EngineType) => void
export type AnimationsRenderType = (engine: EngineType, alpha: number) => void
export type AnimationsType = {
- init: () => void
+ init: (ownerWindow: WindowType) => void
destroy: () => void
start: () => void
stop: () => void
@@ -15,19 +15,21 @@ export type AnimationsType = {
}
export function Animations(
- ownerDocument: Document,
- ownerWindow: WindowType,
update: () => void,
render: (alpha: number) => void
): AnimationsType {
const documentVisibleHandler = EventStore()
const fixedTimeStep = 1000 / 60
+ let windowInstance: WindowType
let lastTimeStamp: number | null = null
let accumulatedTime = 0
let animationId = 0
- function init(): void {
+ function init(ownerWindow: WindowType): void {
+ const ownerDocument = ownerWindow.document
+ windowInstance = ownerWindow
+
documentVisibleHandler.add(ownerDocument, 'visibilitychange', () => {
if (ownerDocument.hidden) reset()
})
@@ -59,17 +61,17 @@ export function Animations(
render(alpha)
if (animationId) {
- animationId = ownerWindow.requestAnimationFrame(animate)
+ animationId = windowInstance.requestAnimationFrame(animate)
}
}
function start(): void {
if (animationId) return
- animationId = ownerWindow.requestAnimationFrame(animate)
+ animationId = windowInstance.requestAnimationFrame(animate)
}
function stop(): void {
- ownerWindow.cancelAnimationFrame(animationId)
+ windowInstance.cancelAnimationFrame(animationId)
lastTimeStamp = null
accumulatedTime = 0
animationId = 0
diff --git a/packages/embla-carousel/src/components/Axis.ts b/packages/embla-carousel/src/components/Axis.ts
index 0504392f1..96deb13c2 100644
--- a/packages/embla-carousel/src/components/Axis.ts
+++ b/packages/embla-carousel/src/components/Axis.ts
@@ -1,4 +1,4 @@
-import { NodeRectType } from './NodeRects'
+import { NodeRectType } from './NodeHandler'
export type AxisOptionType = 'x' | 'y'
export type AxisDirectionOptionType = 'ltr' | 'rtl'
diff --git a/packages/embla-carousel/src/components/DragHandler.ts b/packages/embla-carousel/src/components/DragHandler.ts
index a4e78b8ce..3a5066f21 100644
--- a/packages/embla-carousel/src/components/DragHandler.ts
+++ b/packages/embla-carousel/src/components/DragHandler.ts
@@ -21,7 +21,7 @@ import {
} from './utils'
export type DragHandlerType = {
- init: () => void
+ init: (windowInstance: WindowType) => void
destroy: () => void
pointerDown: () => boolean
}
@@ -30,8 +30,6 @@ export function DragHandler(
active: boolean,
axis: AxisType,
rootNode: HTMLElement,
- ownerDocument: Document,
- ownerWindow: WindowType,
target: Vector1DType,
dragTracker: DragTrackerType,
location: Vector1DType,
@@ -58,6 +56,8 @@ export function DragHandler(
const freeForceBoost = { mouse: 500, touch: 600 }
const baseSpeed = dragFree ? 43 : 25
+ let ownerDocument: Document
+ let ownerWindow: WindowType
let isMoving = false
let startScroll = 0
let startCross = 0
@@ -66,9 +66,14 @@ export function DragHandler(
let preventClick = false
let isMouse = false
- function init(): void {
+ function init(windowInstance: WindowType): void {
if (!active) return
+ ownerDocument = windowInstance.document
+ ownerWindow = windowInstance
+
+ dragTracker.init(windowInstance)
+
const node = rootNode
initEvents
.add(node, 'dragstart', (evt) => evt.preventDefault(), nonPassiveEvent)
diff --git a/packages/embla-carousel/src/components/DragTracker.ts b/packages/embla-carousel/src/components/DragTracker.ts
index aebd3ca54..9f9a8e4c8 100644
--- a/packages/embla-carousel/src/components/DragTracker.ts
+++ b/packages/embla-carousel/src/components/DragTracker.ts
@@ -5,21 +5,24 @@ type PointerCoordType = keyof Touch | keyof MouseEvent
export type PointerEventType = TouchEvent | MouseEvent
export type DragTrackerType = {
+ init: (windowInstance: WindowType) => void
pointerDown: (evt: PointerEventType) => number
pointerMove: (evt: PointerEventType) => number
pointerUp: (evt: PointerEventType) => number
readPoint: (evt: PointerEventType, evtAxis?: AxisOptionType) => number
}
-export function DragTracker(
- axis: AxisType,
- ownerWindow: WindowType
-): DragTrackerType {
+export function DragTracker(axis: AxisType): DragTrackerType {
const logInterval = 170
+ let ownerWindow: WindowType
let startEvent: PointerEventType
let lastEvent: PointerEventType
+ function init(windowInstance: WindowType): void {
+ ownerWindow = windowInstance
+ }
+
function readTime(evt: PointerEventType): number {
return evt.timeStamp
}
@@ -57,6 +60,7 @@ export function DragTracker(
}
const self: DragTrackerType = {
+ init,
pointerDown,
pointerMove,
pointerUp,
diff --git a/packages/embla-carousel/src/components/EmblaCarousel.ts b/packages/embla-carousel/src/components/EmblaCarousel.ts
index 320816d28..8348bde0a 100644
--- a/packages/embla-carousel/src/components/EmblaCarousel.ts
+++ b/packages/embla-carousel/src/components/EmblaCarousel.ts
@@ -3,11 +3,13 @@ import { EventStore } from './EventStore'
import { WatchHandler, WatchHandlerType } from './WatchHandler'
import { EventHandler, EventHandlerType } from './EventHandler'
import { defaultOptions, EmblaOptionsType, OptionsType } from './Options'
+import { NodeHandler, NodeHandlerType } from './NodeHandler'
import { OptionsHandler } from './OptionsHandler'
import { PluginsHandler } from './PluginsHandler'
+import { SsrHandler, SsrHandlerType } from './SsrHandler'
import { EmblaPluginsType, EmblaPluginType } from './Plugins'
-import { isNumber, isString, WindowType } from './utils'
import { ScrollToDirectionType } from './ScrollTo'
+import { isNumber } from './utils'
export type EmblaCarouselType = {
canScrollNext: () => boolean
@@ -24,6 +26,7 @@ export type EmblaCarouselType = {
plugins: () => EmblaPluginsType
previousSnap: () => number
reInit: (options?: EmblaOptionsType, plugins?: EmblaPluginType[]) => void
+ ssrStyles: (container: string, slides: string) => string
rootNode: () => HTMLElement
scrollNext: (jump?: boolean) => void
scrollPrev: (jump?: boolean) => void
@@ -48,11 +51,11 @@ export type EmblaCarouselType = {
function EmblaCarousel(
root: HTMLElement,
userOptions?: EmblaOptionsType,
- userPlugins?: EmblaPluginType[]
+ userPlugins?: EmblaPluginType[],
+ serverMode?: boolean
): EmblaCarouselType {
- const ownerDocument = root.ownerDocument
- const ownerWindow = ownerDocument.defaultView
- const optionsHandler = OptionsHandler(ownerWindow)
+ const isSsr = !!serverMode
+ const optionsHandler = OptionsHandler()
const pluginsHandler = PluginsHandler(optionsHandler)
const mediaHandlers = EventStore()
const watchHandler = WatchHandler()
@@ -64,43 +67,36 @@ function EmblaCarousel(
let destroyed = false
let engine: EngineType
+ let nodeHandler: NodeHandlerType
+ let ssrHandler: SsrHandlerType
let optionsBase = mergeOptions(defaultOptions, EmblaCarousel.globalOptions)
let options = mergeOptions(optionsBase)
let pluginList: EmblaPluginType[] = []
let pluginApis: EmblaPluginsType
-
let container: HTMLElement
let slides: HTMLElement[]
- function storeElements(): void {
- const { container: userContainer, slides: userSlides } = options
-
- const customContainer = isString(userContainer)
- ? root.querySelector(userContainer)
- : userContainer
- container = (customContainer || root.children[0])
+ function createEngine(
+ options: OptionsType,
+ container: HTMLElement,
+ slides: HTMLElement[]
+ ): EngineType {
+ nodeHandler.clearOffsets(container, ...slides)
- const customSlides = isString(userSlides)
- ? container.querySelectorAll(userSlides)
- : userSlides
- slides = [].slice.call(customSlides || container.children)
- }
-
- function createEngine(options: OptionsType): EngineType {
+ // TODO: Pass pixelTolerance, should be 0 when SSR
const engine = Engine(
root,
container,
slides,
- ownerDocument,
- ownerWindow,
options,
+ nodeHandler,
eventHandler,
watchHandler
)
if (options.loop && !engine.slideLooper.canLoop()) {
const optionsWithoutLoop = Object.assign({}, options, { loop: false })
- return createEngine(optionsWithoutLoop)
+ return createEngine(optionsWithoutLoop, container, slides)
}
return engine
}
@@ -111,13 +107,28 @@ function EmblaCarousel(
): void {
if (destroyed) return
+ nodeHandler = NodeHandler(root, isSsr)
+ const { ownerWindow } = nodeHandler
+
+ optionsHandler.init(ownerWindow)
optionsBase = mergeOptions(optionsBase, withOptions)
options = optionsAtMedia(optionsBase)
pluginList = withPlugins || pluginList
- storeElements()
+ const nodes = nodeHandler.getNodes(options)
+ container = nodes.container
+ slides = nodes.slides
+ engine = createEngine(options, container, slides)
- engine = createEngine(options)
+ ssrHandler = SsrHandler(
+ isSsr,
+ container,
+ engine.axis,
+ nodeHandler,
+ optionsBase,
+ mergeOptions,
+ createEngine
+ )
optionsMediaQueries([
optionsBase,
@@ -125,18 +136,22 @@ function EmblaCarousel(
]).forEach((query) => mediaHandlers.add(query, 'change', reActivate))
if (!options.active) return
+ if (!ownerWindow) return
+ if (isSsr) return
engine.translate.to(engine.location.get())
- engine.animation.init()
- engine.slidesInView.init()
- engine.slideFocus.init()
- engine.resizeHandler.init()
- engine.slidesHandler.init()
+ engine.animation.init(ownerWindow)
+ engine.resizeHandler.init(ownerWindow)
+ engine.slidesInView.init(ownerWindow)
+ engine.slidesHandler.init(ownerWindow)
engine.eventHandler.init(self)
engine.watchHandler.init(self)
+ engine.slideFocus.init()
if (engine.options.loop) engine.slideLooper.loop()
- if (container.offsetParent && slides.length) engine.dragHandler.init()
+ if (container.offsetParent && slides.length) {
+ engine.dragHandler.init(ownerWindow)
+ }
pluginApis = pluginsHandler.init(self, pluginList)
}
@@ -166,6 +181,8 @@ function EmblaCarousel(
function destroy(): void {
if (destroyed) return
+ if (isSsr) return
+
destroyed = true
mediaHandlers.clear()
deActivate()
@@ -179,7 +196,10 @@ function EmblaCarousel(
jump?: boolean,
direction?: ScrollToDirectionType
): void {
- if (!options.active || destroyed) return
+ if (destroyed) return
+ if (isSsr) return
+ if (!options.active) return
+
engine.scrollBody
.useBaseFriction()
.useDuration(jump === true ? 0 : options.duration)
@@ -217,6 +237,10 @@ function EmblaCarousel(
return prev !== selectedSnap()
}
+ function ssrStyles(container: string, slides: string): string {
+ return ssrHandler.getStyles(container, slides)
+ }
+
function snapList(): number[] {
return engine.snapList
}
@@ -286,11 +310,12 @@ function EmblaCarousel(
slideNodes,
slidesInView,
slidesNotInView,
- snapList
+ snapList,
+ ssrStyles
}
activate(userOptions, userPlugins)
- setTimeout(() => eventHandler.emit('init', null), 0)
+ setTimeout(() => eventHandler.emit('init', null), 0) // TODO: Won't work in SSR
return self
}
diff --git a/packages/embla-carousel/src/components/Engine.ts b/packages/embla-carousel/src/components/Engine.ts
index 212bc51b2..803a47a62 100644
--- a/packages/embla-carousel/src/components/Engine.ts
+++ b/packages/embla-carousel/src/components/Engine.ts
@@ -12,7 +12,7 @@ import { DragTracker } from './DragTracker'
import { EventHandlerType } from './EventHandler'
import { EventStore, EventStoreType } from './EventStore'
import { LimitType } from './Limit'
-import { NodeRectType, NodeRects } from './NodeRects'
+import { NodeRectType } from './NodeHandler'
import { OptionsType } from './Options'
import { PercentOfView, PercentOfViewType } from './PercentOfView'
import { ResizeHandler, ResizeHandlerType } from './ResizeHandler'
@@ -33,15 +33,15 @@ import { SlidesInView, SlidesInViewType } from './SlidesInView'
import { SlideSizes } from './SlideSizes'
import { SlidesToScroll, SlidesToScrollType } from './SlidesToScroll'
import { Translate, TranslateType } from './Translate'
-import { arrayKeys, arrayLast, arrayLastIndex, WindowType } from './utils'
+import { arrayKeys, arrayLast, arrayLastIndex } from './utils'
import { Vector1D, Vector1DType } from './Vector1d'
import { WatchHandlerType } from './WatchHandler'
+import { NodeHandlerType } from './NodeHandler'
export type EngineType = {
- ownerDocument: Document
- ownerWindow: WindowType
eventHandler: EventHandlerType
watchHandler: WatchHandlerType
+ contentSize: number
axis: AxisType
animation: AnimationsType
scrollBounds: ScrollBoundsType
@@ -80,9 +80,8 @@ export function Engine(
root: HTMLElement,
container: HTMLElement,
slides: HTMLElement[],
- ownerDocument: Document,
- ownerWindow: WindowType,
options: OptionsType,
+ nodeHandler: NodeHandlerType,
eventHandler: EventHandlerType,
watchHandler: WatchHandlerType
): EngineType {
@@ -108,9 +107,8 @@ export function Engine(
// Measurements
const pixelTolerance = 2
- const nodeRects = NodeRects()
- const containerRect = nodeRects.measure(container)
- const slideRects = slides.map(nodeRects.measure)
+ const containerRect = nodeHandler.getRect(container)
+ const slideRects = slides.map(nodeHandler.getRect)
const axis = Axis(scrollAxis, direction)
const viewSize = axis.measureSize(containerRect)
const percentOfView = PercentOfView(viewSize)
@@ -123,7 +121,7 @@ export function Engine(
slideRects,
slides,
readEdgeGap,
- ownerWindow
+ nodeHandler
)
const slidesToScroll = SlidesToScroll(
axis,
@@ -211,8 +209,6 @@ export function Engine(
}
const animation = Animations(
- ownerDocument,
- ownerWindow,
() => update(engine),
(alpha: number) => render(engine, alpha)
)
@@ -278,10 +274,9 @@ export function Engine(
// Engine
const engine: EngineType = {
- ownerDocument,
- ownerWindow,
eventHandler,
containerRect,
+ contentSize,
slideRects,
animation,
axis,
@@ -289,10 +284,8 @@ export function Engine(
draggable,
axis,
root,
- ownerDocument,
- ownerWindow,
target,
- DragTracker(axis, ownerWindow),
+ DragTracker(axis),
location,
animation,
scrollTo,
@@ -321,10 +314,9 @@ export function Engine(
container,
eventHandler,
watchHandler,
- ownerWindow,
slides,
axis,
- nodeRects
+ nodeHandler
),
scrollBody,
scrollBounds: ScrollBounds(
diff --git a/packages/embla-carousel/src/components/NodeHandler.ts b/packages/embla-carousel/src/components/NodeHandler.ts
new file mode 100644
index 000000000..0de7c234f
--- /dev/null
+++ b/packages/embla-carousel/src/components/NodeHandler.ts
@@ -0,0 +1,106 @@
+import { OptionsType } from './Options'
+import { isString, WindowType } from './utils'
+
+export type NodeRectType = {
+ top: number
+ right: number
+ bottom: number
+ left: number
+ width: number
+ height: number
+}
+
+type NodesType = {
+ container: HTMLElement
+ slides: HTMLElement[]
+}
+
+export type NodeHandlerType = {
+ ownerWindow: WindowType | null
+ clearOffsets: (...nodes: HTMLElement[]) => void
+ getNodes: (options: OptionsType) => NodesType
+ getRect: (node: HTMLElement) => NodeRectType
+}
+
+export function NodeHandler(
+ root: HTMLElement,
+ isSsr: boolean
+): NodeHandlerType {
+ const ownerDocument = isSsr ? null : root.ownerDocument
+ const ownerWindow = ownerDocument
+ ? ownerDocument.defaultView
+ : null
+
+ function clearOffsets(...nodes: HTMLElement[]): void {
+ if (isSsr) return
+
+ nodes.forEach((node) => {
+ const style = node.style
+ if (!style.transform) style.transform = 'none'
+ })
+ }
+
+ function getRect(node: HTMLElement): NodeRectType {
+ const { offsetTop, offsetLeft, offsetWidth, offsetHeight } = node
+ const offset: NodeRectType = {
+ top: offsetTop,
+ right: offsetLeft + offsetWidth,
+ bottom: offsetTop + offsetHeight,
+ left: offsetLeft,
+ width: offsetWidth,
+ height: offsetHeight
+ }
+ return offset
+ }
+
+ function createSsrNode(
+ offsetLeft: number,
+ offsetTop: number,
+ offsetWidth: number,
+ offsetHeight: number
+ ): HTMLElement {
+ return { offsetLeft, offsetTop, offsetWidth, offsetHeight }
+ }
+
+ function getBrowserNodes(options: OptionsType): NodesType {
+ const { container: userContainer, slides: userSlides } = options
+
+ const containerNode = isString(userContainer)
+ ? root.querySelector(userContainer)
+ : userContainer
+ const container = (containerNode || root.children[0])
+
+ const slideNodes = isString(userSlides)
+ ? container.querySelectorAll(userSlides)
+ : userSlides
+ const slides = Array.from(slideNodes || container.children)
+
+ return { container, slides }
+ }
+
+ function getSsrNodes(options: OptionsType): NodesType {
+ const containerSize = 100
+ const container = createSsrNode(0, 0, containerSize, containerSize)
+ let startOffset = 0
+
+ const slides = options.ssr.map((size) => {
+ const slide = createSsrNode(startOffset, startOffset, size, size)
+ startOffset += size
+ return slide
+ })
+
+ return { container, slides }
+ }
+
+ function getNodes(options: OptionsType): NodesType {
+ return isSsr ? getSsrNodes(options) : getBrowserNodes(options)
+ }
+
+ const self: NodeHandlerType = {
+ ownerWindow,
+ clearOffsets,
+ getNodes,
+ getRect
+ }
+ return self
+}
diff --git a/packages/embla-carousel/src/components/NodeRects.ts b/packages/embla-carousel/src/components/NodeRects.ts
deleted file mode 100644
index 3b5664cc5..000000000
--- a/packages/embla-carousel/src/components/NodeRects.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-export type NodeRectType = {
- top: number
- right: number
- bottom: number
- left: number
- width: number
- height: number
-}
-
-export type NodeRectsType = {
- measure: (node: HTMLElement) => NodeRectType
-}
-
-export function NodeRects(): NodeRectsType {
- function measure(node: HTMLElement): NodeRectType {
- const { offsetTop, offsetLeft, offsetWidth, offsetHeight } = node
- const offset: NodeRectType = {
- top: offsetTop,
- right: offsetLeft + offsetWidth,
- bottom: offsetTop + offsetHeight,
- left: offsetLeft,
- width: offsetWidth,
- height: offsetHeight
- }
-
- return offset
- }
-
- const self: NodeRectsType = {
- measure
- }
- return self
-}
diff --git a/packages/embla-carousel/src/components/Options.ts b/packages/embla-carousel/src/components/Options.ts
index 938f441a5..8ac14ea36 100644
--- a/packages/embla-carousel/src/components/Options.ts
+++ b/packages/embla-carousel/src/components/Options.ts
@@ -34,6 +34,7 @@ export type OptionsType = CreateOptionsType<{
resize: boolean
focus: boolean
slideChanges: boolean
+ ssr: number[]
}>
export const defaultOptions: OptionsType = {
@@ -56,7 +57,8 @@ export const defaultOptions: OptionsType = {
draggable: true,
resize: true,
focus: true,
- slideChanges: true
+ slideChanges: true,
+ ssr: []
}
export type EmblaOptionsType = Partial
diff --git a/packages/embla-carousel/src/components/OptionsHandler.ts b/packages/embla-carousel/src/components/OptionsHandler.ts
index 8f635fc09..30e40bc6d 100644
--- a/packages/embla-carousel/src/components/OptionsHandler.ts
+++ b/packages/embla-carousel/src/components/OptionsHandler.ts
@@ -1,9 +1,11 @@
+import { NodeHandlerType } from './NodeHandler'
import { LooseOptionsType, CreateOptionsType } from './Options'
import { objectKeys, objectsMergeDeep, WindowType } from './utils'
type OptionsType = Partial>
export type OptionsHandlerType = {
+ init: (windowInstance: NodeHandlerType['ownerWindow']) => void
mergeOptions: (
optionsA: TypeA,
optionsB?: TypeB
@@ -12,7 +14,14 @@ export type OptionsHandlerType = {
optionsMediaQueries: (optionsList: OptionsType[]) => MediaQueryList[]
}
-export function OptionsHandler(ownerWindow: WindowType): OptionsHandlerType {
+export function OptionsHandler(): OptionsHandlerType {
+ let windowInstance: WindowType
+
+ function init(ownerWindow: NodeHandlerType['ownerWindow']): void {
+ if (!ownerWindow) return
+ windowInstance = ownerWindow
+ }
+
function mergeOptions(
optionsA: TypeA,
optionsB?: TypeB
@@ -21,9 +30,11 @@ export function OptionsHandler(ownerWindow: WindowType): OptionsHandlerType {
}
function optionsAtMedia(options: Type): Type {
+ if (!windowInstance) return options
+
const optionsAtMedia = options.breakpoints || {}
const matchedMediaOptions = objectKeys(optionsAtMedia)
- .filter((media) => ownerWindow.matchMedia(media).matches)
+ .filter((media) => windowInstance.matchMedia(media).matches)
.map((media) => optionsAtMedia[media])
.reduce((a, mediaOption) => mergeOptions(a, mediaOption), {})
@@ -31,13 +42,16 @@ export function OptionsHandler(ownerWindow: WindowType): OptionsHandlerType {
}
function optionsMediaQueries(optionsList: OptionsType[]): MediaQueryList[] {
+ if (!windowInstance) return []
+
return optionsList
.map((options) => objectKeys(options.breakpoints || {}))
.reduce((acc, mediaQueries) => acc.concat(mediaQueries), [])
- .map(ownerWindow.matchMedia)
+ .map(windowInstance.matchMedia)
}
const self: OptionsHandlerType = {
+ init,
mergeOptions,
optionsAtMedia,
optionsMediaQueries
diff --git a/packages/embla-carousel/src/components/ResizeHandler.ts b/packages/embla-carousel/src/components/ResizeHandler.ts
index efcd228c8..e82f75c1f 100644
--- a/packages/embla-carousel/src/components/ResizeHandler.ts
+++ b/packages/embla-carousel/src/components/ResizeHandler.ts
@@ -2,11 +2,11 @@ import { AxisType } from './Axis'
import { EmblaCarouselType } from './EmblaCarousel'
import { EventHandlerType } from './EventHandler'
import { WatchHandlerType } from './WatchHandler'
-import { NodeRectsType } from './NodeRects'
+import { NodeHandlerType } from './NodeHandler'
import { mathAbs, WindowType } from './utils'
export type ResizeHandlerType = {
- init: () => void
+ init: (ownerWindow: WindowType) => void
destroy: () => void
}
@@ -15,10 +15,9 @@ export function ResizeHandler(
container: HTMLElement,
eventHandler: EventHandlerType,
watchHandler: WatchHandlerType,
- ownerWindow: WindowType,
slides: HTMLElement[],
axis: AxisType,
- nodeRects: NodeRectsType
+ nodeHandler: NodeHandlerType
): ResizeHandlerType {
const observeNodes = [container].concat(slides)
let resizeObserver: ResizeObserver
@@ -27,16 +26,16 @@ export function ResizeHandler(
let destroyed = false
function readSize(node: HTMLElement): number {
- return axis.measureSize(nodeRects.measure(node))
+ return axis.measureSize(nodeHandler.getRect(node))
}
- function init(): void {
+ function init(ownerWindow: WindowType): void {
if (!active) return
containerSize = readSize(container)
slideSizes = slides.map(readSize)
- resizeObserver = new ResizeObserver((entries) => {
+ resizeObserver = new ownerWindow.ResizeObserver((entries) => {
watchHandler.emit('resize', entries, onResize)
})
diff --git a/packages/embla-carousel/src/components/ScrollSnaps.ts b/packages/embla-carousel/src/components/ScrollSnaps.ts
index ef5f5f9f4..d9cb576b8 100644
--- a/packages/embla-carousel/src/components/ScrollSnaps.ts
+++ b/packages/embla-carousel/src/components/ScrollSnaps.ts
@@ -1,6 +1,6 @@
import { AlignmentType } from './Alignment'
import { AxisType } from './Axis'
-import { NodeRectType } from './NodeRects'
+import { NodeRectType } from './NodeHandler'
import { SlidesToScrollType } from './SlidesToScroll'
import { arrayLast, mathAbs } from './utils'
diff --git a/packages/embla-carousel/src/components/SlideSizes.ts b/packages/embla-carousel/src/components/SlideSizes.ts
index eaf2c1f3b..bc8c784f2 100644
--- a/packages/embla-carousel/src/components/SlideSizes.ts
+++ b/packages/embla-carousel/src/components/SlideSizes.ts
@@ -1,6 +1,7 @@
import { AxisType } from './Axis'
-import { NodeRectType } from './NodeRects'
-import { arrayIsLastIndex, arrayLast, mathAbs, WindowType } from './utils'
+import { NodeHandlerType } from './NodeHandler'
+import { NodeRectType } from './NodeHandler'
+import { arrayIsLastIndex, arrayLast, mathAbs } from './utils'
export type SlideSizesType = {
slideSizes: number[]
@@ -15,8 +16,9 @@ export function SlideSizes(
slideRects: NodeRectType[],
slides: HTMLElement[],
readEdgeGap: boolean,
- ownerWindow: WindowType
+ nodeHandler: NodeHandlerType
): SlideSizesType {
+ const { ownerWindow } = nodeHandler
const { measureSize, startEdge, endEdge } = axis
const withEdgeGap = slideRects[0] && readEdgeGap
const startGap = measureStartGap()
@@ -31,7 +33,7 @@ export function SlideSizes(
}
function measureEndGap(): number {
- if (!withEdgeGap) return 0
+ if (!withEdgeGap || !ownerWindow) return 0
const style = ownerWindow.getComputedStyle(arrayLast(slides))
return parseFloat(style.getPropertyValue(`margin-${endEdge}`))
}
diff --git a/packages/embla-carousel/src/components/SlidesHandler.ts b/packages/embla-carousel/src/components/SlidesHandler.ts
index 61716e401..58a264cbb 100644
--- a/packages/embla-carousel/src/components/SlidesHandler.ts
+++ b/packages/embla-carousel/src/components/SlidesHandler.ts
@@ -1,9 +1,10 @@
import { EmblaCarouselType } from './EmblaCarousel'
import { EventHandlerType } from './EventHandler'
import { WatchHandlerType } from './WatchHandler'
+import { WindowType } from './utils'
export type SlidesHandlerType = {
- init: () => void
+ init: (ownerWindow: WindowType) => void
destroy: () => void
}
@@ -16,10 +17,10 @@ export function SlidesHandler(
let mutationObserver: MutationObserver
let destroyed = false
- function init(): void {
+ function init(ownerWindow: WindowType): void {
if (!active) return
- mutationObserver = new MutationObserver((mutations) => {
+ mutationObserver = new ownerWindow.MutationObserver((mutations) => {
watchHandler.emit('slideschanged', mutations, onSlidesChange)
})
diff --git a/packages/embla-carousel/src/components/SlidesInView.ts b/packages/embla-carousel/src/components/SlidesInView.ts
index 5e778e94e..e66bb7b74 100644
--- a/packages/embla-carousel/src/components/SlidesInView.ts
+++ b/packages/embla-carousel/src/components/SlidesInView.ts
@@ -1,5 +1,5 @@
import { EventHandlerType } from './EventHandler'
-import { objectKeys } from './utils'
+import { objectKeys, WindowType } from './utils'
type IntersectionEntryMapType = {
[key: number]: IntersectionObserverEntry
@@ -8,7 +8,7 @@ type IntersectionEntryMapType = {
export type SlidesInViewOptionsType = IntersectionObserverInit['threshold']
export type SlidesInViewType = {
- init: () => void
+ init: (ownerWindow: WindowType) => void
destroy: () => void
get: (inView?: boolean) => number[]
}
@@ -25,8 +25,8 @@ export function SlidesInView(
let intersectionObserver: IntersectionObserver
let destroyed = false
- function init(): void {
- intersectionObserver = new IntersectionObserver(
+ function init(ownerWindow: WindowType): void {
+ intersectionObserver = new ownerWindow.IntersectionObserver(
(entries) => {
if (destroyed) return
diff --git a/packages/embla-carousel/src/components/SlidesToScroll.ts b/packages/embla-carousel/src/components/SlidesToScroll.ts
index aa81eee82..7bad59f89 100644
--- a/packages/embla-carousel/src/components/SlidesToScroll.ts
+++ b/packages/embla-carousel/src/components/SlidesToScroll.ts
@@ -1,5 +1,5 @@
import { AxisType } from './Axis'
-import { NodeRectType } from './NodeRects'
+import { NodeRectType } from './NodeHandler'
import {
arrayKeys,
arrayLast,
diff --git a/packages/embla-carousel/src/components/SsrHandler.ts b/packages/embla-carousel/src/components/SsrHandler.ts
new file mode 100644
index 000000000..93f8f5c1f
--- /dev/null
+++ b/packages/embla-carousel/src/components/SsrHandler.ts
@@ -0,0 +1,97 @@
+import { Axis, AxisType } from './Axis'
+import { EngineType } from './Engine'
+import { NodeHandlerType } from './NodeHandler'
+import { OptionsType } from './Options'
+import { OptionsHandlerType } from './OptionsHandler'
+import { Translate } from './Translate'
+import { mathSign } from './utils'
+
+// TODO: Enable SSR for library wrappers like React, Vue etc.
+// TODO: Remove init event with timeout in EmblaCarousel.ts which won't work with SSR (deprecated)
+// TODO: Enable SSR for plugins?
+
+export type SsrHandlerType = {
+ getStyles: (container: string, slides: string) => string
+}
+
+export function SsrHandler(
+ isSsr: boolean,
+ container: HTMLElement,
+ axis: AxisType,
+ nodeHandler: NodeHandlerType,
+ options: OptionsType,
+ mergeOptions: OptionsHandlerType['mergeOptions'],
+ createEngine: (
+ options: OptionsType,
+ container: HTMLElement,
+ slides: HTMLElement[]
+ ) => EngineType
+): SsrHandlerType {
+ const translate = Translate(axis, container, '%')
+
+ function getNormalizedEngine(options: OptionsType): EngineType {
+ const normalizedOptions = mergeOptions(options, { direction: 'ltr' })
+ const { slides, container } = nodeHandler.getNodes(normalizedOptions)
+ return createEngine(normalizedOptions, container, slides)
+ }
+
+ function createStyles(
+ options: OptionsType,
+ container: string,
+ slides: string
+ ): string {
+ const { direction } = Axis(options.axis, options.direction)
+ const { location, slideLooper, contentSize } = getNormalizedEngine(options)
+ const loopPoints = options.loop ? slideLooper.loopPoints : []
+ const containerSsr = direction(location.get())
+
+ return `
+ ${container} {
+ transform: ${translate.get(containerSsr)};
+ }
+ ${loopPoints.reduce((acc, loopPoint) => {
+ const { index } = loopPoint
+ const sign = mathSign(loopPoint.target())
+ const size = options.ssr[index]
+
+ if (!sign || !size) return acc
+ const slideSsr = direction((contentSize / size) * 100 * sign)
+
+ return `
+ ${acc}
+ ${slides}:nth-child(${index + 1}) {
+ transform: ${translate.get(slideSsr)};
+ }
+ `
+ }, '')}
+ `
+ }
+
+ function getStyles(container: string, slides: string): string {
+ if (!isSsr) return ''
+ if (!options.ssr.length) return ''
+
+ const optionBreakpoints = options.breakpoints
+ const styles = `
+ ${createStyles(options, container, slides)}
+
+ ${Object.keys(optionBreakpoints).reduce((acc, key) => {
+ const optionsAtMedia = mergeOptions(options, optionBreakpoints[key])
+
+ return `
+ ${acc}
+ @media ${key} {
+ ${createStyles(optionsAtMedia, container, slides)}
+ }
+ `
+ }, '')}
+ `
+
+ return styles //.replace(/\s+/g, '')
+ }
+
+ const self: SsrHandlerType = {
+ getStyles
+ }
+ return self
+}
diff --git a/packages/embla-carousel/src/components/Translate.ts b/packages/embla-carousel/src/components/Translate.ts
index 4ccda61b4..484b45d6d 100644
--- a/packages/embla-carousel/src/components/Translate.ts
+++ b/packages/embla-carousel/src/components/Translate.ts
@@ -5,23 +5,27 @@ export type TranslateType = {
clear: () => void
to: (target: number) => void
toggleActive: (active: boolean) => void
+ get: (n: number) => string
}
export function Translate(
axis: AxisType,
- container: HTMLElement
+ container: HTMLElement,
+ unit?: 'px' | '%'
): TranslateType {
- const translate = axis.scroll === 'x' ? x : y
+ const getTranslate = axis.scroll === 'x' ? x : y
const containerStyle = container.style
+ const transformUnit = unit || 'px'
+
let previousTarget: number | null = null
let disabled = false
function x(n: number): string {
- return `translate3d(${n}px,0px,0px)`
+ return `translate3d(${n}${transformUnit},0px,0px)`
}
function y(n: number): string {
- return `translate3d(0px,${n}px,0px)`
+ return `translate3d(0px,${n}${transformUnit},0px)`
}
function to(target: number): void {
@@ -30,7 +34,7 @@ export function Translate(
const newTarget = roundToTwoDecimals(axis.direction(target))
if (newTarget === previousTarget) return
- containerStyle.transform = translate(newTarget)
+ containerStyle.transform = getTranslate(newTarget)
previousTarget = newTarget
}
@@ -47,7 +51,8 @@ export function Translate(
const self: TranslateType = {
clear,
to,
- toggleActive
+ toggleActive,
+ get: getTranslate
}
return self
}