@opensite/ui 0.7.9 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/registry.cjs CHANGED
@@ -17990,192 +17990,49 @@ function CarouselAutoplayProgress({
17990
17990
  }
17991
17991
  );
17992
17992
  }
17993
- var CarouselContext = React52__namespace.createContext(null);
17994
- function useCarousel() {
17995
- const context = React52__namespace.useContext(CarouselContext);
17996
- if (!context) {
17997
- throw new Error("useCarousel must be used within a <Carousel />");
17998
- }
17999
- return context;
18000
- }
18001
- function Carousel({
18002
- orientation = "horizontal",
18003
- opts,
18004
- setApi,
18005
- plugins,
17993
+ function CarouselPagination({
17994
+ onPrevious,
17995
+ onNext,
17996
+ canScrollPrevious = true,
17997
+ canScrollNext = true,
17998
+ iconSize = 24,
18006
17999
  className,
18007
- children,
18008
- ...props
18000
+ buttonClassName,
18001
+ previousIcon = "lucide/arrow-left",
18002
+ nextIcon = "lucide/arrow-right",
18003
+ previousAriaLabel = "Previous",
18004
+ nextAriaLabel = "Next"
18009
18005
  }) {
18010
- const [carouselRef, api] = useEmblaCarousel__default.default(
18011
- {
18012
- ...opts,
18013
- axis: orientation === "horizontal" ? "x" : "y"
18014
- },
18015
- plugins
18016
- );
18017
- const [canScrollPrev, setCanScrollPrev] = React52__namespace.useState(false);
18018
- const [canScrollNext, setCanScrollNext] = React52__namespace.useState(false);
18019
- const onSelect = React52__namespace.useCallback((api2) => {
18020
- if (!api2) return;
18021
- setCanScrollPrev(api2.canScrollPrev());
18022
- setCanScrollNext(api2.canScrollNext());
18023
- }, []);
18024
- const scrollPrev = React52__namespace.useCallback(() => {
18025
- api?.scrollPrev();
18026
- }, [api]);
18027
- const scrollNext = React52__namespace.useCallback(() => {
18028
- api?.scrollNext();
18029
- }, [api]);
18030
- const handleKeyDown = React52__namespace.useCallback(
18031
- (event) => {
18032
- if (event.key === "ArrowLeft") {
18033
- event.preventDefault();
18034
- scrollPrev();
18035
- } else if (event.key === "ArrowRight") {
18036
- event.preventDefault();
18037
- scrollNext();
18006
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex justify-end gap-2", className), children: [
18007
+ /* @__PURE__ */ jsxRuntime.jsx(
18008
+ Pressable,
18009
+ {
18010
+ onClick: onPrevious,
18011
+ disabled: !canScrollPrevious,
18012
+ "aria-label": previousAriaLabel,
18013
+ asButton: true,
18014
+ className: cn(
18015
+ "relative z-40 flex h-10 w-10 items-center justify-center rounded-full disabled:opacity-50",
18016
+ buttonClassName
18017
+ ),
18018
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: previousIcon, size: iconSize })
18038
18019
  }
18039
- },
18040
- [scrollPrev, scrollNext]
18041
- );
18042
- React52__namespace.useEffect(() => {
18043
- if (!api || !setApi) return;
18044
- setApi(api);
18045
- }, [api, setApi]);
18046
- React52__namespace.useEffect(() => {
18047
- if (!api) return;
18048
- onSelect(api);
18049
- api.on("reInit", onSelect);
18050
- api.on("select", onSelect);
18051
- return () => {
18052
- api?.off("select", onSelect);
18053
- };
18054
- }, [api, onSelect]);
18055
- return /* @__PURE__ */ jsxRuntime.jsx(
18056
- CarouselContext.Provider,
18057
- {
18058
- value: {
18059
- carouselRef,
18060
- api,
18061
- opts,
18062
- orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
18063
- scrollPrev,
18064
- scrollNext,
18065
- canScrollPrev,
18066
- canScrollNext
18067
- },
18068
- children: /* @__PURE__ */ jsxRuntime.jsx(
18069
- "div",
18070
- {
18071
- onKeyDownCapture: handleKeyDown,
18072
- className: cn("relative", className),
18073
- role: "region",
18074
- "aria-roledescription": "carousel",
18075
- "data-slot": "carousel",
18076
- ...props,
18077
- children
18078
- }
18079
- )
18080
- }
18081
- );
18082
- }
18083
- function CarouselContent({ className, ...props }) {
18084
- const { carouselRef, orientation } = useCarousel();
18085
- return /* @__PURE__ */ jsxRuntime.jsx(
18086
- "div",
18087
- {
18088
- ref: carouselRef,
18089
- className: "overflow-hidden",
18090
- "data-slot": "carousel-content",
18091
- children: /* @__PURE__ */ jsxRuntime.jsx(
18092
- "div",
18093
- {
18094
- className: cn(
18095
- "flex",
18096
- orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
18097
- className
18098
- ),
18099
- ...props
18100
- }
18101
- )
18102
- }
18103
- );
18104
- }
18105
- function CarouselItem({ className, ...props }) {
18106
- const { orientation } = useCarousel();
18107
- return /* @__PURE__ */ jsxRuntime.jsx(
18108
- "div",
18109
- {
18110
- role: "group",
18111
- "aria-roledescription": "slide",
18112
- "data-slot": "carousel-item",
18113
- className: cn(
18114
- "min-w-0 shrink-0 grow-0 basis-full",
18115
- orientation === "horizontal" ? "pl-4" : "pt-4",
18116
- className
18117
- ),
18118
- ...props
18119
- }
18120
- );
18121
- }
18122
- function CarouselPrevious({
18123
- className,
18124
- variant = "outline",
18125
- size = "icon",
18126
- ...props
18127
- }) {
18128
- const { orientation, scrollPrev, canScrollPrev } = useCarousel();
18129
- return /* @__PURE__ */ jsxRuntime.jsxs(
18130
- Pressable,
18131
- {
18132
- "data-slot": "carousel-previous",
18133
- variant,
18134
- size,
18135
- className: cn(
18136
- "absolute size-8 rounded-full",
18137
- orientation === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
18138
- className
18139
- ),
18140
- disabled: !canScrollPrev,
18141
- onClick: scrollPrev,
18142
- asButton: true,
18143
- ...props,
18144
- children: [
18145
- /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/arrow-left" }),
18146
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Previous slide" })
18147
- ]
18148
- }
18149
- );
18150
- }
18151
- function CarouselNext({
18152
- className,
18153
- variant = "outline",
18154
- size = "icon",
18155
- ...props
18156
- }) {
18157
- const { orientation, scrollNext, canScrollNext } = useCarousel();
18158
- return /* @__PURE__ */ jsxRuntime.jsxs(
18159
- Pressable,
18160
- {
18161
- "data-slot": "carousel-next",
18162
- variant,
18163
- size,
18164
- className: cn(
18165
- "absolute size-8 rounded-full",
18166
- orientation === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
18167
- className
18168
- ),
18169
- disabled: !canScrollNext,
18170
- onClick: scrollNext,
18171
- asButton: true,
18172
- ...props,
18173
- children: [
18174
- /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/arrow-right" }),
18175
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Next slide" })
18176
- ]
18177
- }
18178
- );
18020
+ ),
18021
+ /* @__PURE__ */ jsxRuntime.jsx(
18022
+ Pressable,
18023
+ {
18024
+ onClick: onNext,
18025
+ disabled: !canScrollNext,
18026
+ "aria-label": nextAriaLabel,
18027
+ asButton: true,
18028
+ className: cn(
18029
+ "relative z-40 flex h-10 w-10 items-center justify-center rounded-full disabled:opacity-50",
18030
+ buttonClassName
18031
+ ),
18032
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: nextIcon, size: iconSize })
18033
+ }
18034
+ )
18035
+ ] });
18179
18036
  }
