UNPKG

gvf3n4ygn-test

Version:
43 lines 7.19 kB
{ "name": "carousel", "dependencies": [ "embla-carousel-vue", "@vueuse/core" ], "registryDependencies": [], "files": [ { "name": "Carousel.vue", "content": "<script setup lang=\"ts\">\nimport { useProvideCarousel } from './useCarousel';\nimport type { CarouselEmits, CarouselProps } from './interface';\nimport { cn } from '@ui/utils';\n\nconst props = withDefaults(defineProps<CarouselProps>(), {\n orientation: 'horizontal',\n});\n\nconst emits = defineEmits<CarouselEmits>();\n\nconst carouselArgs = useProvideCarousel(props, emits);\n\ndefineExpose(carouselArgs);\n\nfunction onKeyDown(event: KeyboardEvent) {\n const prevKey = props.orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft';\n const nextKey = props.orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight';\n\n if (event.key === prevKey) {\n event.preventDefault();\n carouselArgs.scrollPrev();\n\n return;\n }\n\n if (event.key === nextKey) {\n event.preventDefault();\n carouselArgs.scrollNext();\n }\n}\n</script>\n\n<template>\n <div\n :class=\"cn('relative', $attrs.class ?? '')\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n tabindex=\"0\"\n @keydown=\"onKeyDown\"\n >\n <slot v-bind=\"carouselArgs\" />\n </div>\n</template>\n" }, { "name": "CarouselContent.vue", "content": "<script setup lang=\"ts\">\nimport { useCarousel } from './useCarousel';\nimport { cn } from '@ui/utils';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst { carouselRef, orientation } = useCarousel();\n</script>\n\n<template>\n <div\n ref=\"carouselRef\"\n class=\"overflow-hidden\"\n >\n <div\n :class=\"\n cn(\n 'flex',\n orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',\n $attrs.class ?? '',\n )\"\n v-bind=\"$attrs\"\n >\n <slot />\n </div>\n </div>\n</template>\n" }, { "name": "CarouselItem.vue", "content": "<script setup lang=\"ts\">\nimport { useCarousel } from './useCarousel';\nimport { cn } from '@ui/utils';\n\nconst { orientation } = useCarousel();\n</script>\n\n<template>\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n :class=\"cn(\n 'min-w-0 shrink-0 grow-0 basis-full',\n orientation === 'horizontal' ? 'pl-4' : 'pt-4',\n $attrs.class ?? '',\n )\"\n >\n <slot />\n </div>\n</template>\n" }, { "name": "CarouselNext.vue", "content": "<script setup lang=\"ts\">\nimport { ArrowRightIcon } from 'lucide-vue-next';\nimport { useCarousel } from './useCarousel';\nimport { cn } from '@ui/utils';\nimport { Button } from '@ui/registry/tailwind/ui/button';\n\nconst { orientation, canScrollNext, scrollNext } = useCarousel();\n</script>\n\n<template>\n <Button\n :disabled=\"!canScrollNext\"\n :class=\"cn(\n 'touch-manipulation absolute h-8 w-8 rounded p-0',\n orientation === 'horizontal'\n ? '-right-12 top-1/2 -translate-y-1/2'\n : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',\n $attrs.class ?? '',\n )\"\n variant=\"outline\"\n @click=\"scrollNext\"\n >\n <slot>\n <ArrowRightIcon class=\"h-4 w-4 text-current\" />\n <span class=\"sr-only\">Next Slide</span>\n </slot>\n </Button>\n</template>\n" }, { "name": "CarouselPrevious.vue", "content": "<script setup lang=\"ts\">\nimport { ArrowLeftIcon } from 'lucide-vue-next';\nimport { useCarousel } from './useCarousel';\nimport { cn } from '@ui/utils';\nimport { Button } from '@ui/registry/tailwind/ui/button';\n\nconst { orientation, canScrollPrev, scrollPrev } = useCarousel();\n</script>\n\n<template>\n <Button\n :disabled=\"!canScrollPrev\"\n :class=\"cn(\n 'touch-manipulation absolute h-8 w-8 rounded p-0',\n orientation === 'horizontal'\n ? '-left-12 top-1/2 -translate-y-1/2'\n : '-top-12 left-1/2 -translate-x-1/2 rotate-90',\n $attrs.class ?? '',\n )\"\n variant=\"outline\"\n @click=\"scrollPrev\"\n >\n <slot>\n <ArrowLeftIcon class=\"h-4 w-4 text-current\" />\n <span class=\"sr-only\">Previous Slide</span>\n </slot>\n </Button>\n</template>\n" }, { "name": "index.ts", "content": "export { default as Carousel } from './Carousel.vue';\nexport { default as CarouselContent } from './CarouselContent.vue';\nexport { default as CarouselItem } from './CarouselItem.vue';\nexport { default as CarouselPrevious } from './CarouselPrevious.vue';\nexport { default as CarouselNext } from './CarouselNext.vue';\nexport { useCarousel } from './useCarousel';\n\nexport type {\n UnwrapRefCarouselApi as CarouselApi,\n} from './interface';\n" }, { "name": "interface.ts", "content": "import type { UnwrapRef } from 'vue';\nimport type useEmblaCarousel from 'embla-carousel-vue';\nimport type {\n EmblaCarouselVueType,\n} from 'embla-carousel-vue';\n\ntype CarouselApi = EmblaCarouselVueType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\nexport type UnwrapRefCarouselApi = UnwrapRef<CarouselApi>;\n\nexport interface CarouselProps {\n opts?: CarouselOptions;\n plugins?: CarouselPlugin;\n orientation?: 'horizontal' | 'vertical';\n}\n\nexport interface CarouselEmits {\n (e: 'init-api', payload: UnwrapRefCarouselApi): void;\n}\n" }, { "name": "useCarousel.ts", "content": "import { createInjectionState } from '@vueuse/core';\nimport emblaCarouselVue from 'embla-carousel-vue';\nimport { onMounted, ref } from 'vue';\nimport type { UnwrapRefCarouselApi as CarouselApi, CarouselEmits, CarouselProps } from './interface';\n\nconst [useProvideCarousel, useInjectCarousel] = createInjectionState(\n ({\n opts,\n orientation,\n plugins,\n }: CarouselProps, emits: CarouselEmits) => {\n const [emblaNode, emblaApi] = emblaCarouselVue({\n ...opts,\n axis: orientation === 'horizontal' ? 'x' : 'y',\n }, plugins);\n\n function scrollPrev() {\n emblaApi.value?.scrollPrev();\n }\n\n function scrollNext() {\n emblaApi.value?.scrollNext();\n }\n\n const canScrollNext = ref(false);\n const canScrollPrev = ref(false);\n\n function onSelect(api: CarouselApi) {\n canScrollNext.value = api?.canScrollNext() || false;\n canScrollPrev.value = api?.canScrollPrev() || false;\n }\n\n onMounted(() => {\n if (!emblaApi.value) {\n return;\n }\n\n emblaApi.value?.on('init', onSelect);\n emblaApi.value?.on('reInit', onSelect);\n emblaApi.value?.on('select', onSelect);\n\n emits('init-api', emblaApi.value);\n });\n\n return { carouselRef: emblaNode, carouselApi: emblaApi, canScrollPrev, canScrollNext, scrollPrev, scrollNext, orientation };\n },\n);\n\nfunction useCarousel() {\n const carouselState = useInjectCarousel();\n\n if (!carouselState) {\n throw new Error('useCarousel must be used within a <Carousel />');\n }\n\n return carouselState;\n}\n\nexport { useCarousel, useProvideCarousel };\n" } ], "type": "components:ui" }