Skip to content

Commit

Permalink
Implement #1091.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidjerleke committed Jan 7, 2025
1 parent dd0f021 commit 415a416
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,10 @@ Scroll to the previous scroll snap if possible. When [loop](/api/options/#loop)

### scrollToSnap

Parameters: <BrandPrimaryText>`index: number`, `jump?: boolean`</BrandPrimaryText>
Parameters: <BrandPrimaryText>`index: number`, `jump?: boolean`, `direction?: 'forward' | 'backward'`</BrandPrimaryText>
Returns: <BrandSecondaryText>`void`</BrandSecondaryText>

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.

<Admonition type="note">
**Note:** A scroll snap isn't equvialent to a slide. A scroll snap can hold
Expand All @@ -339,10 +339,10 @@ Scroll to a scroll snap by its unique index. If [loop](/api/options/#loop) is en

### scrollToSlide

Parameters: <BrandPrimaryText>`subject: number | HTMLElement`, `jump?: boolean`</BrandPrimaryText>
Parameters: <BrandPrimaryText>`subject: number | HTMLElement`, `jump?: boolean`, `direction?: 'forward' | 'backward'`</BrandPrimaryText>
Returns: <BrandSecondaryText>`void`</BrandSecondaryText>

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.

---

Expand Down
19 changes: 14 additions & 5 deletions packages/embla-carousel/src/components/EmblaCarousel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(
Expand Down Expand Up @@ -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))
Expand Down
9 changes: 5 additions & 4 deletions packages/embla-carousel/src/components/ScrollTarget.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LimitType } from './Limit'
import { DirectionType } from './ScrollTo'
import { Vector1DType } from './Vector1d'
import { arrayLast, mathAbs, mathSign } from './utils'

Expand All @@ -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(
Expand All @@ -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
Expand All @@ -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 }
Expand Down
18 changes: 14 additions & 4 deletions packages/embla-carousel/src/components/ScrollTo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 415a416

Please sign in to comment.