@opensite/ui 0.7.7 → 0.7.8

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.js CHANGED
@@ -5,7 +5,7 @@ import { twMerge } from 'tailwind-merge';
5
5
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
6
6
  import { Img } from '@page-speed/img';
7
7
  import { cva } from 'class-variance-authority';
8
- import { motion, AnimatePresence, useMotionValue, useMotionTemplate, useScroll, useTransform, useSpring, useInView, useMotionValueEvent } from 'framer-motion';
8
+ import { motion, AnimatePresence, useMotionValue, useMotionTemplate, useSpring, useTransform, useInView, useScroll, useMotionValueEvent } from 'framer-motion';
9
9
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
10
10
  import { useForm, Form, Field } from '@page-speed/forms';
11
11
  import { TextInput as TextInput$1, Select, TextArea as TextArea$1, Radio } from '@page-speed/forms/inputs';
@@ -18483,7 +18483,8 @@ function CarouselGalleryThumbnails({
18483
18483
  background = "white",
18484
18484
  spacing = "xl",
18485
18485
  pattern,
18486
- patternOpacity
18486
+ patternOpacity,
18487
+ slideMediaBrightness = "50"
18487
18488
  }) {
18488
18489
  const [currentIndex, setCurrentIndex] = React52.useState(0);
18489
18490
  const prevSlide = React52.useCallback(() => {
@@ -18537,7 +18538,11 @@ function CarouselGalleryThumbnails({
18537
18538
  {
18538
18539
  src: image.src,
18539
18540
  alt: typeof image.alt === "string" ? image.alt : `Image ${index + 1}`,
18540
- className: cn("h-full w-full object-cover", image.imageClassName),
18541
+ className: cn(
18542
+ "h-full w-full object-cover",
18543
+ BRIGHTNESS_CLASS_MAP[slideMediaBrightness],
18544
+ image.imageClassName
18545
+ ),
18541
18546
  optixFlowConfig
18542
18547
  }
18543
18548
  )
@@ -18648,7 +18653,7 @@ function CarouselHorizontalCards({
18648
18653
  return items.map((item, index) => /* @__PURE__ */ jsx(
18649
18654
  motion.div,
18650
18655
  {
18651
- className: cn("group w-[280px] shrink-0", item.className),
18656
+ className: cn("group w-[320px] shrink-0 sm:w-[360px] lg:w-[400px]", item.className),
18652
18657
  initial: { opacity: 0, y: 20 },
18653
18658
  animate: { opacity: 1, y: 0 },
18654
18659
  transition: { duration: 0.5, delay: index * 0.1 },
@@ -18684,7 +18689,7 @@ function CarouselHorizontalCards({
18684
18689
  patternOpacity,
18685
18690
  "aria-labelledby": "carousel-title",
18686
18691
  children: /* @__PURE__ */ jsxs("div", { className: cn("container mx-auto px-4 md:px-6", containerClassName), children: [
18687
- /* @__PURE__ */ jsx("div", { className: cn("mb-6 flex items-center justify-between", headerClassName), children: /* @__PURE__ */ jsxs("div", { children: [
18692
+ /* @__PURE__ */ jsx("div", { className: cn("mb-8 flex items-center justify-between gap-4", headerClassName), children: /* @__PURE__ */ jsxs("div", { children: [
18688
18693
  heading && /* @__PURE__ */ jsxs("a", { href: headingHref, className: "group inline-flex items-center", children: [
18689
18694
  typeof heading === "string" ? /* @__PURE__ */ jsx(
18690
18695
  "h2",
@@ -18699,7 +18704,7 @@ function CarouselHorizontalCards({
18699
18704
  {
18700
18705
  name: "lucide/chevron-right",
18701
18706
  size: 24,
18702
- className: "ml-2 transition-transform group-hover:translate-x-1"
18707
+ className: "ml-2 flex-shrink-0 self-center transition-transform group-hover:translate-x-1"
18703
18708
  }
18704
18709
  )
18705
18710
  ] }),
@@ -18718,20 +18723,20 @@ function CarouselHorizontalCards({
18718
18723
  Pressable,
18719
18724
  {
18720
18725
  onClick: () => scroll("left"),
18721
- className: cn("absolute left-0 top-1/2 z-10 -translate-y-1/2 rounded-full border bg-background/60 p-2 text-foreground shadow-md backdrop-blur-sm transition-opacity hover:bg-background/80", navigationClassName),
18726
+ className: cn("absolute left-0 top-1/2 z-10 -translate-y-1/2 flex h-10 w-10 items-center justify-center rounded-full border bg-background/60 text-foreground shadow-md backdrop-blur-sm transition-opacity hover:bg-background/80", navigationClassName),
18722
18727
  "aria-label": "Scroll left",
18723
18728
  asButton: true,
18724
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/chevron-left", size: 24 })
18729
+ children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/chevron-left", size: 20 })
18725
18730
  }
18726
18731
  ),
18727
18732
  !isAtEnd && /* @__PURE__ */ jsx(
18728
18733
  Pressable,
18729
18734
  {
18730
18735
  onClick: () => scroll("right"),
18731
- className: cn("absolute right-0 top-1/2 z-10 -translate-y-1/2 rounded-full border bg-background/60 p-2 text-foreground shadow-md backdrop-blur-sm transition-opacity hover:bg-background/80", navigationClassName),
18736
+ className: cn("absolute right-0 top-1/2 z-10 -translate-y-1/2 flex h-10 w-10 items-center justify-center rounded-full border bg-background/60 text-foreground shadow-md backdrop-blur-sm transition-opacity hover:bg-background/80", navigationClassName),
18732
18737
  "aria-label": "Scroll right",
18733
18738
  asButton: true,
18734
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/chevron-right", size: 24 })
18739
+ children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/chevron-right", size: 20 })
18735
18740
  }
18736
18741
  )
18737
18742
  ] })
@@ -18787,7 +18792,7 @@ function CarouselImageHero({
18787
18792
  Pressable,
18788
18793
  {
18789
18794
  asButton: true,
18790
- className: cn("bg-primary-foreground text-primary dark:bg-primary dark:text-primary-foreground", actionClassName),
18795
+ className: actionClassName,
18791
18796
  ...pressableProps,
18792
18797
  children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
18793
18798
  icon,
@@ -18855,12 +18860,12 @@ function CarouselImageHero({
18855
18860
  children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/chevron-right", size: 24, className: "text-white" })
18856
18861
  }
18857
18862
  ),
18858
- /* @__PURE__ */ jsx("div", { className: cn("absolute bottom-6 left-1/2 z-10 flex -translate-x-1/2 gap-2", indicatorsClassName), children: images?.map((_, index) => /* @__PURE__ */ jsx(
18863
+ /* @__PURE__ */ jsx("div", { className: cn("absolute bottom-6 left-1/2 z-10 flex -translate-x-1/2 gap-3", indicatorsClassName), children: images?.map((_, index) => /* @__PURE__ */ jsx(
18859
18864
  "button",
18860
18865
  {
18861
18866
  onClick: () => setCurrentImageIndex(index),
18862
18867
  className: cn(
18863
- "h-2.5 w-2.5 rounded-full transition-colors",
18868
+ "flex h-3 w-3 items-center justify-center rounded-full transition-colors",
18864
18869
  index === currentImageIndex ? "bg-white" : "bg-white/50 hover:bg-white/80"
18865
18870
  ),
18866
18871
  "aria-label": `Go to image ${index + 1}`
@@ -18868,7 +18873,7 @@ function CarouselImageHero({
18868
18873
  index
18869
18874
  )) })
18870
18875
  ] }),
18871
- /* @__PURE__ */ jsx("div", { className: cn("container relative z-10 mx-auto flex min-h-[600px] flex-col items-center justify-center px-4 py-24 text-center md:px-6 md:py-32 2xl:max-w-[1400px]", containerClassName), children: /* @__PURE__ */ jsxs("div", { className: cn("max-w-3xl space-y-8", contentClassName), children: [
18876
+ /* @__PURE__ */ jsx("div", { className: cn("container relative z-10 mx-auto flex min-h-[600px] flex-col items-center justify-center px-4 py-16 text-center md:px-6 md:py-20", containerClassName), children: /* @__PURE__ */ jsxs("div", { className: cn("max-w-4xl space-y-6", contentClassName), children: [
18872
18877
  /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
18873
18878
  badge && (typeof badge === "string" ? /* @__PURE__ */ jsx("div", { className: cn("inline-flex items-center rounded-full bg-white/10 px-3 py-1 text-sm font-medium text-white backdrop-blur-sm", badgeClassName), children: /* @__PURE__ */ jsx("span", { children: badge }) }) : /* @__PURE__ */ jsx("div", { className: badgeClassName, children: badge })),
18874
18879
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsx("h1", { className: cn("text-4xl font-bold tracking-tight text-primary-foreground dark:text-primary sm:text-5xl md:text-6xl", headingClassName), children: heading }) : /* @__PURE__ */ jsx("div", { className: headingClassName, children: heading })),
@@ -19004,38 +19009,42 @@ function CarouselMultiStepShowcase({
19004
19009
  }
19005
19010
  ) : /* @__PURE__ */ jsx("div", { className: subheadingClassName, children: subheading }))
19006
19011
  ] }),
19007
- stepsSlot ? /* @__PURE__ */ jsx("div", { className: stepNavigationClassName, children: stepsSlot }) : /* @__PURE__ */ jsx(
19012
+ stepsSlot ? /* @__PURE__ */ jsx("div", { className: cn("hidden sm:block", stepNavigationClassName), children: stepsSlot }) : /* @__PURE__ */ jsx(
19008
19013
  "div",
19009
19014
  {
19010
19015
  className: cn(
19011
- "mb-8 flex flex-wrap justify-center gap-2",
19016
+ "mb-8 hidden flex-wrap justify-center gap-2 sm:flex",
19012
19017
  stepNavigationClassName
19013
19018
  ),
19014
- children: steps?.map((step, index) => /* @__PURE__ */ jsxs(
19015
- "button",
19016
- {
19017
- onClick: () => goToStep(index),
19018
- className: cn(
19019
- "flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium transition-all",
19020
- activeStep === index ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:bg-muted/80",
19021
- step.className
19022
- ),
19023
- children: [
19024
- /* @__PURE__ */ jsx(
19025
- "span",
19026
- {
19027
- className: cn(
19028
- "flex h-6 w-6 items-center justify-center rounded-full text-xs",
19029
- activeStep === index ? "bg-primary-foreground text-primary" : "bg-background"
19030
- ),
19031
- children: step.step
19032
- }
19019
+ children: steps?.map((step, index) => {
19020
+ const isCompleted = index < activeStep;
19021
+ const isActive = index === activeStep;
19022
+ return /* @__PURE__ */ jsxs(
19023
+ "button",
19024
+ {
19025
+ onClick: () => goToStep(index),
19026
+ className: cn(
19027
+ "flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium transition-all",
19028
+ isActive ? "bg-primary text-primary-foreground" : isCompleted ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:bg-muted/80",
19029
+ step.className
19033
19030
  ),
19034
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: typeof step.title === "string" ? step.title.split(":")[0] : step.title })
19035
- ]
19036
- },
19037
- step.id
19038
- ))
19031
+ children: [
19032
+ /* @__PURE__ */ jsx(
19033
+ "span",
19034
+ {
19035
+ className: cn(
19036
+ "flex h-6 w-6 items-center justify-center rounded-full text-xs",
19037
+ isActive ? "bg-primary-foreground text-primary" : isCompleted ? "bg-primary-foreground text-primary" : "bg-background"
19038
+ ),
19039
+ children: isCompleted ? /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/check", size: 14 }) : step.step
19040
+ }
19041
+ ),
19042
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: typeof step.title === "string" ? step.title.split(":")[0] : step.title })
19043
+ ]
19044
+ },
19045
+ step.id
19046
+ );
19047
+ })
19039
19048
  }
19040
19049
  ),
19041
19050
  /* @__PURE__ */ jsx(
@@ -19184,10 +19193,11 @@ function CarouselPortfolioHero({
19184
19193
  navigationClassName,
19185
19194
  counterClassName,
19186
19195
  optixFlowConfig,
19187
- background = "white",
19188
- spacing = "xl",
19196
+ background = "dark",
19197
+ spacing = "none",
19189
19198
  pattern,
19190
- patternOpacity
19199
+ patternOpacity,
19200
+ slideMediaBrightness = "50"
19191
19201
  }) {
19192
19202
  const [currentIndex, setCurrentIndex] = React52.useState(0);
19193
19203
  const goToNext = React52.useCallback(() => {
@@ -19233,7 +19243,7 @@ function CarouselPortfolioHero({
19233
19243
  pattern,
19234
19244
  patternOpacity,
19235
19245
  children: [
19236
- slidesSlot ? slidesSlot : slides?.map((slide, index) => /* @__PURE__ */ jsxs(
19246
+ slidesSlot ? slidesSlot : slides?.map((slide, index) => /* @__PURE__ */ jsx(
19237
19247
  "div",
19238
19248
  {
19239
19249
  className: cn(
@@ -19241,22 +19251,23 @@ function CarouselPortfolioHero({
19241
19251
  index === currentIndex ? "opacity-100" : "opacity-0",
19242
19252
  slide.className
19243
19253
  ),
19244
- children: [
19245
- /* @__PURE__ */ jsx(
19246
- Img,
19247
- {
19248
- src: slide.image,
19249
- alt: typeof slide.title === "string" ? slide.title : `Slide ${index + 1}`,
19250
- className: cn("h-full w-full object-cover", slide.imageClassName),
19251
- optixFlowConfig
19252
- }
19253
- ),
19254
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent" })
19255
- ]
19254
+ children: /* @__PURE__ */ jsx(
19255
+ Img,
19256
+ {
19257
+ src: slide.image,
19258
+ alt: typeof slide.title === "string" ? slide.title : `Slide ${index + 1}`,
19259
+ className: cn(
19260
+ "h-full w-full object-cover",
19261
+ BRIGHTNESS_CLASS_MAP[slideMediaBrightness],
19262
+ slide.imageClassName
19263
+ ),
19264
+ optixFlowConfig
19265
+ }
19266
+ )
19256
19267
  },
19257
19268
  slide.id
19258
19269
  )),
19259
- /* @__PURE__ */ jsx("div", { className: cn("relative z-10 flex h-full w-full flex-col justify-end p-4 pb-16 text-white sm:p-8 md:p-12", containerClassName), children: /* @__PURE__ */ jsx("div", { className: "container mx-auto", children: /* @__PURE__ */ jsxs("div", { className: cn("max-w-3xl", contentClassName), children: [
19270
+ /* @__PURE__ */ jsx("div", { className: cn("relative z-10 flex h-full w-full flex-col justify-end px-6 pb-16 text-white md:px-8 lg:px-12", containerClassName), children: /* @__PURE__ */ jsx("div", { className: "container mx-auto", children: /* @__PURE__ */ jsxs("div", { className: cn("max-w-4xl", contentClassName), children: [
19260
19271
  currentSlide?.tag && /* @__PURE__ */ jsx("div", { className: "mb-4", children: typeof currentSlide.tag === "string" ? /* @__PURE__ */ jsx("span", { className: cn("inline-block rounded-full bg-primary px-3 py-1 text-sm font-medium", tagClassName), children: currentSlide.tag }) : /* @__PURE__ */ jsx("div", { className: tagClassName, children: currentSlide.tag }) }),
19261
19272
  currentSlide?.title && (typeof currentSlide.title === "string" ? /* @__PURE__ */ jsx("h1", { className: cn("text-4xl font-bold sm:text-5xl md:text-6xl", titleClassName), children: currentSlide.title }) : /* @__PURE__ */ jsx("div", { className: titleClassName, children: currentSlide.title })),
19262
19273
  currentSlide?.description && (typeof currentSlide.description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("mt-4 text-lg text-white/80 sm:text-xl md:max-w-2xl", descriptionClassName), children: currentSlide.description }) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: currentSlide.description })),
@@ -19360,13 +19371,13 @@ function CarouselProductFeatureShowcase({
19360
19371
  const renderActions = () => {
19361
19372
  if (actionsSlot) return actionsSlot;
19362
19373
  if (!actions || actions.length === 0) return null;
19363
- return actions.map((action, index) => {
19374
+ return /* @__PURE__ */ jsx("div", { className: "mt-8 flex flex-wrap gap-3", children: actions.map((action, index) => {
19364
19375
  const { label, icon, iconAfter, children, className: actionClassName, ...pressableProps } = action;
19365
19376
  return /* @__PURE__ */ jsx(
19366
19377
  Pressable,
19367
19378
  {
19368
19379
  asButton: true,
19369
- className: cn("mt-8", actionClassName),
19380
+ className: actionClassName,
19370
19381
  ...pressableProps,
19371
19382
  children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
19372
19383
  icon,
@@ -19376,7 +19387,7 @@ function CarouselProductFeatureShowcase({
19376
19387
  },
19377
19388
  index
19378
19389
  );
19379
- });
19390
+ }) });
19380
19391
  };
19381
19392
  return /* @__PURE__ */ jsx(
19382
19393
  Section,
@@ -19421,9 +19432,9 @@ function CarouselProductFeatureShowcase({
19421
19432
  {
19422
19433
  onClick: goToPrev,
19423
19434
  asButton: true,
19424
- variant: "secondary",
19435
+ variant: "outline",
19425
19436
  size: "icon",
19426
- className: "rounded-full bg-background/80 backdrop-blur-sm",
19437
+ className: "flex h-10 w-10 items-center justify-center rounded-full border-border bg-background/90 text-foreground backdrop-blur-sm hover:bg-background",
19427
19438
  children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/chevron-left", size: 20 })
19428
19439
  }
19429
19440
  ),
@@ -19432,9 +19443,9 @@ function CarouselProductFeatureShowcase({
19432
19443
  {
19433
19444
  onClick: goToNext,
19434
19445
  asButton: true,
19435
- variant: "secondary",
19446
+ variant: "outline",
19436
19447
  size: "icon",
19437
- className: "rounded-full bg-background/80 backdrop-blur-sm",
19448
+ className: "flex h-10 w-10 items-center justify-center rounded-full border-border bg-background/90 text-foreground backdrop-blur-sm hover:bg-background",
19438
19449
  children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/chevron-right", size: 20 })
19439
19450
  }
19440
19451
  )
@@ -19520,13 +19531,13 @@ function SliderBtn({
19520
19531
  /* @__PURE__ */ jsx(
19521
19532
  "div",
19522
19533
  {
19523
- className: "absolute inset-0 -z-10 max-h-full max-w-full overflow-hidden",
19534
+ className: "absolute inset-0 -z-10 max-h-full max-w-full overflow-hidden rounded-lg",
19524
19535
  role: "progressbar",
19525
19536
  "aria-valuenow": active === value ? progress : 0,
19526
19537
  children: /* @__PURE__ */ jsx(
19527
19538
  "span",
19528
19539
  {
19529
- className: cn("absolute left-0", progressBarClass),
19540
+ className: cn("absolute left-0 rounded-b-lg", progressBarClass),
19530
19541
  style: {
19531
19542
  [vertical ? "height" : "width"]: active === value ? `${progress}%` : "0%"
19532
19543
  }
@@ -19557,7 +19568,7 @@ function CarouselProgressSlider({
19557
19568
  subheading,
19558
19569
  slides,
19559
19570
  slidesSlot,
19560
- duration = 5e3,
19571
+ duration = 8e3,
19561
19572
  fastDuration = 400,
19562
19573
  vertical = false,
19563
19574
  className,
@@ -19576,22 +19587,35 @@ function CarouselProgressSlider({
19576
19587
  const [active, setActive] = React52.useState(slides?.[0]?.id ?? "");
19577
19588
  const [progress, setProgress] = React52.useState(0);
19578
19589
  const [isFastForward, setIsFastForward] = React52.useState(false);
19590
+ const [isPaused, setIsPaused] = React52.useState(false);
19579
19591
  const frame = React52.useRef(0);
19580
19592
  const firstFrameTime = React52.useRef(performance.now());
19581
19593
  const targetValue = React52.useRef(null);
19594
+ const pausedProgress = React52.useRef(0);
19582
19595
  const sliderValues = React52.useMemo(
19583
19596
  () => slides?.map((slide) => slide.id),
19584
19597
  [slides]
19585
19598
  );
19586
19599
  React52.useEffect(() => {
19587
- if ((sliderValues?.length ?? 0) > 0) {
19600
+ if ((sliderValues?.length ?? 0) > 0 && !isPaused) {
19588
19601
  firstFrameTime.current = performance.now();
19602
+ if (pausedProgress.current > 0) {
19603
+ setProgress(pausedProgress.current);
19604
+ pausedProgress.current = 0;
19605
+ }
19589
19606
  frame.current = requestAnimationFrame(animate);
19590
19607
  }
19591
19608
  return () => {
19592
19609
  cancelAnimationFrame(frame.current);
19593
19610
  };
19594
- }, [sliderValues, active, isFastForward]);
19611
+ }, [sliderValues, active, isFastForward, isPaused]);
19612
+ const togglePause = () => {
19613
+ if (!isPaused) {
19614
+ pausedProgress.current = progress;
19615
+ cancelAnimationFrame(frame.current);
19616
+ }
19617
+ setIsPaused(!isPaused);
19618
+ };
19595
19619
  const animate = (now) => {
19596
19620
  const currentDuration = isFastForward ? fastDuration : duration;
19597
19621
  const elapsedTime = now - firstFrameTime.current;
@@ -19643,26 +19667,40 @@ function CarouselProgressSlider({
19643
19667
  pattern,
19644
19668
  patternOpacity,
19645
19669
  children: /* @__PURE__ */ jsx("div", { className: cn("relative", containerClassName), children: /* @__PURE__ */ jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2", contentClassName), children: [
19646
- /* @__PURE__ */ jsx("div", { className: cn("relative min-h-[300px]", imageClassName), children: slidesSlot ? slidesSlot : slides?.map((slide) => /* @__PURE__ */ jsx(
19647
- SliderWrapper,
19648
- {
19649
- value: slide.id,
19650
- className: cn("absolute inset-0", slide.className),
19651
- children: /* @__PURE__ */ jsx("div", { className: "aspect-video overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
19652
- Img,
19653
- {
19654
- src: slide.image,
19655
- alt: typeof slide.title === "string" ? slide.title : `Slide ${slide.id}`,
19656
- className: cn(
19657
- "h-full w-full object-cover",
19658
- slide.imageClassName
19659
- ),
19660
- optixFlowConfig
19661
- }
19662
- ) })
19663
- },
19664
- slide.id
19665
- )) }),
19670
+ /* @__PURE__ */ jsxs("div", { className: cn("relative", imageClassName), children: [
19671
+ slidesSlot ? slidesSlot : slides?.map((slide) => /* @__PURE__ */ jsx(
19672
+ SliderWrapper,
19673
+ {
19674
+ value: slide.id,
19675
+ className: cn("", slide.className),
19676
+ children: /* @__PURE__ */ jsx("div", { className: "aspect-video overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
19677
+ Img,
19678
+ {
19679
+ src: slide.image,
19680
+ alt: typeof slide.title === "string" ? slide.title : `Slide ${slide.id}`,
19681
+ className: cn(
19682
+ "h-full w-full object-cover",
19683
+ slide.imageClassName
19684
+ ),
19685
+ optixFlowConfig
19686
+ }
19687
+ ) })
19688
+ },
19689
+ slide.id
19690
+ )),
19691
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-center lg:justify-start", children: /* @__PURE__ */ jsx(
19692
+ Pressable,
19693
+ {
19694
+ onClick: togglePause,
19695
+ asButton: true,
19696
+ variant: "outline",
19697
+ size: "icon",
19698
+ className: "flex h-10 w-10 items-center justify-center rounded-full",
19699
+ "aria-label": isPaused ? "Play" : "Pause",
19700
+ children: /* @__PURE__ */ jsx(DynamicIcon, { name: isPaused ? "lucide/play" : "lucide/pause", size: 18 })
19701
+ }
19702
+ ) })
19703
+ ] }),
19666
19704
  /* @__PURE__ */ jsx(
19667
19705
  "div",
19668
19706
  {
@@ -19720,78 +19758,85 @@ function CarouselScrollingFeatureShowcase({
19720
19758
  const [activeFeature, setActiveFeature] = React52.useState(
19721
19759
  features?.[0]?.id ?? ""
19722
19760
  );
19723
- const containerRef = React52.useRef(null);
19724
- const { scrollYProgress } = useScroll({
19725
- target: containerRef,
19726
- offset: ["start start", "end end"]
19727
- });
19728
- const imageOpacity = useTransform(scrollYProgress, [0, 0.1], [0, 1]);
19761
+ const featureRefs = React52.useRef(/* @__PURE__ */ new Map());
19729
19762
  React52.useEffect(() => {
19730
- const observers = [];
19731
- features?.forEach((feature) => {
19732
- const element = document.getElementById(feature.id);
19733
- if (element) {
19734
- const observer = new IntersectionObserver(
19735
- (entries) => {
19736
- entries.forEach((entry) => {
19737
- if (entry.isIntersecting) {
19738
- setActiveFeature(feature.id);
19739
- }
19740
- });
19741
- },
19742
- { threshold: 0.5 }
19743
- );
19744
- observer.observe(element);
19745
- observers.push(observer);
19746
- }
19763
+ if (!features || features.length === 0) return;
19764
+ const observerOptions = {
19765
+ root: null,
19766
+ rootMargin: "-20% 0px -60% 0px",
19767
+ threshold: 0
19768
+ };
19769
+ const observer = new IntersectionObserver((entries) => {
19770
+ entries.forEach((entry) => {
19771
+ if (entry.isIntersecting) {
19772
+ const featureId = entry.target.getAttribute("data-feature-id");
19773
+ if (featureId) {
19774
+ setActiveFeature(featureId);
19775
+ }
19776
+ }
19777
+ });
19778
+ }, observerOptions);
19779
+ featureRefs.current.forEach((element) => {
19780
+ observer.observe(element);
19747
19781
  });
19748
19782
  return () => {
19749
- observers.forEach((observer) => observer.disconnect());
19783
+ observer.disconnect();
19750
19784
  };
19751
19785
  }, [features]);
19752
19786
  const activeFeatureData = features?.find((f) => f.id === activeFeature);
19787
+ const setFeatureRef = (id) => (el) => {
19788
+ if (el) {
19789
+ featureRefs.current.set(id, el);
19790
+ } else {
19791
+ featureRefs.current.delete(id);
19792
+ }
19793
+ };
19753
19794
  return /* @__PURE__ */ jsx(
19754
19795
  Section,
19755
19796
  {
19756
- ref: containerRef,
19757
19797
  background,
19758
19798
  spacing,
19759
19799
  className: cn(className),
19760
19800
  pattern,
19761
19801
  patternOpacity,
19762
19802
  children: /* @__PURE__ */ jsxs("div", { className: cn("container mx-auto px-4", containerClassName), children: [
19763
- /* @__PURE__ */ jsxs("div", { className: cn("py-16 text-center", headerClassName), children: [
19803
+ /* @__PURE__ */ jsxs("div", { className: cn("mb-12 text-center", headerClassName), children: [
19764
19804
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsx("h2", { className: cn("text-3xl font-bold tracking-tight md:text-4xl", headingClassName), children: heading }) : /* @__PURE__ */ jsx("div", { className: headingClassName, children: heading })),
19765
19805
  subheading && (typeof subheading === "string" ? /* @__PURE__ */ jsx("p", { className: cn("mt-4 text-lg text-muted-foreground", subheadingClassName), children: subheading }) : /* @__PURE__ */ jsx("div", { className: cn("mt-4", subheadingClassName), children: subheading }))
19766
19806
  ] }),
19767
- /* @__PURE__ */ jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2", contentClassName), children: [
19768
- /* @__PURE__ */ jsx("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsx("div", { className: "sticky top-24", children: /* @__PURE__ */ jsx(
19807
+ /* @__PURE__ */ jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2 lg:gap-12", contentClassName), children: [
19808
+ /* @__PURE__ */ jsx("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsx("div", { className: "sticky top-24", children: /* @__PURE__ */ jsx("div", { className: cn("aspect-video overflow-hidden rounded-xl bg-muted", imageClassName), children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: activeFeatureData && /* @__PURE__ */ jsx(
19769
19809
  motion.div,
19770
19810
  {
19771
- style: { opacity: imageOpacity },
19772
- className: cn("aspect-video overflow-hidden rounded-xl", imageClassName),
19773
- children: activeFeatureData && /* @__PURE__ */ jsx(
19811
+ initial: { opacity: 0 },
19812
+ animate: { opacity: 1 },
19813
+ exit: { opacity: 0 },
19814
+ transition: { duration: 0.3 },
19815
+ className: "h-full w-full",
19816
+ children: /* @__PURE__ */ jsx(
19774
19817
  Img,
19775
19818
  {
19776
19819
  src: activeFeatureData.image,
19777
19820
  alt: typeof activeFeatureData.title === "string" ? activeFeatureData.title : `Feature ${activeFeatureData.id}`,
19778
- className: cn("h-full w-full object-cover transition-all duration-500", activeFeatureData.imageClassName),
19821
+ className: cn("h-full w-full object-cover", activeFeatureData.imageClassName),
19779
19822
  optixFlowConfig
19780
19823
  }
19781
19824
  )
19782
- }
19783
- ) }) }),
19784
- /* @__PURE__ */ jsx("div", { className: cn("space-y-32 py-16", featuresClassName), children: featuresSlot ? featuresSlot : features?.map((feature, index) => /* @__PURE__ */ jsxs(
19825
+ },
19826
+ activeFeatureData.id
19827
+ ) }) }) }) }),
19828
+ /* @__PURE__ */ jsx("div", { className: cn("space-y-24 lg:space-y-32", featuresClassName), children: featuresSlot ? featuresSlot : features?.map((feature, index) => /* @__PURE__ */ jsxs(
19785
19829
  "div",
19786
19830
  {
19787
- id: feature.id,
19831
+ ref: setFeatureRef(feature.id),
19832
+ "data-feature-id": feature.id,
19788
19833
  className: cn(
19789
- "min-h-[50vh] transition-opacity duration-300",
19834
+ "scroll-mt-24 transition-opacity duration-300",
19790
19835
  activeFeature === feature.id ? "opacity-100" : "opacity-50",
19791
19836
  feature.className
19792
19837
  ),
19793
19838
  children: [
19794
- /* @__PURE__ */ jsx("div", { className: "mb-6 lg:hidden", children: /* @__PURE__ */ jsx("div", { className: "aspect-video overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
19839
+ /* @__PURE__ */ jsx("div", { className: "mb-6 lg:hidden", children: /* @__PURE__ */ jsx("div", { className: "aspect-video overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsx(
19795
19840
  Img,
19796
19841
  {
19797
19842
  src: feature.image,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensite/ui",
3
- "version": "0.7.7",
3
+ "version": "0.7.8",
4
4
  "description": "Foundational UI component library for OpenSite Semantic Site Builder with tree-shakable exports and abstract styling",
5
5
  "keywords": [
6
6
  "react",