From 415a4164e72c30358075c056357d6b4b6d3dc1c2 Mon Sep 17 00:00:00 2001 From: David Jerleke Date: Mon, 16 Dec 2024 21:10:20 +0100 Subject: [PATCH] Implement #1091. --- .../src/content/pages/api/methods.mdx | 8 ++++---- .../src/components/EmblaCarousel.ts | 19 ++++++++++++++----- .../src/components/ScrollTarget.ts | 9 +++++---- .../embla-carousel/src/components/ScrollTo.ts | 18 ++++++++++++++---- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/packages/embla-carousel-docs/src/content/pages/api/methods.mdx b/packages/embla-carousel-docs/src/content/pages/api/methods.mdx index 8eb582ecf..1946fde6b 100644 --- a/packages/embla-carousel-docs/src/content/pages/api/methods.mdx +++ b/packages/embla-carousel-docs/src/content/pages/api/methods.mdx @@ -322,10 +322,10 @@ Scroll to the previous scroll snap if possible. When [loop](/api/options/#loop) ### scrollToSnap -Parameters: `index: number`, `jump?: boolean` +Parameters: `index: number`, `jump?: boolean`, `direction?: 'forward' | 'backward'` Returns: `void` -Scroll to a scroll snap by its unique index. If [loop](/api/options/#loop) is enabled, Embla Carousel will choose the closest way to the target scroll snap. Set the **jump** parameter to `true` when you want to go to the desired scroll snap instantly. +Scroll to a scroll snap by its unique index. Set the **jump** parameter to `true` when you want to go to the desired scroll snap instantly. If [loop](/api/options/#loop) is enabled and the **direction** parameter is omitted, Embla Carousel will choose the closest way to the target scroll snap. **Note:** A scroll snap isn't equvialent to a slide. A scroll snap can hold @@ -339,10 +339,10 @@ Scroll to a scroll snap by its unique index. If [loop](/api/options/#loop) is en ### scrollToSlide -Parameters: `subject: number | HTMLElement`, `jump?: boolean` +Parameters: `subject: number | HTMLElement`, `jump?: boolean`, `direction?: 'forward' | 'backward'` Returns: `void` -Scroll to a scroll snap by providing a slide index or a slide element. The carousel will scroll to the scroll snap that holds the provided slide. If [loop](/api/options/#loop) is enabled, Embla Carousel will choose the closest way to the target scroll snap. Set the **jump** parameter to `true` when you want to go to the desired scroll snap instantly. +Scroll to a scroll snap by providing a slide index or a slide element. The carousel will scroll to the scroll snap that holds the provided slide. Set the **jump** parameter to `true` when you want to go to the desired scroll snap instantly. If [loop](/api/options/#loop) is enabled and the **direction** parameter is omitted, Embla Carousel will choose the closest way to the target scroll snap. --- diff --git a/packages/embla-carousel/src/components/EmblaCarousel.ts b/packages/embla-carousel/src/components/EmblaCarousel.ts index e28af8e98..320816d28 100644 --- a/packages/embla-carousel/src/components/EmblaCarousel.ts +++ b/packages/embla-carousel/src/components/EmblaCarousel.ts @@ -7,6 +7,7 @@ import { OptionsHandler } from './OptionsHandler' import { PluginsHandler } from './PluginsHandler' import { EmblaPluginsType, EmblaPluginType } from './Plugins' import { isNumber, isString, WindowType } from './utils' +import { ScrollToDirectionType } from './ScrollTo' export type EmblaCarouselType = { canScrollNext: () => boolean @@ -28,12 +29,20 @@ export type EmblaCarouselType = { scrollPrev: (jump?: boolean) => void scrollProgress: () => number snapList: () => number[] - scrollToSnap: (index: number, jump?: boolean) => void - scrollToSlide: (subject: number | HTMLElement, jump?: boolean) => void selectedSnap: () => number slideNodes: () => HTMLElement[] slidesInView: () => number[] slidesNotInView: () => number[] + scrollToSnap: ( + index: number, + jump?: boolean, + direction?: ScrollToDirectionType + ) => void + scrollToSlide: ( + subject: number | HTMLElement, + jump?: boolean, + direction?: ScrollToDirectionType + ) => void } function EmblaCarousel( @@ -168,19 +177,19 @@ function EmblaCarousel( function scrollToSnap( index: number, jump?: boolean, - direction?: number + direction?: ScrollToDirectionType ): void { if (!options.active || destroyed) return engine.scrollBody .useBaseFriction() .useDuration(jump === true ? 0 : options.duration) - engine.scrollTo.index(index, direction || 0) + engine.scrollTo.index(index, direction) } function scrollToSlide( subject: number | HTMLElement, jump?: boolean, - direction?: number + direction?: ScrollToDirectionType ): void { const index = isNumber(subject) ? subject : slides.indexOf(subject) const snapIndex = engine.slideRegistry.findIndex((g) => g.includes(index)) diff --git a/packages/embla-carousel/src/components/ScrollTarget.ts b/packages/embla-carousel/src/components/ScrollTarget.ts index 1408b2603..6c5dce21b 100644 --- a/packages/embla-carousel/src/components/ScrollTarget.ts +++ b/packages/embla-carousel/src/components/ScrollTarget.ts @@ -1,4 +1,5 @@ import { LimitType } from './Limit' +import { DirectionType } from './ScrollTo' import { Vector1DType } from './Vector1d' import { arrayLast, mathAbs, mathSign } from './utils' @@ -8,9 +9,9 @@ export type TargetType = { } export type ScrollTargetType = { - byIndex: (target: number, direction: number) => TargetType + byIndex: (target: number, direction: DirectionType) => TargetType byDistance: (force: number, snap: boolean) => TargetType - shortcut: (target: number, direction: number) => number + shortcut: (target: number, direction: DirectionType) => number } export function ScrollTarget( @@ -36,7 +37,7 @@ export function ScrollTarget( return { index, distance } } - function shortcut(target: number, direction: number): number { + function shortcut(target: number, direction: DirectionType): number { const targets = [target, target + contentSize, target - contentSize] if (!loop) return target @@ -47,7 +48,7 @@ export function ScrollTarget( return arrayLast(targets) - contentSize } - function byIndex(index: number, direction: number): TargetType { + function byIndex(index: number, direction: DirectionType): TargetType { const diffToSnap = scrollSnaps[index] - targetVector.get() const distance = shortcut(diffToSnap, direction) return { index, distance } diff --git a/packages/embla-carousel/src/components/ScrollTo.ts b/packages/embla-carousel/src/components/ScrollTo.ts index 98a17c054..0f444551e 100644 --- a/packages/embla-carousel/src/components/ScrollTo.ts +++ b/packages/embla-carousel/src/components/ScrollTo.ts @@ -4,10 +4,14 @@ import { EventHandlerType } from './EventHandler' import { ScrollBodyType } from './ScrollBody' import { ScrollTargetType, TargetType } from './ScrollTarget' import { Vector1DType } from './Vector1d' +import { isNumber } from './utils' + +export type DirectionType = 0 | 1 | -1 +export type ScrollToDirectionType = 'forward' | 'backward' | DirectionType export type ScrollToType = { distance: (n: number, snap: boolean) => void - index: (n: number, direction: number) => void + index: (n: number, direction?: ScrollToDirectionType) => void } export function ScrollTo( @@ -47,12 +51,18 @@ export function ScrollTo( scrollTo(target) } - function index(n: number, direction: number): void { - const targetIndex = indexCurrent.clone().set(n) - const target = scrollTarget.byIndex(targetIndex.get(), direction) + function index(n: number, direction?: ScrollToDirectionType): void { + const targetIndex = indexCurrent.clone().set(n).get() + const target = scrollTarget.byIndex(targetIndex, getDirection(direction)) scrollTo(target) } + function getDirection(direction?: ScrollToDirectionType): DirectionType { + if (!direction) return 0 + if (isNumber(direction)) return direction + return direction === 'forward' ? -1 : 1 + } + const self: ScrollToType = { distance, index