18180
18037
  var SLIDE_LAYOUT_ASPECT_MAP = {
18181
18038
  horizontal: "aspect-video",
@@ -18204,27 +18061,62 @@ function CarouselFeatureBadge({
18204
18061
  slideLayoutVariant = "square",
18205
18062
  containerMaxWidth = "2xl"
18206
18063
  }) {
18064
+ const [emblaRef, emblaApi] = useEmblaCarousel__default.default();
18065
+ const [canScrollPrev, setCanScrollPrev] = React52__namespace.useState(false);
18066
+ const [canScrollNext, setCanScrollNext] = React52__namespace.useState(false);
18067
+ const scrollPrev = React52__namespace.useCallback(() => {
18068
+ emblaApi?.scrollPrev();
18069
+ }, [emblaApi]);
18070
+ const scrollNext = React52__namespace.useCallback(() => {
18071
+ emblaApi?.scrollNext();
18072
+ }, [emblaApi]);
18073
+ const onSelect = React52__namespace.useCallback(() => {
18074
+ if (!emblaApi) return;
18075
+ setCanScrollPrev(emblaApi.canScrollPrev());
18076
+ setCanScrollNext(emblaApi.canScrollNext());
18077
+ }, [emblaApi]);
18078
+ React52__namespace.useEffect(() => {
18079
+ if (!emblaApi) return;
18080
+ onSelect();
18081
+ emblaApi.on("reInit", onSelect);
18082
+ emblaApi.on("select", onSelect);
18083
+ return () => {
18084
+ emblaApi?.off("select", onSelect);
18085
+ };
18086
+ }, [emblaApi, onSelect]);
18207
18087
  const renderCarouselItems = () => {
18208
18088
  if (itemsSlot) return itemsSlot;
18209
18089
  if (!items || items.length === 0) return null;
18210
- return items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(CarouselItem, { className: carouselItemClassName, children: /* @__PURE__ */ jsxRuntime.jsx(
18090
+ return items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
18211
18091
  "div",
18212
18092
  {
18093
+ role: "group",
18094
+ "aria-roledescription": "slide",
18213
18095
  className: cn(
18214
- "flex items-center justify-center overflow-hidden rounded-2xl",
18215
- SLIDE_LAYOUT_ASPECT_MAP[slideLayoutVariant]
18096
+ "min-w-0 shrink-0 grow-0 basis-full pl-4",
18097
+ carouselItemClassName
18216
18098
  ),
18217
18099
  children: /* @__PURE__ */ jsxRuntime.jsx(
18218
- img.Img,
18100
+ "div",
18219
18101
  {
18220
- src: item.src,
18221
- alt: item.alt,
18222
- className: cn("h-full w-full object-cover", item.className),
18223
- optixFlowConfig
18102
+ className: cn(
18103
+ "flex items-center justify-center overflow-hidden rounded-2xl",
18104
+ SLIDE_LAYOUT_ASPECT_MAP[slideLayoutVariant]
18105
+ ),
18106
+ children: /* @__PURE__ */ jsxRuntime.jsx(
18107
+ img.Img,
18108
+ {
18109
+ src: item.src,
18110
+ alt: item.alt,
18111
+ className: cn("h-full w-full object-cover", item.className),
18112
+ optixFlowConfig
18113
+ }
18114
+ )
18224
18115
  }
18225
18116
  )
18226
- }
18227
- ) }, index));
18117
+ },
18118
+ index
18119
+ ));
18228
18120
  };
