@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.
@@ -430,78 +430,85 @@ function CarouselScrollingFeatureShowcase({
430
430
  const [activeFeature, setActiveFeature] = React3__namespace.useState(
431
431
  features?.[0]?.id ?? ""
432
432
  );
433
- const containerRef = React3__namespace.useRef(null);
434
- const { scrollYProgress } = framerMotion.useScroll({
435
- target: containerRef,
436
- offset: ["start start", "end end"]
437
- });
438
- const imageOpacity = framerMotion.useTransform(scrollYProgress, [0, 0.1], [0, 1]);
433
+ const featureRefs = React3__namespace.useRef(/* @__PURE__ */ new Map());
439
434
  React3__namespace.useEffect(() => {
440
- const observers = [];
441
- features?.forEach((feature) => {
442
- const element = document.getElementById(feature.id);
443
- if (element) {
444
- const observer = new IntersectionObserver(
445
- (entries) => {
446
- entries.forEach((entry) => {
447
- if (entry.isIntersecting) {
448
- setActiveFeature(feature.id);
449
- }
450
- });
451
- },
452
- { threshold: 0.5 }
453
- );
454
- observer.observe(element);
455
- observers.push(observer);
456
- }
435
+ if (!features || features.length === 0) return;
436
+ const observerOptions = {
437
+ root: null,
438
+ rootMargin: "-20% 0px -60% 0px",
439
+ threshold: 0
440
+ };
441
+ const observer = new IntersectionObserver((entries) => {
442
+ entries.forEach((entry) => {
443
+ if (entry.isIntersecting) {
444
+ const featureId = entry.target.getAttribute("data-feature-id");
445
+ if (featureId) {
446
+ setActiveFeature(featureId);
447
+ }
448
+ }
449
+ });
450
+ }, observerOptions);
451
+ featureRefs.current.forEach((element) => {
452
+ observer.observe(element);
457
453
  });
458
454
  return () => {
459
- observers.forEach((observer) => observer.disconnect());
455
+ observer.disconnect();
460
456
  };
461
457
  }, [features]);
462
458
  const activeFeatureData = features?.find((f) => f.id === activeFeature);
459
+ const setFeatureRef = (id) => (el) => {
460
+ if (el) {
461
+ featureRefs.current.set(id, el);
462
+ } else {
463
+ featureRefs.current.delete(id);
464
+ }
465
+ };
463
466
  return /* @__PURE__ */ jsxRuntime.jsx(
464
467
  Section,
465
468
  {
466
- ref: containerRef,
467
469
  background,
468
470
  spacing,
469
471
  className: cn(className),
470
472
  pattern,
471
473
  patternOpacity,
472
474
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("container mx-auto px-4", containerClassName), children: [
473
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("py-16 text-center", headerClassName), children: [
475
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mb-12 text-center", headerClassName), children: [
474
476
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: cn("text-3xl font-bold tracking-tight md:text-4xl", headingClassName), children: heading }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
475
477
  subheading && (typeof subheading === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-4 text-lg text-muted-foreground", subheadingClassName), children: subheading }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-4", subheadingClassName), children: subheading }))
476
478
  ] }),
477
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2", contentClassName), children: [
478
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-24", children: /* @__PURE__ */ jsxRuntime.jsx(
479
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2 lg:gap-12", contentClassName), children: [
480
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-24", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("aspect-video overflow-hidden rounded-xl bg-muted", imageClassName), children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: activeFeatureData && /* @__PURE__ */ jsxRuntime.jsx(
479
481
  framerMotion.motion.div,
480
482
  {
481
- style: { opacity: imageOpacity },
482
- className: cn("aspect-video overflow-hidden rounded-xl", imageClassName),
483
- children: activeFeatureData && /* @__PURE__ */ jsxRuntime.jsx(
483
+ initial: { opacity: 0 },
484
+ animate: { opacity: 1 },
485
+ exit: { opacity: 0 },
486
+ transition: { duration: 0.3 },
487
+ className: "h-full w-full",
488
+ children: /* @__PURE__ */ jsxRuntime.jsx(
484
489
  img.Img,
485
490
  {
486
491
  src: activeFeatureData.image,
487
492
  alt: typeof activeFeatureData.title === "string" ? activeFeatureData.title : `Feature ${activeFeatureData.id}`,
488
- className: cn("h-full w-full object-cover transition-all duration-500", activeFeatureData.imageClassName),
493
+ className: cn("h-full w-full object-cover", activeFeatureData.imageClassName),
489
494
  optixFlowConfig
490
495
  }
491
496
  )
492
- }
493
- ) }) }),
494
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-32 py-16", featuresClassName), children: featuresSlot ? featuresSlot : features?.map((feature, index) => /* @__PURE__ */ jsxRuntime.jsxs(
497
+ },
498
+ activeFeatureData.id
499
+ ) }) }) }) }),
500
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-24 lg:space-y-32", featuresClassName), children: featuresSlot ? featuresSlot : features?.map((feature, index) => /* @__PURE__ */ jsxRuntime.jsxs(
495
501
  "div",
