61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import type { WithElementRef } from '$lib/utils.js'
|
|
import type {
|
|
EmblaCarouselSvelteType,
|
|
default as emblaCarouselSvelte,
|
|
} from 'embla-carousel-svelte'
|
|
import { getContext, hasContext, setContext } from 'svelte'
|
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
|
|
export type CarouselAPI =
|
|
NonNullable<
|
|
NonNullable<EmblaCarouselSvelteType['$$_attributes']>['on:emblaInit']
|
|
> extends (evt: CustomEvent<infer CarouselAPI>) => void
|
|
? CarouselAPI
|
|
: never
|
|
|
|
type EmblaCarouselConfig = NonNullable<
|
|
Parameters<typeof emblaCarouselSvelte>[1]
|
|
>
|
|
|
|
export type CarouselOptions = EmblaCarouselConfig['options']
|
|
export type CarouselPlugins = EmblaCarouselConfig['plugins']
|
|
|
|
////
|
|
|
|
export type CarouselProps = {
|
|
opts?: CarouselOptions
|
|
plugins?: CarouselPlugins
|
|
setApi?: (api: CarouselAPI | undefined) => void
|
|
orientation?: 'horizontal' | 'vertical'
|
|
} & WithElementRef<HTMLAttributes<HTMLDivElement>>
|
|
|
|
const EMBLA_CAROUSEL_CONTEXT = Symbol('EMBLA_CAROUSEL_CONTEXT')
|
|
|
|
export type EmblaContext = {
|
|
api: CarouselAPI | undefined
|
|
orientation: 'horizontal' | 'vertical'
|
|
scrollNext: () => void
|
|
scrollPrev: () => void
|
|
canScrollNext: boolean
|
|
canScrollPrev: boolean
|
|
handleKeyDown: (e: KeyboardEvent) => void
|
|
options: CarouselOptions
|
|
plugins: CarouselPlugins
|
|
onInit: (e: CustomEvent<CarouselAPI>) => void
|
|
scrollTo: (index: number, jump?: boolean) => void
|
|
scrollSnaps: number[]
|
|
selectedIndex: number
|
|
}
|
|
|
|
export function setEmblaContext(config: EmblaContext): EmblaContext {
|
|
setContext(EMBLA_CAROUSEL_CONTEXT, config)
|
|
return config
|
|
}
|
|
|
|
export function getEmblaContext(name = 'This component') {
|
|
if (!hasContext(EMBLA_CAROUSEL_CONTEXT)) {
|
|
throw new Error(`${name} must be used within a <Carousel.Root> component`)
|
|
}
|
|
return getContext<ReturnType<typeof setEmblaContext>>(EMBLA_CAROUSEL_CONTEXT)
|
|
}
|