18229
18121
  return /* @__PURE__ */ jsxRuntime.jsx(
18230
18122
  Section,
@@ -18267,10 +18159,18 @@ function CarouselFeatureBadge({
18267
18159
  ]
18268
18160
  }
18269
18161
  ),
18270
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full max-w-full px-6", carouselClassName), children: /* @__PURE__ */ jsxRuntime.jsxs(Carousel, { children: [
18271
- /* @__PURE__ */ jsxRuntime.jsx(CarouselContent, { children: renderCarouselItems() }),
18272
- /* @__PURE__ */ jsxRuntime.jsx(CarouselPrevious, {}),
18273
- /* @__PURE__ */ jsxRuntime.jsx(CarouselNext, {})
18162
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full max-w-full", carouselClassName), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
18163
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: emblaRef, className: "overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex -ml-4", children: renderCarouselItems() }) }),
18164
+ /* @__PURE__ */ jsxRuntime.jsx(
18165
+ CarouselPagination,
18166
+ {
18167
+ onPrevious: scrollPrev,
18168
+ onNext: scrollNext,
18169
+ canScrollPrevious: canScrollPrev,
18170
+ canScrollNext,
18171
+ className: "mt-4"
18172
+ }
18173
+ )
18274
18174
  ] }) })
18275
18175
  ] }) })
