mirror of
https://github.com/huntabyte/shadcn-svelte.git
synced 2026-09-14 19:33:46 +08:00
51 lines
9.4 KiB
JSON
51 lines
9.4 KiB
JSON
{
|
|
"$schema": "https://shadcn-svelte.com/schema/registry-item.json",
|
|
"name": "carousel",
|
|
"type": "registry:ui",
|
|
"devDependencies": [
|
|
"embla-carousel-svelte@^8.6.0",
|
|
"@lucide/svelte@^0.561.0",
|
|
"bits-ui@^2.14.4",
|
|
"@internationalized/date@^3.10.0"
|
|
],
|
|
"registryDependencies": [
|
|
"button"
|
|
],
|
|
"files": [
|
|
{
|
|
"content": "<script lang=\"ts\">\n\timport emblaCarouselSvelte from \"embla-carousel-svelte\";\n\timport type { HTMLAttributes } from \"svelte/elements\";\n\timport { getEmblaContext } from \"./context.js\";\n\timport { cn, type WithElementRef } from \"$UTILS$.js\";\n\n\tlet {\n\t\tref = $bindable(null),\n\t\tclass: className,\n\t\tchildren,\n\t\t...restProps\n\t}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();\n\n\tconst emblaCtx = getEmblaContext(\"<Carousel.Content/>\");\n</script>\n\n<div\n\tdata-slot=\"carousel-content\"\n\tclass=\"overflow-hidden\"\n\tuse:emblaCarouselSvelte={{\n\t\toptions: {\n\t\t\tcontainer: \"[data-embla-container]\",\n\t\t\tslides: \"[data-embla-slide]\",\n\t\t\t...emblaCtx.options,\n\t\t\taxis: emblaCtx.orientation === \"horizontal\" ? \"x\" : \"y\",\n\t\t},\n\t\tplugins: emblaCtx.plugins,\n\t}}\n\tonemblaInit={emblaCtx.onInit}\n>\n\t<div\n\t\tbind:this={ref}\n\t\tclass={cn(\n\t\t\t\"flex\",\n\t\t\temblaCtx.orientation === \"horizontal\" ? \"-ms-4\" : \"-mt-4 flex-col\",\n\t\t\tclassName\n\t\t)}\n\t\tdata-embla-container=\"\"\n\t\t{...restProps}\n\t>\n\t\t{@render children?.()}\n\t</div>\n</div>\n",
|
|
"type": "registry:file",
|
|
"target": "carousel/carousel-content.svelte"
|
|
},
|
|
{
|
|
"content": "<script lang=\"ts\">\n\timport type { HTMLAttributes } from \"svelte/elements\";\n\timport { getEmblaContext } from \"./context.js\";\n\timport { cn, type WithElementRef } from \"$UTILS$.js\";\n\n\tlet {\n\t\tref = $bindable(null),\n\t\tclass: className,\n\t\tchildren,\n\t\t...restProps\n\t}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();\n\n\tconst emblaCtx = getEmblaContext(\"<Carousel.Item/>\");\n</script>\n\n<div\n\tbind:this={ref}\n\tdata-slot=\"carousel-item\"\n\trole=\"group\"\n\taria-roledescription=\"slide\"\n\tclass={cn(\n\t\t\"min-w-0 shrink-0 grow-0 basis-full\",\n\t\temblaCtx.orientation === \"horizontal\" ? \"ps-4\" : \"pt-4\",\n\t\tclassName\n\t)}\n\tdata-embla-slide=\"\"\n\t{...restProps}\n>\n\t{@render children?.()}\n</div>\n",
|
|
"type": "registry:file",
|
|
"target": "carousel/carousel-item.svelte"
|
|
},
|
|
{
|
|
"content": "<script lang=\"ts\">\n\timport ArrowRightIcon from \"@lucide/svelte/icons/arrow-right\";\n\timport type { WithoutChildren } from \"bits-ui\";\n\timport { getEmblaContext } from \"./context.js\";\n\timport { cn } from \"$UTILS$.js\";\n\timport { Button, type Props } from \"$UI$/button/index.js\";\n\n\tlet {\n\t\tref = $bindable(null),\n\t\tclass: className,\n\t\tvariant = \"outline\",\n\t\tsize = \"icon\",\n\t\t...restProps\n\t}: WithoutChildren<Props> = $props();\n\n\tconst emblaCtx = getEmblaContext(\"<Carousel.Next/>\");\n</script>\n\n<Button\n\tdata-slot=\"carousel-next\"\n\t{variant}\n\t{size}\n\taria-disabled={!emblaCtx.canScrollNext}\n\tclass={cn(\n\t\t\"absolute size-8 rounded-full\",\n\t\temblaCtx.orientation === \"horizontal\"\n\t\t\t? \"inset-y-0 -end-12 my-auto\"\n\t\t\t: \"start-1/2 -bottom-12 -translate-x-1/2 rotate-90\",\n\t\tclassName\n\t)}\n\tonclick={emblaCtx.scrollNext}\n\tonkeydown={emblaCtx.handleKeyDown}\n\tbind:ref\n\t{...restProps}\n>\n\t<ArrowRightIcon class=\"size-4\" />\n\t<span class=\"sr-only\">Next slide</span>\n</Button>\n",
|
|
"type": "registry:file",
|
|
"target": "carousel/carousel-next.svelte"
|
|
},
|
|
{
|
|
"content": "<script lang=\"ts\">\n\timport ArrowLeftIcon from \"@lucide/svelte/icons/arrow-left\";\n\timport type { WithoutChildren } from \"bits-ui\";\n\timport { getEmblaContext } from \"./context.js\";\n\timport { cn } from \"$UTILS$.js\";\n\timport { Button, type Props } from \"$UI$/button/index.js\";\n\n\tlet {\n\t\tref = $bindable(null),\n\t\tclass: className,\n\t\tvariant = \"outline\",\n\t\tsize = \"icon\",\n\t\t...restProps\n\t}: WithoutChildren<Props> = $props();\n\n\tconst emblaCtx = getEmblaContext(\"<Carousel.Previous/>\");\n</script>\n\n<Button\n\tdata-slot=\"carousel-previous\"\n\t{variant}\n\t{size}\n\taria-disabled={!emblaCtx.canScrollPrev}\n\tclass={cn(\n\t\t\"absolute size-8 rounded-full\",\n\t\temblaCtx.orientation === \"horizontal\"\n\t\t\t? \"inset-y-0 -start-12 my-auto\"\n\t\t\t: \"start-1/2 -top-12 -translate-x-1/2 rotate-90\",\n\t\tclassName\n\t)}\n\tonclick={emblaCtx.scrollPrev}\n\tonkeydown={emblaCtx.handleKeyDown}\n\t{...restProps}\n\tbind:ref\n>\n\t<ArrowLeftIcon class=\"size-4\" />\n\t<span class=\"sr-only\">Previous slide</span>\n</Button>\n",
|
|
"type": "registry:file",
|
|
"target": "carousel/carousel-previous.svelte"
|
|
},
|
|
{
|
|
"content": "<script lang=\"ts\">\n\timport {\n\t\ttype CarouselAPI,\n\t\ttype CarouselProps,\n\t\ttype EmblaContext,\n\t\tsetEmblaContext,\n\t} from \"./context.js\";\n\timport { cn, type WithElementRef } from \"$UTILS$.js\";\n\n\tlet {\n\t\tref = $bindable(null),\n\t\topts = {},\n\t\tplugins = [],\n\t\tsetApi = () => {},\n\t\torientation = \"horizontal\",\n\t\tclass: className,\n\t\tchildren,\n\t\t...restProps\n\t}: WithElementRef<CarouselProps> = $props();\n\n\tlet carouselState = $state<EmblaContext>({\n\t\tapi: undefined,\n\t\tscrollPrev,\n\t\tscrollNext,\n\t\torientation,\n\t\tcanScrollNext: false,\n\t\tcanScrollPrev: false,\n\t\thandleKeyDown,\n\t\toptions: opts,\n\t\tplugins,\n\t\tonInit,\n\t\tscrollSnaps: [],\n\t\tselectedIndex: 0,\n\t\tscrollTo,\n\t});\n\n\tsetEmblaContext(carouselState);\n\n\tfunction scrollPrev() {\n\t\tcarouselState.api?.scrollPrev();\n\t}\n\n\tfunction scrollNext() {\n\t\tcarouselState.api?.scrollNext();\n\t}\n\n\tfunction scrollTo(index: number, jump?: boolean) {\n\t\tcarouselState.api?.scrollTo(index, jump);\n\t}\n\n\tfunction onSelect() {\n\t\tif (!carouselState.api) return;\n\t\tcarouselState.selectedIndex = carouselState.api.selectedScrollSnap();\n\t\tcarouselState.canScrollNext = carouselState.api.canScrollNext();\n\t\tcarouselState.canScrollPrev = carouselState.api.canScrollPrev();\n\t}\n\n\tfunction handleKeyDown(e: KeyboardEvent) {\n\t\tif (e.key === \"ArrowLeft\") {\n\t\t\te.preventDefault();\n\t\t\tscrollPrev();\n\t\t} else if (e.key === \"ArrowRight\") {\n\t\t\te.preventDefault();\n\t\t\tscrollNext();\n\t\t}\n\t}\n\n\tfunction onInit(event: CustomEvent<CarouselAPI>) {\n\t\tcarouselState.api = event.detail;\n\t\tsetApi(carouselState.api);\n\n\t\tcarouselState.scrollSnaps = carouselState.api.scrollSnapList();\n\t\tcarouselState.api.on(\"select\", onSelect);\n\t\tonSelect();\n\t}\n\n\t$effect(() => {\n\t\treturn () => {\n\t\t\tcarouselState.api?.off(\"select\", onSelect);\n\t\t};\n\t});\n</script>\n\n<div\n\tbind:this={ref}\n\tdata-slot=\"carousel\"\n\tclass={cn(\"relative\", className)}\n\trole=\"region\"\n\taria-roledescription=\"carousel\"\n\t{...restProps}\n>\n\t{@render children?.()}\n</div>\n",
|
|
"type": "registry:file",
|
|
"target": "carousel/carousel.svelte"
|
|
},
|
|
{
|
|
"content": "import type { WithElementRef } from \"$UTILS$.js\";\nimport type {\n\tEmblaCarouselSvelteType,\n\tdefault as emblaCarouselSvelte,\n} from \"embla-carousel-svelte\";\nimport { getContext, hasContext, setContext } from \"svelte\";\nimport type { HTMLAttributes } from \"svelte/elements\";\n\nexport type CarouselAPI =\n\tNonNullable<NonNullable<EmblaCarouselSvelteType[\"$$_attributes\"]>[\"on:emblaInit\"]> extends (\n\t\tevt: CustomEvent<infer CarouselAPI>\n\t) => void\n\t\t? CarouselAPI\n\t\t: never;\n\ntype EmblaCarouselConfig = NonNullable<Parameters<typeof emblaCarouselSvelte>[1]>;\n\nexport type CarouselOptions = EmblaCarouselConfig[\"options\"];\nexport type CarouselPlugins = EmblaCarouselConfig[\"plugins\"];\n\n////\n\nexport type CarouselProps = {\n\topts?: CarouselOptions;\n\tplugins?: CarouselPlugins;\n\tsetApi?: (api: CarouselAPI | undefined) => void;\n\torientation?: \"horizontal\" | \"vertical\";\n} & WithElementRef<HTMLAttributes<HTMLDivElement>>;\n\nconst EMBLA_CAROUSEL_CONTEXT = Symbol(\"EMBLA_CAROUSEL_CONTEXT\");\n\nexport type EmblaContext = {\n\tapi: CarouselAPI | undefined;\n\torientation: \"horizontal\" | \"vertical\";\n\tscrollNext: () => void;\n\tscrollPrev: () => void;\n\tcanScrollNext: boolean;\n\tcanScrollPrev: boolean;\n\thandleKeyDown: (e: KeyboardEvent) => void;\n\toptions: CarouselOptions;\n\tplugins: CarouselPlugins;\n\tonInit: (e: CustomEvent<CarouselAPI>) => void;\n\tscrollTo: (index: number, jump?: boolean) => void;\n\tscrollSnaps: number[];\n\tselectedIndex: number;\n};\n\nexport function setEmblaContext(config: EmblaContext): EmblaContext {\n\tsetContext(EMBLA_CAROUSEL_CONTEXT, config);\n\treturn config;\n}\n\nexport function getEmblaContext(name = \"This component\") {\n\tif (!hasContext(EMBLA_CAROUSEL_CONTEXT)) {\n\t\tthrow new Error(`${name} must be used within a <Carousel.Root> component`);\n\t}\n\treturn getContext<ReturnType<typeof setEmblaContext>>(EMBLA_CAROUSEL_CONTEXT);\n}\n",
|
|
"type": "registry:file",
|
|
"target": "carousel/context.ts"
|
|
},
|
|
{
|
|
"content": "import Root from \"./carousel.svelte\";\nimport Content from \"./carousel-content.svelte\";\nimport Item from \"./carousel-item.svelte\";\nimport Previous from \"./carousel-previous.svelte\";\nimport Next from \"./carousel-next.svelte\";\n\nexport {\n\tRoot,\n\tContent,\n\tItem,\n\tPrevious,\n\tNext,\n\t//\n\tRoot as Carousel,\n\tContent as CarouselContent,\n\tItem as CarouselItem,\n\tPrevious as CarouselPrevious,\n\tNext as CarouselNext,\n};\n",
|
|
"type": "registry:file",
|
|
"target": "carousel/index.ts"
|
|
}
|
|
]
|
|
} |