* feat: create new carousel component with embala-carousel * feat: create demos for the carousel component * feat: add the default carousel component to the docs * feat: add new-york styling for carousels * feat: add more examples for spacing, size and options * refactor: change ways to better pass the data to parent * feat: add examples for carousel api handling * feat: add example for using embla plugin * chore: add carousel component doc to the table of contents * feat: add focusability on carousel element * fix: update docs * chore: add docs for slot props * feat: expose api for the parent component * chore: include missing filenames * chore: update embla carousel dependency versions * chore: fix typescript error by getting the types from core package * chore: prevent duplicate classes by using class as prop * feat: use slot fallback content so user could change navigation button icons * fix: change attribute inheritance element * chore: update www package.json `scripts` update tsconfig exclude for the strict registry build * refactor: fix embla-carousel types after v8.0.0-rc18 update embla deps * chore: update @vue/tsconfig * chore: run registry * refactor: remove uneended ref * fix: dependencies for embla missing * docs: update carousel for optional plugin installation --------- Co-authored-by: sadeghbarati <sadeghbaratiwork@gmail.com> Co-authored-by: zernonia <zernonia@gmail.com>
58 lines
1.5 KiB
TypeScript
58 lines
1.5 KiB
TypeScript
import { createInjectionState } from '@vueuse/core'
|
|
import emblaCarouselVue from 'embla-carousel-vue'
|
|
import { onMounted, ref } from 'vue'
|
|
import type {
|
|
EmblaCarouselType as CarouselApi,
|
|
} from 'embla-carousel'
|
|
import type { CarouselEmits, CarouselProps } from './interface'
|
|
|
|
const [useProvideCarousel, useInjectCarousel] = createInjectionState(
|
|
({
|
|
opts, orientation, plugins,
|
|
}: CarouselProps, emits: CarouselEmits) => {
|
|
const [emblaNode, emblaApi] = emblaCarouselVue({
|
|
...opts,
|
|
axis: orientation === 'horizontal' ? 'x' : 'y',
|
|
}, plugins)
|
|
|
|
function scrollPrev() {
|
|
emblaApi.value?.scrollPrev()
|
|
}
|
|
function scrollNext() {
|
|
emblaApi.value?.scrollNext()
|
|
}
|
|
|
|
const canScrollNext = ref(true)
|
|
const canScrollPrev = ref(true)
|
|
|
|
function onSelect(api: CarouselApi) {
|
|
canScrollNext.value = api.canScrollNext()
|
|
canScrollPrev.value = api.canScrollPrev()
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (!emblaApi.value)
|
|
return
|
|
|
|
emblaApi.value?.on('init', onSelect)
|
|
emblaApi.value?.on('reInit', onSelect)
|
|
emblaApi.value?.on('select', onSelect)
|
|
|
|
emits('init-api', emblaApi.value)
|
|
})
|
|
|
|
return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, orientation }
|
|
},
|
|
)
|
|
|
|
function useCarousel() {
|
|
const carouselState = useInjectCarousel()
|
|
|
|
if (!carouselState)
|
|
throw new Error('useCarousel must be used within a <Carousel />')
|
|
|
|
return carouselState
|
|
}
|
|
|
|
export { useCarousel, useProvideCarousel }
|