18276
18176
  }
@@ -18692,28 +18592,22 @@ function CarouselHorizontalCards({
18692
18592
  const carouselRef = React52__namespace.useRef(null);
18693
18593
  const [isAtStart, setIsAtStart] = React52__namespace.useState(true);
18694
18594
  const [isAtEnd, setIsAtEnd] = React52__namespace.useState(false);
18695
- const getCardWidth = React52__namespace.useCallback(() => {
18696
- if (typeof window === "undefined") return 320;
18697
- if (window.innerWidth >= 1024) return 400;
18698
- if (window.innerWidth >= 640) return 360;
18699
- return 320;
18700
- }, []);
18701
- const scroll = (direction) => {
18595
+ const scrollLeft = () => {
18702
18596
  if (carouselRef.current) {
18703
- const { scrollLeft } = carouselRef.current;
18704
- const cardWidth = getCardWidth();
18705
- const gap = 16;
18706
- const scrollAmount = cardWidth + gap;
18707
- const newScrollLeft = direction === "left" ? scrollLeft - scrollAmount : scrollLeft + scrollAmount;
18708
- carouselRef.current.scrollTo({ left: newScrollLeft, behavior: "smooth" });
18597
+ carouselRef.current.scrollBy({ left: -300, behavior: "smooth" });
18598
+ }
18599
+ };
18600
+ const scrollRight = () => {
18601
+ if (carouselRef.current) {
18602
+ carouselRef.current.scrollBy({ left: 300, behavior: "smooth" });
18709
18603
  }
18710
18604
  };
18711
18605
  React52__namespace.useEffect(() => {
18712
18606
  const checkScrollPosition = () => {
18713
18607
  if (carouselRef.current) {
18714
- const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current;
18715
- setIsAtStart(scrollLeft < 10);
18716
- setIsAtEnd(scrollLeft + clientWidth >= scrollWidth - 10);
18608
+ const { scrollLeft: scrollLeft2, scrollWidth, clientWidth } = carouselRef.current;
18609
+ setIsAtStart(scrollLeft2 < 10);
18610
+ setIsAtEnd(scrollLeft2 + clientWidth >= scrollWidth - 10);
18717
18611
  }
18718
18612
  };
18719
18613
  const currentRef = carouselRef.current;
@@ -18729,41 +18623,6 @@ function CarouselHorizontalCards({
18729
18623
  window.removeEventListener("resize", checkScrollPosition);
18730
18624
  };
18731
18625
  }, [items]);
18732
- const renderItems = () => {
18733
- if (itemsSlot) return itemsSlot;
18734
- if (!items || items.length === 0) return null;
18735
- return items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
18736
- framerMotion.motion.div,
18737
- {
18738
- className: cn(
18739
- "group w-[320px] shrink-0 snap-start sm:w-[360px] lg:w-[400px]",
18740
- item.className
18741
- ),
18742
- initial: { opacity: 0, y: 20 },
18743
- animate: { opacity: 1, y: 0 },
18744
- transition: { duration: 0.5, delay: index * 0.1 },
18745
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-lg border bg-card text-card-foreground shadow-sm transition-shadow hover:shadow-md", children: [
18746
- /* @__PURE__ */ jsxRuntime.jsx(
18747
- img.Img,
18748
- {
18749
- alt: typeof item.title === "string" ? item.title : `Card ${index + 1}`,
18750
- className: cn("aspect-video w-full object-cover transition-transform group-hover:scale-105", item.imageClassName),
18751
- src: item.imageSrc,
18752
- optixFlowConfig
18753
- }
18754
- ),
18755
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
18756
- item.title && (typeof item.title === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-md font-semibold leading-tight text-card-foreground", children: item.title }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.title })),
18757
- (item.count !== void 0 || item.countLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
18758
- item.count !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-bold", children: item.count }),
18759
- item.countLabel && (typeof item.countLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground", children: item.countLabel }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.countLabel }))
18760
- ] })
18761
- ] })
18762
- ] })
18763
- },
18764
- item.id
18765
- ));
18766
- };
18767
18626
  return /* @__PURE__ */ jsxRuntime.jsx(
18768
18627
  Section,
18769
18628
  {
@@ -18774,74 +18633,143 @@ function CarouselHorizontalCards({
18774
18633
  patternOpacity,
18775
18634
  "aria-labelledby": "carousel-title",
18776
18635
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("container mx-auto px-4 md:px-6", containerClassName), children: [
18777
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-8 flex items-center justify-between gap-4", headerClassName), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
18778
- heading && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: headingHref, className: "group inline-flex items-center", children: [
18779
- typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
18780
- "h2",
18781
- {
18782
- id: "carousel-title",
18783
- className: cn("text-2xl font-bold tracking-tight text-card-foreground md:text-3xl", headingClassName),
18784
- children: heading
18785
- }
18786
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading }),
18787
- /* @__PURE__ */ jsxRuntime.jsx(
18788
- DynamicIcon,
18789
- {
18790
- name: "lucide/chevron-right",
18791
- size: 24,
18792
- className: "ml-2 flex-shrink-0 self-center transition-transform group-hover:translate-x-1"
18793
- }
18794
- )
18795
- ] }),
18796
- subtitle && (typeof subtitle === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-1 text-muted-foreground", subtitleClassName), children: subtitle }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: subtitleClassName, children: subtitle }))
18797
- ] }) }),
18798
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
18636
+ /* @__PURE__ */ jsxRuntime.jsx(
18637
+ "div",
18638
+ {
18639
+ className: cn(
18640
+ "mb-8 flex items-center justify-between gap-4",
18641
+ headerClassName
18642
+ ),
18643
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
18644
+ heading && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: headingHref, className: "group inline-flex items-center", children: [
18645
+ typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
18646
+ "h2",
18647
+ {
18648
+ id: "carousel-title",
18649
+ className: cn(
18650
+ "text-2xl font-bold tracking-tight text-card-foreground md:text-3xl",
18651
+ headingClassName
18652
+ ),
18653
+ children: heading
18654
+ }
18655
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading }),
18656
+ /* @__PURE__ */ jsxRuntime.jsx(
18657
+ DynamicIcon,
18658
+ {
18659
+ name: "lucide/chevron-right",
18660
+ size: 24,
18661
+ className: "ml-2 shrink-0 self-center transition-transform group-hover:translate-x-1"
18662
+ }
18663
+ )
18664
+ ] }),
18665
+ subtitle && (typeof subtitle === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
18666
+ "p",
18667
+ {
18668
+ className: cn(
18669
+ "mt-1 text-muted-foreground",
18670
+ subtitleClassName
18671
+ ),
18672
+ children: subtitle
18673
+ }
18674
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: subtitleClassName, children: subtitle }))
18675
+ ] })
18676
+ }
18677
+ ),
18678
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", children: [
18799
18679
  /* @__PURE__ */ jsxRuntime.jsx(
18800
18680
  "div",
18801
18681
  {
18682
+ className: "flex w-full overflow-x-scroll overscroll-x-auto scroll-smooth py-4 [scrollbar-width:none] md:py-6",
18802
18683
  ref: carouselRef,
18803
- className: cn(
18804
- "scrollbar-hide flex w-full space-x-4 overflow-x-auto pb-4",
18805
- "snap-x snap-mandatory scroll-pl-0",
18806
- carouselClassName
18807
- ),
18808
- children: renderItems()
18809
- }
18810
- ),
18811
- !isAtStart && /* @__PURE__ */ jsxRuntime.jsx(
18812
- Pressable,
18813
- {
18814
- onClick: () => scroll("left"),
18815
- className: cn(
18816
- "absolute left-4 top-1/2 z-10 -translate-y-1/2",
18817
- "flex h-12 w-12 items-center justify-center",
18818
- "rounded-full border border-border/50 bg-background shadow-lg",
18819
- "text-foreground transition-all duration-200",
18820
- "hover:bg-accent hover:shadow-xl hover:scale-105",
18821
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
18822
- navigationClassName
18823
- ),
18824
- "aria-label": "Scroll left",
18825
- asButton: true,
18826
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-left", size: 24 })
18684
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
18685
+ "div",
18686
+ {
18687
+ className: cn(
18688
+ "flex flex-row justify-start gap-4 pl-4",
18689
+ carouselClassName
18690
+ ),
18691
+ children: [
18692
+ items?.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
18693
+ framerMotion.motion.div,
18694
+ {
18695
+ className: cn(
18696
+ "rounded-lg last:pr-[5%] md:last:pr-[33%]"
18697
+ ),
18698
+ initial: { opacity: 0, y: 20 },
18699
+ animate: { opacity: 1, y: 0 },
18700
+ transition: { duration: 0.5, delay: 0.2 * index, ease: "easeOut" },
18701
+ children: /* @__PURE__ */ jsxRuntime.jsx(
18702
+ "div",
18703
+ {
18704
+ className: cn(
18705
+ "group w-56 shrink-0 md:w-96",
18706
+ item.className
18707
+ ),
18708
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-lg border bg-card text-card-foreground shadow-sm transition-shadow hover:shadow-md", children: [
18709
+ /* @__PURE__ */ jsxRuntime.jsx(
18710
+ img.Img,
18711
+ {
18712
+ alt: typeof item.title === "string" ? item.title : `Card ${index + 1}`,
18713
+ className: cn(
18714
+ "aspect-video w-full object-cover transition-transform group-hover:scale-105",
18715
+ item.imageClassName
18716
+ ),
18717
+ src: item.imageSrc,
18718
+ optixFlowConfig
18719
+ }
18720
+ ),
18721
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
18722
+ item.title && (typeof item.title === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-md font-semibold leading-tight text-card-foreground", children: item.title }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.title })),
18723
+ (item.count !== void 0 || item.countLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
18724
+ item.count !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-bold", children: item.count }),
18725
+ item.countLabel && (typeof item.countLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground", children: item.countLabel }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.countLabel }))
18726
+ ] }),
18727
+ item.actions && item.actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex flex-wrap gap-2", children: item.actions.map((action, actionIndex) => {
18728
+ const {
18729
+ label,
18730
+ icon,
18731
+ iconAfter,
18732
+ children,
18733
+ className: actionClassName,
18734
+ asButton,
18735
+ ...pressableProps
18736
+ } = action;
18737
+ return /* @__PURE__ */ jsxRuntime.jsx(
18738
+ Pressable,
18739
+ {
18740
+ asButton,
18741
+ className: actionClassName,
18742
+ ...pressableProps,
18743
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18744
+ icon,
18745
+ label,
18746
+ iconAfter
18747
+ ] })
18748
+ },
18749
+ actionIndex
18750
+ );
18751
+ }) })
18752
+ ] })
18753
+ ] })
18754
+ }
18755
+ )
18756
+ },
18757
+ item.id
18758
+ )),
18759
+ itemsSlot
18760
+ ]
18761
+ }
18762
+ )
18827
18763
  }
