{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "carousel-peek",
  "title": "Carousel Peek",
  "description": "A responsive carousel with one slide and a peek of the next on phones, two or three per view on wider containers, paged dots and a \"Showing 1-2 of 6\" readout.",
  "dependencies": [
    "embla-carousel-react@^8.6.0",
    "embla-carousel@^8.6.0",
    "lucide-react"
  ],
  "registryDependencies": [
    "@tealmac/carousel-kit"
  ],
  "files": [
    {
      "path": "registry/tealmac/carousel-peek.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\nimport {\n  Carousel,\n  CarouselDots,\n  CarouselNext,\n  CarouselPrevious,\n  CarouselSlide,\n  CarouselTrack,\n  CarouselViewport,\n  useCarousel,\n  type CarouselApi,\n  type CarouselItem,\n} from \"@/registry/tealmac/carousel-kit\"\n\nfunction VisibleRange({ total }: { total: number }) {\n  const { api, index } = useCarousel()\n  const [range, setRange] = React.useState<[number, number]>([1, 1])\n  React.useEffect(() => {\n    if (!api) return\n    const update = () => {\n      const inView = api.slidesInView()\n      if (inView.length)\n        setRange([Math.min(...inView) + 1, Math.max(...inView) + 1])\n    }\n    update()\n    api.on(\"slidesInView\", update).on(\"reInit\", update).on(\"select\", update)\n    return () => {\n      api\n        .off(\"slidesInView\", update)\n        .off(\"reInit\", update)\n        .off(\"select\", update)\n    }\n  }, [api, index])\n  return (\n    <p className=\"text-muted-foreground text-sm tabular-nums\">\n      Showing {range[0]}\n      {range[1] !== range[0] ? `–${range[1]}` : \"\"} of {total}\n    </p>\n  )\n}\n\nexport interface CarouselPeekProps {\n  items: CarouselItem[]\n  label: string\n  /**\n   * Slide width classes. The default shows one slide with a peek of the next on a phone,\n   * two from a 28rem container, three from 44rem.\n   */\n  slideClassName?: string\n  className?: string\n  /** Called with the snap index whenever the selection changes. */\n  onIndexChange?: (index: number) => void\n  /** Receive the Embla API, for controls placed outside the carousel. */\n  setApi?: (api: CarouselApi) => void\n}\n\n/** Several slides per view that change with the container width, with the next slide peeking in so people know there is more. Dots are per page. */\nexport function CarouselPeek({\n  items,\n  label,\n  slideClassName = \"basis-[85%] @md:basis-[46%] @2xl:basis-[31%]\",\n  className,\n  onIndexChange,\n  setApi,\n}: CarouselPeekProps) {\n  return (\n    <Carousel\n      label={label}\n      onIndexChange={onIndexChange}\n      setApi={setApi}\n      opts={{\n        align: \"start\",\n        slidesToScroll: \"auto\",\n        containScroll: \"trimSnaps\",\n      }}\n      className={cn(\"@container\", className)}\n    >\n      <CarouselViewport>\n        <CarouselTrack className=\"-ms-3\">\n          {items.map((item) => (\n            <CarouselSlide key={item.id} className={cn(\"ps-3\", slideClassName)}>\n              {item.content}\n            </CarouselSlide>\n          ))}\n        </CarouselTrack>\n      </CarouselViewport>\n      <div className=\"mt-3 flex items-center justify-between gap-3\">\n        <VisibleRange total={items.length} />\n        <CarouselDots />\n        <div className=\"flex gap-2\">\n          <CarouselPrevious />\n          <CarouselNext />\n        </div>\n      </div>\n    </Carousel>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}