496
502
  {
497
- id: feature.id,
503
+ ref: setFeatureRef(feature.id),
504
+ "data-feature-id": feature.id,
498
505
  className: cn(
499
- "min-h-[50vh] transition-opacity duration-300",
506
+ "scroll-mt-24 transition-opacity duration-300",
500
507
  activeFeature === feature.id ? "opacity-100" : "opacity-50",
501
508
  feature.className
502
509
  ),
503
510
  children: [
504
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6 lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-video overflow-hidden rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
511
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6 lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-video overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(
505
512
  img.Img,
506
513
  {
507
514
  src: feature.image,
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import * as React3 from 'react';
3
3
  import React3__default from 'react';
4
- import { useScroll, useTransform, motion } from 'framer-motion';
4
+ import { AnimatePresence, motion } from 'framer-motion';
5
5
  import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import { Img } from '@page-speed/img';
@@ -409,78 +409,85 @@ function CarouselScrollingFeatureShowcase({
409
409
  const [activeFeature, setActiveFeature] = React3.useState(
410
410
  features?.[0]?.id ?? ""
411
411
  );
412
- const containerRef = React3.useRef(null);
413
- const { scrollYProgress } = useScroll({
414
- target: containerRef,
415
- offset: ["start start", "end end"]
416
- });
417
- const imageOpacity = useTransform(scrollYProgress, [0, 0.1], [0, 1]);
412
+ const featureRefs = React3.useRef(/* @__PURE__ */ new Map());
418
413
  React3.useEffect(() => {
419
- const observers = [];
420
- features?.forEach((feature) => {
421
- const element = document.getElementById(feature.id);
422
- if (element) {
423
- const observer = new IntersectionObserver(
424
- (entries) => {
425
- entries.forEach((entry) => {
426
- if (entry.isIntersecting) {
427
- setActiveFeature(feature.id);
428
- }
429
- });
430
- },
431
- { threshold: 0.5 }
432
- );
433
- observer.observe(element);
434
- observers.push(observer);
435
- }
414
+ if (!features || features.length === 0) return;
415
+ const observerOptions = {
416
+ root: null,
417
+ rootMargin: "-20% 0px -60% 0px",
418
+ threshold: 0
419
+ };
420
+ const observer = new IntersectionObserver((entries) => {
421
+ entries.forEach((entry) => {
422
+ if (entry.isIntersecting) {
423
+ const featureId = entry.target.getAttribute("data-feature-id");
424
+ if (featureId) {
425
+ setActiveFeature(featureId);
426
+ }
427
+ }
428
+ });
429
+ }, observerOptions);
430
+ featureRefs.current.forEach((element) => {
431
+ observer.observe(element);
436
432
  });
437
433
  return () => {
438
- observers.forEach((observer) => observer.disconnect());
434
+ observer.disconnect();
439
435
  };
440
436
  }, [features]);
441
437
  const activeFeatureData = features?.find((f) => f.id === activeFeature);
438
+ const setFeatureRef = (id) => (el) => {
439
+ if (el) {
440
+ featureRefs.current.set(id, el);
441
+ } else {
442
+ featureRefs.current.delete(id);
443
+ }
444
+ };
442
445
  return /* @__PURE__ */ jsx(
443
446
  Section,
444
447
  {
445
- ref: containerRef,
446
448
  background,
447
449
  spacing,
448
450
  className: cn(className),
449
451
  pattern,
450
452
  patternOpacity,
451
453
  children: /* @__PURE__ */ jsxs("div", { className: cn("container mx-auto px-4", containerClassName), children: [
452
- /* @__PURE__ */ jsxs("div", { className: cn("py-16 text-center", headerClassName), children: [
454
+ /* @__PURE__ */ jsxs("div", { className: cn("mb-12 text-center", headerClassName), children: [
453
455
  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 })),
454
456
  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 }))
455
457
  ] }),
456
- /* @__PURE__ */ jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2", contentClassName), children: [
457
- /* @__PURE__ */ jsx("div", { className: "hidden lg:block", children: /* @__PURE__ */ jsx("div", { className: "sticky top-24", children: /* @__PURE__ */ jsx(
458
+ /* @__PURE__ */ jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2 lg:gap-12", contentClassName), children: [
459
+ /* @__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(
458
460
  motion.div,
459
461
  {
460
- style: { opacity: imageOpacity },
461
- className: cn("aspect-video overflow-hidden rounded-xl", imageClassName),
462
- children: activeFeatureData && /* @__PURE__ */ jsx(
462
+ initial: { opacity: 0 },
463
+ animate: { opacity: 1 },
464
+ exit: { opacity: 0 },
465
+ transition: { duration: 0.3 },
466
+ className: "h-full w-full",
467
+ children: /* @__PURE__ */ jsx(
463
468
  Img,
464
469
  {
465
470
  src: activeFeatureData.image,
466
471
  alt: typeof activeFeatureData.title === "string" ? activeFeatureData.title : `Feature ${activeFeatureData.id}`,
467
- className: cn("h-full w-full object-cover transition-all duration-500", activeFeatureData.imageClassName),
472
+ className: cn("h-full w-full object-cover", activeFeatureData.imageClassName),
468
473
  optixFlowConfig
469
474
  }
470
475
  )
471
- }
472
- ) }) }),
473
- /* @__PURE__ */ jsx("div", { className: cn("space-y-32 py-16", featuresClassName), children: featuresSlot ? featuresSlot : features?.map((feature, index) => /* @__PURE__ */ jsxs(
476
+ },
477
+ activeFeatureData.id
478
+ ) }) }) }) }),
479
+ /* @__PURE__ */ jsx("div", { className: cn("space-y-24 lg:space-y-32", featuresClassName), children: featuresSlot ? featuresSlot : features?.map((feature, index) => /* @__PURE__ */ jsxs(
474
480
  "div",
475
481
  {
476
- id: feature.id,
482
+ ref: setFeatureRef(feature.id),
483
+ "data-feature-id": feature.id,
477
484
  className: cn(
478
- "min-h-[50vh] transition-opacity duration-300",
485
+ "scroll-mt-24 transition-opacity duration-300",
479
486
  activeFeature === feature.id ? "opacity-100" : "opacity-50",
480
487
  feature.className
481
488
  ),
482
489
  children: [
483
- /* @__PURE__ */ jsx("div", { className: "mb-6 lg:hidden", children: /* @__PURE__ */ jsx("div", { className: "aspect-video overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
490
+ /* @__PURE__ */ jsx("div", { className: "mb-6 lg:hidden", children: /* @__PURE__ */ jsx("div", { className: "aspect-video overflow-hidden rounded-lg bg-muted", children: /* @__PURE__ */ jsx(
484
491
  Img,
485
492
  {
486
493
  src: feature.image,