18828
18764
  ),
18829
- !isAtEnd && /* @__PURE__ */ jsxRuntime.jsx(
18830
- Pressable,
18765
+ /* @__PURE__ */ jsxRuntime.jsx(
18766
+ CarouselPagination,
18831
18767
  {
18832
- onClick: () => scroll("right"),
18833
- className: cn(
18834
- "absolute right-4 top-1/2 z-10 -translate-y-1/2",
18835
- "flex h-12 w-12 items-center justify-center",
18836
- "rounded-full border border-border/50 bg-background shadow-lg",
18837
- "text-foreground transition-all duration-200",
18838
- "hover:bg-accent hover:shadow-xl hover:scale-105",
18839
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
18840
- navigationClassName
18841
- ),
18842
- "aria-label": "Scroll right",
18843
- asButton: true,
18844
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-right", size: 24 })
18768
+ onPrevious: scrollLeft,
18769
+ onNext: scrollRight,
18770
+ canScrollPrevious: !isAtStart,
18771
+ canScrollNext: !isAtEnd,
18772
+ className: cn("mr-0 md:mr-10", navigationClassName)
18845
18773
  }
18846
18774
  )
18847
18775
  ] })
@@ -19966,6 +19894,193 @@ function CarouselScrollingFeatureShowcase({
19966
19894
  }
19967
19895
  );
19968
19896
  }
19897
+ var CarouselContext = React52__namespace.createContext(null);
19898
+ function useCarousel() {
19899
+ const context = React52__namespace.useContext(CarouselContext);
19900
+ if (!context) {
19901
+ throw new Error("useCarousel must be used within a <Carousel />");
19902
+ }
19903
+ return context;
19904
+ }
19905
+ function Carousel({
19906
+ orientation = "horizontal",
19907
+ opts,
19908
+ setApi,
19909
+ plugins,
19910
+ className,
19911
+ children,
19912
+ ...props
19913
+ }) {
19914
+ const [carouselRef, api] = useEmblaCarousel__default.default(
19915
+ {
19916
+ ...opts,
19917
+ axis: orientation === "horizontal" ? "x" : "y"
19918
+ },
19919
+ plugins
19920
+ );
19921
+ const [canScrollPrev, setCanScrollPrev] = React52__namespace.useState(false);
19922
+ const [canScrollNext, setCanScrollNext] = React52__namespace.useState(false);
19923
+ const onSelect = React52__namespace.useCallback((api2) => {
19924
+ if (!api2) return;
19925
+ setCanScrollPrev(api2.canScrollPrev());
19926
+ setCanScrollNext(api2.canScrollNext());
19927
+ }, []);
19928
+ const scrollPrev = React52__namespace.useCallback(() => {
19929
+ api?.scrollPrev();
19930
+ }, [api]);
19931
+ const scrollNext = React52__namespace.useCallback(() => {
19932
+ api?.scrollNext();
19933
+ }, [api]);
19934
+ const handleKeyDown = React52__namespace.useCallback(
19935
+ (event) => {
19936
+ if (event.key === "ArrowLeft") {
19937
+ event.preventDefault();
19938
+ scrollPrev();
19939
+ } else if (event.key === "ArrowRight") {
19940
+ event.preventDefault();
19941
+ scrollNext();
19942
+ }
19943
+ },
19944
+ [scrollPrev, scrollNext]
19945
+ );
19946
+ React52__namespace.useEffect(() => {
19947
+ if (!api || !setApi) return;
19948
+ setApi(api);
19949
+ }, [api, setApi]);
19950
+ React52__namespace.useEffect(() => {
19951
+ if (!api) return;
19952
+ onSelect(api);
19953
+ api.on("reInit", onSelect);
19954
+ api.on("select", onSelect);
19955
+ return () => {
19956
+ api?.off("select", onSelect);
19957
+ };
19958
+ }, [api, onSelect]);
19959
+ return /* @__PURE__ */ jsxRuntime.jsx(
19960
+ CarouselContext.Provider,
19961
+ {
19962
+ value: {
19963
+ carouselRef,
19964
+ api,
19965
+ opts,
19966
+ orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
19967
+ scrollPrev,
19968
+ scrollNext,
19969
+ canScrollPrev,
19970
+ canScrollNext
19971
+ },
19972
+ children: /* @__PURE__ */ jsxRuntime.jsx(
19973
+ "div",
19974
+ {
19975
+ onKeyDownCapture: handleKeyDown,
19976
+ className: cn("relative", className),
19977
+ role: "region",
19978
+ "aria-roledescription": "carousel",
19979
+ "data-slot": "carousel",
19980
+ ...props,
19981
+ children
19982
+ }
19983
+ )
19984
+ }
19985
+ );
19986
+ }
19987
+ function CarouselContent({ className, ...props }) {
19988
+ const { carouselRef, orientation } = useCarousel();
19989
+ return /* @__PURE__ */ jsxRuntime.jsx(
19990
+ "div",
19991
+ {
19992
+ ref: carouselRef,
19993
+ className: "overflow-hidden",
19994
+ "data-slot": "carousel-content",
19995
+ children: /* @__PURE__ */ jsxRuntime.jsx(
19996
+ "div",
19997
+ {
19998
+ className: cn(
19999
+ "flex",
20000
+ orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
20001
+ className
20002
+ ),
20003
+ ...props
20004
+ }
20005
+ )
20006
+ }
20007
+ );
20008
+ }
20009
+ function CarouselItem({ className, ...props }) {
20010
+ const { orientation } = useCarousel();
20011
+ return /* @__PURE__ */ jsxRuntime.jsx(
20012
+ "div",
20013
+ {
20014
+ role: "group",
20015
+ "aria-roledescription": "slide",
20016
+ "data-slot": "carousel-item",
20017
+ className: cn(
20018
+ "min-w-0 shrink-0 grow-0 basis-full",
20019
+ orientation === "horizontal" ? "pl-4" : "pt-4",
20020
+ className
20021
+ ),
20022
+ ...props
20023
+ }
20024
+ );
20025
+ }
20026
+ function CarouselPrevious({
20027
+ className,
20028
+ variant = "outline",
20029
+ size = "icon",
20030
+ ...props
20031
+ }) {
20032
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel();
20033
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20034
+ Pressable,
20035
+ {
20036
+ "data-slot": "carousel-previous",
20037
+ variant,
20038
+ size,
20039
+ className: cn(
20040
+ "absolute size-8 rounded-full",
20041
+ orientation === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
20042
+ className
20043
+ ),
20044
+ disabled: !canScrollPrev,
20045
+ onClick: scrollPrev,
20046
+ asButton: true,
20047
+ ...props,
20048
+ children: [
20049
+ /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/arrow-left" }),
20050
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Previous slide" })
20051
+ ]
20052
+ }
20053
+ );
20054
+ }
20055
+ function CarouselNext({
20056
+ className,
20057
+ variant = "outline",
20058
+ size = "icon",
20059
+ ...props
20060
+ }) {
20061
+ const { orientation, scrollNext, canScrollNext } = useCarousel();
20062
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20063
+ Pressable,
20064
+ {
20065
+ "data-slot": "carousel-next",
20066
+ variant,
20067
+ size,
20068
+ className: cn(
20069
+ "absolute size-8 rounded-full",
20070
+ orientation === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
20071
+ className
20072
+ ),
20073
+ disabled: !canScrollNext,
20074
+ onClick: scrollNext,
20075
+ asButton: true,
20076
+ ...props,
20077
+ children: [
20078
+ /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/arrow-right" }),
20079
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Next slide" })
20080
+ ]
20081
+ }
20082
+ );
20083
+ }
19969
20084
  function FeatureShowcase({
19970
20085
  items,
19971
20086
  children,