@opensite/ui 1.2.4 → 1.2.6

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.
@@ -1,12 +1,13 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React4 = require('react');
4
+ var React6 = require('react');
5
5
  var framerMotion = require('framer-motion');
6
6
  var clsx = require('clsx');
7
7
  var tailwindMerge = require('tailwind-merge');
8
8
  var img = require('@page-speed/img');
9
9
  var jsxRuntime = require('react/jsx-runtime');
10
+ var classVarianceAuthority = require('class-variance-authority');
10
11
 
11
12
  function _interopNamespace(e) {
12
13
  if (e && e.__esModule) return e;
@@ -26,42 +27,12 @@ function _interopNamespace(e) {
26
27
  return Object.freeze(n);
27
28
  }
28
29
 
29
- var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
30
+ var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
30
31
 
31
32
  // components/blocks/features/feature-animated-carousel.tsx
32
33
  function cn(...inputs) {
33
34
  return tailwindMerge.twMerge(clsx.clsx(inputs));
34
35
  }
35
- function getNestedCardBg(parentBg, variant = "muted", options) {
36
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
37
- if (isDark) {
38
- switch (variant) {
39
- case "muted":
40
- return "bg-background";
41
- case "card":
42
- return "bg-card";
43
- case "accent":
44
- return "bg-accent";
45
- case "subtle":
46
- return "bg-background/50";
47
- }
48
- } else {
49
- switch (variant) {
50
- case "muted":
51
- return "bg-muted";
52
- case "card":
53
- return "bg-card";
54
- case "accent":
55
- return "bg-accent";
56
- case "subtle":
57
- return "bg-muted/50";
58
- }
59
- }
60
- }
61
- function getNestedCardTextColor(parentBg, options) {
62
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
63
- return isDark ? "text-foreground" : "";
64
- }
65
36
  var svgCache = /* @__PURE__ */ new Map();
66
37
  function DynamicIcon({
67
38
  name,
@@ -70,10 +41,10 @@ function DynamicIcon({
70
41
  className,
71
42
  alt
72
43
  }) {
73
- const [svgContent, setSvgContent] = React4__namespace.useState(null);
74
- const [isLoading, setIsLoading] = React4__namespace.useState(true);
75
- const [error, setError] = React4__namespace.useState(null);
76
- const { url, iconName } = React4__namespace.useMemo(() => {
44
+ const [svgContent, setSvgContent] = React6__namespace.useState(null);
45
+ const [isLoading, setIsLoading] = React6__namespace.useState(true);
46
+ const [error, setError] = React6__namespace.useState(null);
47
+ const { url, iconName } = React6__namespace.useMemo(() => {
77
48
  const separator = name.includes("/") ? "/" : ":";
78
49
  const [prefix, iconName2] = name.split(separator);
79
50
  const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}`;
@@ -82,7 +53,7 @@ function DynamicIcon({
82
53
  iconName: iconName2
83
54
  };
84
55
  }, [name, size]);
85
- React4__namespace.useEffect(() => {
56
+ React6__namespace.useEffect(() => {
86
57
  let isMounted = true;
87
58
  const fetchSvg = async () => {
88
59
  const cached = svgCache.get(url);
@@ -176,7 +147,7 @@ var maxWidthStyles = {
176
147
  "4xl": "max-w-[1536px]",
177
148
  full: "max-w-full"
178
149
  };
179
- var Container = React4__namespace.default.forwardRef(
150
+ var Container = React6__namespace.default.forwardRef(
180
151
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
181
152
  const Component = as;
182
153
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -481,7 +452,7 @@ var spacingStyles = {
481
452
  };
482
453
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl"];
483
454
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
484
- var Section = React4__namespace.default.forwardRef(
455
+ var Section = React6__namespace.default.forwardRef(
485
456
  ({
486
457
  id,
487
458
  title,
@@ -542,271 +513,728 @@ var Section = React4__namespace.default.forwardRef(
542
513
  }
543
514
  );
544
515
  Section.displayName = "Section";
545
- var Controls = React4__namespace.memo(({
546
- handleNext,
547
- handlePrevious,
548
- isPreviousDisabled,
549
- isNextDisabled
550
- }) => {
551
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden flex-col items-start gap-8 lg:flex", children: [
552
- /* @__PURE__ */ jsxRuntime.jsx(
553
- "button",
554
- {
555
- className: "rounded-full border bg-background/50 p-2 hover:bg-background disabled:opacity-50",
556
- onClick: handlePrevious,
557
- disabled: isPreviousDisabled,
558
- type: "button",
559
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-up", size: 24 })
516
+ var baseStyles = [
517
+ // Layout
518
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
519
+ // Typography - using CSS variables with sensible defaults
520
+ "font-[var(--button-font-family,inherit)]",
521
+ "font-[var(--button-font-weight,500)]",
522
+ "tracking-[var(--button-letter-spacing,0)]",
523
+ "leading-[var(--button-line-height,1.25)]",
524
+ "[text-transform:var(--button-text-transform,none)]",
525
+ "text-sm",
526
+ // Border radius
527
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
528
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
529
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
530
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
531
+ "[box-shadow:var(--button-shadow,none)]",
532
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
533
+ // Disabled state
534
+ "disabled:pointer-events-none disabled:opacity-50",
535
+ // SVG handling
536
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
537
+ // Focus styles
538
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
539
+ // Invalid state
540
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
541
+ ].join(" ");
542
+ var buttonVariants = classVarianceAuthority.cva(baseStyles, {
543
+ variants: {
544
+ variant: {
545
+ // Default (Primary) variant - full customization
546
+ default: [
547
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
548
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
549
+ "border-[length:var(--button-default-border-width,0px)]",
550
+ "border-[color:var(--button-default-border,transparent)]",
551
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
552
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
553
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
554
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
555
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
556
+ ].join(" "),
557
+ // Destructive variant - full customization
558
+ destructive: [
559
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
560
+ "text-[var(--button-destructive-fg,white)]",
561
+ "border-[length:var(--button-destructive-border-width,0px)]",
562
+ "border-[color:var(--button-destructive-border,transparent)]",
563
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
564
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
565
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
566
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
567
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
568
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
569
+ "dark:bg-destructive/60"
570
+ ].join(" "),
571
+ // Outline variant - full customization with proper border handling
572
+ outline: [
573
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
574
+ "text-[var(--button-outline-fg,inherit)]",
575
+ "border-[length:var(--button-outline-border-width,1px)]",
576
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
577
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
578
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
579
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
580
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
581
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
582
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
583
+ ].join(" "),
584
+ // Secondary variant - full customization
585
+ secondary: [
586
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
587
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
588
+ "border-[length:var(--button-secondary-border-width,0px)]",
589
+ "border-[color:var(--button-secondary-border,transparent)]",
590
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
591
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
592
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
593
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
594
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
595
+ ].join(" "),
596
+ // Ghost variant - full customization
597
+ ghost: [
598
+ "bg-[var(--button-ghost-bg,transparent)]",
599
+ "text-[var(--button-ghost-fg,inherit)]",
600
+ "border-[length:var(--button-ghost-border-width,0px)]",
601
+ "border-[color:var(--button-ghost-border,transparent)]",
602
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
603
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
604
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
605
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
606
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
607
+ "dark:hover:bg-accent/50"
608
+ ].join(" "),
609
+ // Link variant - full customization
610
+ link: [
611
+ "bg-[var(--button-link-bg,transparent)]",
612
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
613
+ "border-[length:var(--button-link-border-width,0px)]",
614
+ "border-[color:var(--button-link-border,transparent)]",
615
+ "[box-shadow:var(--button-link-shadow,none)]",
616
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
617
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
618
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
619
+ "underline-offset-4 hover:underline"
620
+ ].join(" ")
621
+ },
622
+ size: {
623
+ default: [
624
+ "h-[var(--button-height-md,2.25rem)]",
625
+ "px-[var(--button-padding-x-md,1rem)]",
626
+ "py-[var(--button-padding-y-md,0.5rem)]",
627
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
628
+ ].join(" "),
629
+ sm: [
630
+ "h-[var(--button-height-sm,2rem)]",
631
+ "px-[var(--button-padding-x-sm,0.75rem)]",
632
+ "py-[var(--button-padding-y-sm,0.25rem)]",
633
+ "gap-1.5",
634
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
635
+ ].join(" "),
636
+ md: [
637
+ "h-[var(--button-height-md,2.25rem)]",
638
+ "px-[var(--button-padding-x-md,1rem)]",
639
+ "py-[var(--button-padding-y-md,0.5rem)]",
640
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
641
+ ].join(" "),
642
+ lg: [
643
+ "h-[var(--button-height-lg,2.5rem)]",
644
+ "px-[var(--button-padding-x-lg,1.5rem)]",
645
+ "py-[var(--button-padding-y-lg,0.5rem)]",
646
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
647
+ ].join(" "),
648
+ icon: "size-[var(--button-height-md,2.25rem)]",
649
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
650
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
651
+ }
652
+ },
653
+ defaultVariants: {
654
+ variant: "default",
655
+ size: "default"
656
+ }
657
+ });
658
+ function normalizePhoneNumber(input) {
659
+ const trimmed = input.trim();
660
+ if (trimmed.toLowerCase().startsWith("tel:")) {
661
+ return trimmed;
662
+ }
663
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
664
+ if (match) {
665
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
666
+ const extension = match[3];
667
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
668
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
669
+ return `tel:${withExtension}`;
670
+ }
671
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
672
+ return `tel:${cleaned}`;
673
+ }
674
+ function normalizeEmail(input) {
675
+ const trimmed = input.trim();
676
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
677
+ return trimmed;
678
+ }
679
+ return `mailto:${trimmed}`;
680
+ }
681
+ function isEmail(input) {
682
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
683
+ return emailRegex.test(input.trim());
684
+ }
685
+ function isPhoneNumber(input) {
686
+ const trimmed = input.trim();
687
+ if (trimmed.toLowerCase().startsWith("tel:")) {
688
+ return true;
689
+ }
690
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
691
+ return phoneRegex.test(trimmed);
692
+ }
693
+ function isInternalUrl(href) {
694
+ if (typeof window === "undefined") {
695
+ return href.startsWith("/") && !href.startsWith("//");
696
+ }
697
+ const trimmed = href.trim();
698
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
699
+ return true;
700
+ }
701
+ try {
702
+ const url = new URL(trimmed, window.location.href);
703
+ const currentOrigin = window.location.origin;
704
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
705
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
706
+ } catch {
707
+ return false;
708
+ }
709
+ }
710
+ function toRelativePath(href) {
711
+ if (typeof window === "undefined") {
712
+ return href;
713
+ }
714
+ const trimmed = href.trim();
715
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
716
+ return trimmed;
717
+ }
718
+ try {
719
+ const url = new URL(trimmed, window.location.href);
720
+ const currentOrigin = window.location.origin;
721
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
722
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
723
+ return url.pathname + url.search + url.hash;
724
+ }
725
+ } catch {
726
+ }
727
+ return trimmed;
728
+ }
729
+ function useNavigation({
730
+ href,
731
+ onClick
732
+ } = {}) {
733
+ const linkType = React6__namespace.useMemo(() => {
734
+ if (!href || href.trim() === "") {
735
+ return onClick ? "none" : "none";
736
+ }
737
+ const trimmed = href.trim();
738
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
739
+ return "mailto";
740
+ }
741
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
742
+ return "tel";
743
+ }
744
+ if (isInternalUrl(trimmed)) {
745
+ return "internal";
746
+ }
747
+ try {
748
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
749
+ return "external";
750
+ } catch {
751
+ return "internal";
752
+ }
753
+ }, [href, onClick]);
754
+ const normalizedHref = React6__namespace.useMemo(() => {
755
+ if (!href || href.trim() === "") {
756
+ return void 0;
757
+ }
758
+ const trimmed = href.trim();
759
+ switch (linkType) {
760
+ case "tel":
761
+ return normalizePhoneNumber(trimmed);
762
+ case "mailto":
763
+ return normalizeEmail(trimmed);
764
+ case "internal":
765
+ return toRelativePath(trimmed);
766
+ case "external":
767
+ return trimmed;
768
+ default:
769
+ return trimmed;
770
+ }
771
+ }, [href, linkType]);
772
+ const target = React6__namespace.useMemo(() => {
773
+ switch (linkType) {
774
+ case "external":
775
+ return "_blank";
776
+ case "internal":
777
+ return "_self";
778
+ case "mailto":
779
+ case "tel":
780
+ return void 0;
781
+ default:
782
+ return void 0;
783
+ }
784
+ }, [linkType]);
785
+ const rel = React6__namespace.useMemo(() => {
786
+ if (linkType === "external") {
787
+ return "noopener noreferrer";
788
+ }
789
+ return void 0;
790
+ }, [linkType]);
791
+ const isExternal = linkType === "external";
792
+ const isInternal = linkType === "internal";
793
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
794
+ const handleClick = React6__namespace.useCallback(
795
+ (event) => {
796
+ if (onClick) {
797
+ try {
798
+ onClick(event);
799
+ } catch (error) {
800
+ console.error("Error in user onClick handler:", error);
801
+ }
560
802
  }
561
- ),
562
- /* @__PURE__ */ jsxRuntime.jsx(
563
- "button",
564
- {
565
- className: "rounded-full border bg-background/50 p-2 hover:bg-background disabled:opacity-50",
566
- onClick: handleNext,
567
- disabled: isNextDisabled,
568
- type: "button",
569
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-down", size: 24 })
803
+ if (event.defaultPrevented) {
804
+ return;
805
+ }
806
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
807
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
808
+ if (typeof window !== "undefined") {
809
+ const handler = window.__opensiteNavigationHandler;
810
+ if (typeof handler === "function") {
811
+ try {
812
+ const handled = handler(normalizedHref, event.nativeEvent || event);
813
+ if (handled !== false) {
814
+ event.preventDefault();
815
+ }
816
+ } catch (error) {
817
+ console.error("Error in navigation handler:", error);
818
+ }
819
+ }
820
+ }
570
821
  }
571
- )
572
- ] });
573
- });
574
- var FeatureCard = React4__namespace.memo(({ feature, isActive, onClick }) => {
575
- const variants = React4.useMemo(() => ({
576
- initial: {
577
- opacity: 0
578
- },
579
- animate: {
580
- opacity: 1
581
822
  },
582
- exit: {
583
- opacity: 0
823
+ [onClick, shouldUseRouter, normalizedHref]
824
+ );
825
+ return {
826
+ linkType,
827
+ normalizedHref,
828
+ target,
829
+ rel,
830
+ isExternal,
831
+ isInternal,
832
+ shouldUseRouter,
833
+ handleClick
834
+ };
835
+ }
836
+ var Pressable = React6__namespace.forwardRef(
837
+ ({
838
+ children,
839
+ className,
840
+ href,
841
+ onClick,
842
+ variant,
843
+ size,
844
+ asButton = false,
845
+ fallbackComponentType = "span",
846
+ componentType,
847
+ "aria-label": ariaLabel,
848
+ "aria-describedby": ariaDescribedby,
849
+ id,
850
+ ...props
851
+ }, ref) => {
852
+ const navigation = useNavigation({ href, onClick });
853
+ const {
854
+ normalizedHref,
855
+ target,
856
+ rel,
857
+ linkType,
858
+ isInternal,
859
+ handleClick
860
+ } = navigation;
861
+ const shouldRenderLink = normalizedHref && linkType !== "none";
862
+ const shouldRenderButton = !shouldRenderLink && onClick;
863
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
864
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
865
+ const shouldApplyButtonStyles = asButton || variant || size;
866
+ const combinedClassName = cn(
867
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
868
+ className
869
+ );
870
+ const dataProps = Object.fromEntries(
871
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
872
+ );
873
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
874
+ "data-slot": "button",
875
+ "data-variant": variant ?? "default",
876
+ "data-size": size ?? "default"
877
+ } : {};
878
+ const commonProps = {
879
+ className: combinedClassName,
880
+ onClick: handleClick,
881
+ "aria-label": ariaLabel,
882
+ "aria-describedby": ariaDescribedby,
883
+ id,
884
+ ...dataProps,
885
+ ...buttonDataAttributes
886
+ };
887
+ if (finalComponentType === "a" && shouldRenderLink) {
888
+ return /* @__PURE__ */ jsxRuntime.jsx(
889
+ "a",
890
+ {
891
+ ref,
892
+ href: normalizedHref,
893
+ target,
894
+ rel,
895
+ ...commonProps,
896
+ ...props,
897
+ children
898
+ }
899
+ );
584
900
  }
585
- }), []);
586
- return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "popLayout", children: /* @__PURE__ */ jsxRuntime.jsx(
587
- framerMotion.motion.div,
588
- {
589
- layout: true,
590
- transition: {
591
- layout: {
592
- duration: 0.4,
593
- ease: "easeOut"
901
+ if (finalComponentType === "button") {
902
+ return /* @__PURE__ */ jsxRuntime.jsx(
903
+ "button",
904
+ {
905
+ ref,
906
+ type: props.type || "button",
907
+ ...commonProps,
908
+ ...props,
909
+ children
594
910
  }
595
- },
596
- style: {
597
- borderRadius: "24px"
598
- },
599
- className: "flex cursor-pointer items-start gap-4 overflow-hidden bg-background md:w-fit md:max-w-sm",
600
- onClick,
601
- children: isActive ? /* @__PURE__ */ jsxRuntime.jsx(
602
- framerMotion.motion.div,
911
+ );
912
+ }
913
+ if (finalComponentType === "div") {
914
+ return /* @__PURE__ */ jsxRuntime.jsx(
915
+ "div",
603
916
  {
604
- layout: true,
605
- variants,
606
- initial: "initial",
607
- animate: "animate",
608
- exit: "exit",
609
- transition: {
917
+ ref,
918
+ ...commonProps,
919
+ children
920
+ }
921
+ );
922
+ }
923
+ return /* @__PURE__ */ jsxRuntime.jsx(
924
+ "span",
925
+ {
926
+ ref,
927
+ ...commonProps,
928
+ children
929
+ }
930
+ );
931
+ }
932
+ );
933
+ Pressable.displayName = "Pressable";
934
+ var Controls = React6__namespace.memo(
935
+ ({
936
+ handleNext,
937
+ handlePrevious,
938
+ isPreviousDisabled,
939
+ isNextDisabled
940
+ }) => {
941
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden flex-col items-start gap-8 lg:flex", children: [
942
+ /* @__PURE__ */ jsxRuntime.jsx(
943
+ "button",
944
+ {
945
+ className: "rounded-full border p-2 flex items-center justify-center disabled:opacity-50 h-fit w-fit bg-card text-card-foreground",
946
+ onClick: handlePrevious,
947
+ disabled: isPreviousDisabled,
948
+ type: "button",
949
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-up", size: 24 })
950
+ }
951
+ ),
952
+ /* @__PURE__ */ jsxRuntime.jsx(
953
+ "button",
954
+ {
955
+ className: "rounded-full border p-2 flex items-center justify-center disabled:opacity-50 h-fit w-fit bg-card text-card-foreground",
956
+ onClick: handleNext,
957
+ disabled: isNextDisabled,
958
+ type: "button",
959
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-down", size: 24 })
960
+ }
961
+ )
962
+ ] });
963
+ }
964
+ );
965
+ var FeatureCard = React6__namespace.memo(
966
+ ({ feature, isActive, onClick }) => {
967
+ const variants = React6.useMemo(
968
+ () => ({
969
+ initial: {
970
+ opacity: 0
971
+ },
972
+ animate: {
973
+ opacity: 1
974
+ },
975
+ exit: {
976
+ opacity: 0
977
+ }
978
+ }),
979
+ []
980
+ );
981
+ return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "popLayout", children: /* @__PURE__ */ jsxRuntime.jsxs(
982
+ framerMotion.motion.div,
983
+ {
984
+ layout: true,
985
+ transition: {
986
+ layout: {
610
987
  duration: 0.4,
611
- delay: 0.3,
612
988
  ease: "easeOut"
989
+ }
990
+ },
991
+ style: {
992
+ borderRadius: "24px"
993
+ },
994
+ className: cn(
995
+ "relative flex items-start gap-4 bg-background text-foreground md:w-fit md:max-w-sm",
996
+ isActive ? "shadow-xl overflow-visible" : "cursor-pointer shadow-none hover:shadow-xl transition-shadow duration-500 overflow-hidden"
997
+ ),
998
+ onClick,
999
+ children: [
1000
+ isActive && feature.href && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 translate-x-1/2 bg-background rounded-full h-fit w-fit p-2 flex items-center justify-center z-10", children: /* @__PURE__ */ jsxRuntime.jsx(
1001
+ Pressable,
1002
+ {
1003
+ href: feature.href,
1004
+ size: "icon-lg",
1005
+ className: "bg-primary text-primary-foreground",
1006
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/arrow-up-right" })
1007
+ }
1008
+ ) }),
1009
+ isActive ? /* @__PURE__ */ jsxRuntime.jsx(
1010
+ framerMotion.motion.div,
1011
+ {
1012
+ layout: true,
1013
+ variants,
1014
+ initial: "initial",
1015
+ animate: "animate",
1016
+ exit: "exit",
1017
+ transition: {
1018
+ duration: 0.4,
1019
+ delay: 0.3,
1020
+ ease: "easeOut"
1021
+ },
1022
+ className: "p-6 text-sm md:p-8 md:text-base",
1023
+ children: (feature.title || feature.description) && /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
1024
+ feature.title && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold", children: [
1025
+ feature.title,
1026
+ "."
1027
+ ] }),
1028
+ feature.title && feature.description && " ",
1029
+ feature.description && /* @__PURE__ */ jsxRuntime.jsx("span", { children: feature.description })
1030
+ ] })
1031
+ },
1032
+ `feature-description-active-${feature.title}`
1033
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1034
+ framerMotion.motion.div,
1035
+ {
1036
+ layout: true,
1037
+ variants,
1038
+ initial: "initial",
1039
+ animate: "animate",
1040
+ exit: "exit",
1041
+ transition: {
1042
+ duration: 0.4,
1043
+ delay: 0.2,
1044
+ ease: "easeOut"
1045
+ },
1046
+ className: cn(
1047
+ "flex h-fit shrink-0 items-center gap-4 text-sm md:py-3.5 md:pr-6 md:pl-3 md:text-base",
1048
+ !isActive && "h-0 w-0 md:h-auto md:w-auto"
1049
+ ),
1050
+ style: {
1051
+ height: "auto",
1052
+ lineHeight: "normal"
1053
+ },
1054
+ children: [
1055
+ /* @__PURE__ */ jsxRuntime.jsx(
1056
+ DynamicIcon,
1057
+ {
1058
+ name: "lucide/plus-circle",
1059
+ size: 24,
1060
+ className: "shrink-0"
1061
+ }
1062
+ ),
1063
+ feature.title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0 font-semibold", children: feature.title })
1064
+ ]
1065
+ },
1066
+ `feature-description-inactive-${feature.title}`
1067
+ )
1068
+ ]
1069
+ }
1070
+ ) });
1071
+ }
1072
+ );
1073
+ var FeaturesDesktop = React6__namespace.memo(
1074
+ ({
1075
+ features,
1076
+ handleNext,
1077
+ handlePrevious,
1078
+ activeIndex,
1079
+ handleFeatureClick,
1080
+ isPreviousDisabled,
1081
+ isNextDisabled
1082
+ }) => {
1083
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative z-10 hidden items-center gap-8 md:flex", children: [
1084
+ /* @__PURE__ */ jsxRuntime.jsx(
1085
+ Controls,
1086
+ {
1087
+ handleNext,
1088
+ handlePrevious,
1089
+ isPreviousDisabled,
1090
+ isNextDisabled
1091
+ }
1092
+ ),
1093
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: features.map((feature, index) => {
1094
+ return /* @__PURE__ */ jsxRuntime.jsx(
1095
+ FeatureCard,
1096
+ {
1097
+ feature,
1098
+ isActive: index === activeIndex,
1099
+ onClick: () => handleFeatureClick(index)
613
1100
  },
614
- className: "p-6 text-sm md:p-8 md:text-base",
615
- children: (feature.title || feature.description) && /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
616
- feature.title && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold", children: [
617
- feature.title,
618
- "."
619
- ] }),
620
- feature.title && feature.description && " ",
621
- feature.description && /* @__PURE__ */ jsxRuntime.jsx("span", { children: feature.description })
622
- ] })
1101
+ `feature-card-${index}`
1102
+ );
1103
+ }) })
1104
+ ] });
1105
+ }
1106
+ );
1107
+ var FeaturesMobile = React6__namespace.memo(
1108
+ ({
1109
+ features,
1110
+ handleNext,
1111
+ handlePrevious,
1112
+ activeIndex,
1113
+ direction,
1114
+ isPreviousDisabled,
1115
+ isNextDisabled
1116
+ }) => {
1117
+ const variants = React6.useMemo(
1118
+ () => ({
1119
+ enter: (direction2) => ({
1120
+ x: direction2 > 0 ? 100 : -100,
1121
+ opacity: 0
1122
+ }),
1123
+ center: {
1124
+ x: 0,
1125
+ opacity: 1
623
1126
  },
624
- `feature-description-active-${feature.title}`
625
- ) : /* @__PURE__ */ jsxRuntime.jsxs(
1127
+ exit: (direction2) => ({
1128
+ x: direction2 < 0 ? 100 : -100,
1129
+ opacity: 0
1130
+ })
1131
+ }),
1132
+ []
1133
+ );
1134
+ const currentFeature = features[activeIndex];
1135
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 flex flex-col gap-4 md:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-stretch gap-4", children: [
1136
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", custom: direction, children: /* @__PURE__ */ jsxRuntime.jsx(
626
1137
  framerMotion.motion.div,
627
1138
  {
628
- layout: true,
1139
+ custom: direction,
629
1140
  variants,
630
- initial: "initial",
631
- animate: "animate",
1141
+ initial: "enter",
1142
+ animate: "center",
632
1143
  exit: "exit",
633
1144
  transition: {
634
- duration: 0.4,
635
- delay: 0.2,
636
- ease: "easeOut"
637
- },
638
- className: cn(
639
- "flex h-fit shrink-0 items-center gap-4 text-sm md:py-3.5 md:pr-6 md:pl-3 md:text-base",
640
- !isActive && "h-0 w-0 md:h-auto md:w-auto"
641
- ),
642
- style: {
643
- height: "auto",
644
- lineHeight: "normal"
1145
+ x: { type: "spring", stiffness: 300, damping: 30 },
1146
+ opacity: { duration: 0.2 }
645
1147
  },
646
- children: [
647
- /* @__PURE__ */ jsxRuntime.jsx(
648
- DynamicIcon,
649
- {
650
- name: "lucide/plus-circle",
651
- size: 24,
652
- className: "shrink-0"
653
- }
654
- ),
655
- feature.title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "shrink-0 font-semibold", children: feature.title })
656
- ]
657
- },
658
- `feature-description-inactive-${feature.title}`
659
- )
660
- }
661
- ) });
662
- });
663
- var FeaturesDesktop = React4__namespace.memo(({
664
- features,
665
- handleNext,
666
- handlePrevious,
667
- activeIndex,
668
- handleFeatureClick,
669
- isPreviousDisabled,
670
- isNextDisabled
671
- }) => {
672
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative z-10 hidden items-center gap-8 md:flex", children: [
673
- /* @__PURE__ */ jsxRuntime.jsx(
674
- Controls,
675
- {
676
- handleNext,
677
- handlePrevious,
678
- isPreviousDisabled,
679
- isNextDisabled
680
- }
681
- ),
682
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: features.map((feature, index) => {
683
- return /* @__PURE__ */ jsxRuntime.jsx(
684
- FeatureCard,
685
- {
686
- feature,
687
- isActive: index === activeIndex,
688
- onClick: () => handleFeatureClick(index)
689
- },
690
- `feature-card-${index}`
691
- );
692
- }) })
693
- ] });
694
- });
695
- var FeaturesMobile = React4__namespace.memo(({
696
- features,
697
- handleNext,
698
- handlePrevious,
699
- activeIndex,
700
- direction,
701
- isPreviousDisabled,
702
- isNextDisabled
703
- }) => {
704
- const variants = React4.useMemo(() => ({
705
- enter: (direction2) => ({
706
- x: direction2 > 0 ? 100 : -100,
707
- opacity: 0
708
- }),
709
- center: {
710
- x: 0,
711
- opacity: 1
712
- },
713
- exit: (direction2) => ({
714
- x: direction2 < 0 ? 100 : -100,
715
- opacity: 0
716
- })
717
- }), []);
718
- const currentFeature = features[activeIndex];
719
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 flex flex-col items-center gap-6 md:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center justify-between gap-4", children: [
720
- /* @__PURE__ */ jsxRuntime.jsx(
721
- "button",
722
- {
723
- className: "rounded-full border bg-background/50 p-2 hover:bg-background disabled:opacity-50",
724
- onClick: handlePrevious,
725
- disabled: isPreviousDisabled,
726
- type: "button",
727
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-left", size: 24 })
728
- }
729
- ),
730
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-24 w-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", custom: direction, children: /* @__PURE__ */ jsxRuntime.jsx(
731
- framerMotion.motion.div,
732
- {
733
- custom: direction,
734
- variants,
735
- initial: "enter",
736
- animate: "center",
737
- exit: "exit",
738
- transition: {
739
- x: { type: "spring", stiffness: 300, damping: 30 },
740
- opacity: { duration: 0.2 }
1148
+ className: "rounded-3xl bg-background p-4 text-left",
1149
+ children: (currentFeature?.title || currentFeature?.description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm", children: [
1150
+ currentFeature.title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold", children: currentFeature.title }),
1151
+ currentFeature.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1", children: currentFeature.description })
1152
+ ] })
741
1153
  },
742
- className: "absolute inset-0 flex items-center justify-center rounded-3xl bg-background p-4",
743
- children: (currentFeature?.title || currentFeature?.description) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-center text-sm", children: [
744
- currentFeature.title && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold", children: [
745
- currentFeature.title,
746
- "."
747
- ] }),
748
- currentFeature.title && currentFeature.description && " ",
749
- currentFeature.description && /* @__PURE__ */ jsxRuntime.jsx("span", { children: currentFeature.description })
750
- ] })
751
- },
752
- activeIndex
753
- ) }) }),
754
- /* @__PURE__ */ jsxRuntime.jsx(
755
- "button",
756
- {
757
- className: "rounded-full border bg-background/50 p-2 hover:bg-background disabled:opacity-50",
758
- onClick: handleNext,
759
- disabled: isNextDisabled,
760
- type: "button",
761
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-right", size: 24 })
762
- }
763
- )
764
- ] }) });
765
- });
1154
+ activeIndex
1155
+ ) }) }),
1156
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center gap-2", children: [
1157
+ /* @__PURE__ */ jsxRuntime.jsx(
1158
+ "button",
1159
+ {
1160
+ className: "rounded-full border p-2 flex items-center justify-center disabled:opacity-50 h-fit w-fit bg-card text-card-foreground",
1161
+ onClick: handlePrevious,
1162
+ disabled: isPreviousDisabled,
1163
+ type: "button",
1164
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-up", size: 20 })
1165
+ }
1166
+ ),
1167
+ /* @__PURE__ */ jsxRuntime.jsx(
1168
+ "button",
1169
+ {
1170
+ className: "rounded-full border p-2 flex items-center justify-center disabled:opacity-50 h-fit w-fit bg-card text-card-foreground",
1171
+ onClick: handleNext,
1172
+ disabled: isNextDisabled,
1173
+ type: "button",
1174
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-down", size: 20 })
1175
+ }
1176
+ )
1177
+ ] })
1178
+ ] }) });
1179
+ }
1180
+ );
766
1181
  function FeatureAnimatedCarousel({
1182
+ title,
1183
+ description,
1184
+ titleClassName,
1185
+ descriptionClassName,
767
1186
  features,
768
1187
  className,
769
1188
  optixFlowConfig,
770
1189
  background,
771
- spacing,
772
1190
  pattern,
773
1191
  patternOpacity,
774
- patternClassName
1192
+ patternClassName,
1193
+ headerClassName,
1194
+ blockCardClassName,
1195
+ spacing = "py-12 md:py-32",
1196
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8"
775
1197
  }) {
776
- const [activeIndex, setActiveIndex] = React4__namespace.useState(0);
777
- const [direction, setDirection] = React4__namespace.useState(1);
778
- const handleNext = React4.useCallback(() => {
1198
+ const [activeIndex, setActiveIndex] = React6__namespace.useState(0);
1199
+ const [direction, setDirection] = React6__namespace.useState(1);
1200
+ const handleNext = React6.useCallback(() => {
779
1201
  if (features && activeIndex < features.length - 1) {
780
1202
  setDirection(1);
781
1203
  setActiveIndex(activeIndex + 1);
782
1204
  }
783
1205
  }, [activeIndex, features]);
784
- const handlePrevious = React4.useCallback(() => {
1206
+ const handlePrevious = React6.useCallback(() => {
785
1207
  if (activeIndex > 0) {
786
1208
  setDirection(-1);
787
1209
  setActiveIndex(activeIndex - 1);
788
1210
  }
789
1211
  }, [activeIndex]);
790
- const handleFeatureClick = React4.useCallback((index) => {
791
- setDirection(index > activeIndex ? 1 : -1);
792
- setActiveIndex(index);
793
- }, [activeIndex]);
1212
+ const handleFeatureClick = React6.useCallback(
1213
+ (index) => {
1214
+ setDirection(index > activeIndex ? 1 : -1);
1215
+ setActiveIndex(index);
1216
+ },
1217
+ [activeIndex]
1218
+ );
794
1219
  const isPreviousDisabled = activeIndex === 0;
795
1220
  const isNextDisabled = !features || activeIndex === features.length - 1;
796
- const imageVariants = React4.useMemo(() => ({
797
- enter: (direction2) => ({
798
- x: direction2 > 0 ? 300 : -300,
799
- opacity: 0
1221
+ const imageVariants = React6.useMemo(
1222
+ () => ({
1223
+ enter: (direction2) => ({
1224
+ x: direction2 > 0 ? 300 : -300,
1225
+ opacity: 0
1226
+ }),
1227
+ center: {
1228
+ x: 0,
1229
+ opacity: 1
1230
+ },
1231
+ exit: (direction2) => ({
1232
+ x: direction2 < 0 ? 300 : -300,
1233
+ opacity: 0
1234
+ })
800
1235
  }),
801
- center: {
802
- x: 0,
803
- opacity: 1
804
- },
805
- exit: (direction2) => ({
806
- x: direction2 < 0 ? 300 : -300,
807
- opacity: 0
808
- })
809
- }), []);
1236
+ []
1237
+ );
810
1238
  if (!features || features.length === 0) {
811
1239
  return /* @__PURE__ */ jsxRuntime.jsx(
812
1240
  Section,
@@ -817,11 +1245,15 @@ function FeatureAnimatedCarousel({
817
1245
  patternOpacity,
818
1246
  patternClassName,
819
1247
  className,
820
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
821
- "relative flex min-h-[500px] flex-col-reverse gap-8 overflow-hidden rounded-3xl p-6 md:flex-row md:items-center md:p-12 lg:min-h-[600px]",
822
- getNestedCardBg(background),
823
- getNestedCardTextColor(background)
824
- ) })
1248
+ containerClassName,
1249
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1250
+ "div",
1251
+ {
1252
+ className: cn(
1253
+ "relative flex min-h-[500px] flex-col-reverse gap-8 overflow-hidden rounded-3xl bg-muted p-6 md:flex-row md:items-center md:p-12 lg:min-h-[600px]"
1254
+ )
1255
+ }
1256
+ )
825
1257
  }
826
1258
  );
827
1259
  }
@@ -835,60 +1267,116 @@ function FeatureAnimatedCarousel({
835
1267
  patternOpacity,
836
1268
  patternClassName,
837
1269
  className,
838
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
839
- "relative flex min-h-[500px] flex-col-reverse gap-8 overflow-hidden rounded-3xl p-6 md:flex-row md:items-center md:p-12 lg:min-h-[600px]",
840
- getNestedCardBg(background),
841
- getNestedCardTextColor(background)
842
- ), children: [
843
- /* @__PURE__ */ jsxRuntime.jsx(
844
- FeaturesDesktop,
1270
+ containerClassName,
1271
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-6 md:space-y-16", children: [
1272
+ title || description ? /* @__PURE__ */ jsxRuntime.jsxs(
1273
+ "div",
845
1274
  {
846
- features,
847
- handleNext,
848
- handlePrevious,
849
- activeIndex,
850
- handleFeatureClick,
851
- isPreviousDisabled,
852
- isNextDisabled
1275
+ className: cn(
1276
+ "flex flex-col gap-4 md:gap-6 text-left",
1277
+ headerClassName
1278
+ ),
1279
+ children: [
1280
+ title && (typeof title === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1281
+ "h2",
1282
+ {
1283
+ className: cn(
1284
+ "text-xl font-semibold text-balance md:text-2xl lg:text-3xl max-w-lg md:max-w-md",
1285
+ titleClassName
1286
+ ),
1287
+ children: title
1288
+ }
1289
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1290
+ "div",
1291
+ {
1292
+ className: cn(
1293
+ "text-xl font-semibold text-balance md:text-2xl lg:text-3xl max-w-lg md:max-w-md",
1294
+ titleClassName
1295
+ ),
1296
+ children: title
1297
+ }
1298
+ )),
1299
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("max-w-lg md:max-w-md", descriptionClassName), children: description }) : /* @__PURE__ */ jsxRuntime.jsx(
1300
+ "div",
1301
+ {
1302
+ className: cn("max-w-lg md:max-w-md", descriptionClassName),
1303
+ children: description
1304
+ }
1305
+ ))
1306
+ ]
853
1307
  }
854
- ),
855
- /* @__PURE__ */ jsxRuntime.jsx(
856
- FeaturesMobile,
1308
+ ) : null,
1309
+ /* @__PURE__ */ jsxRuntime.jsxs(
1310
+ "div",
857
1311
  {
858
- features,
859
- handleNext,
860
- handlePrevious,
861
- activeIndex,
862
- direction,
863
- isPreviousDisabled,
864
- isNextDisabled
1312
+ className: cn(
1313
+ "relative flex min-h-full md:min-h-[500px] flex-col-reverse gap-5 md:gap-8 bg-muted overflow-hidden rounded-3xl p-4 md:p-6 md:flex-row md:items-center lg:p-12 lg:min-h-[600px]",
1314
+ blockCardClassName
1315
+ ),
1316
+ children: [
1317
+ /* @__PURE__ */ jsxRuntime.jsx(
1318
+ FeaturesDesktop,
1319
+ {
1320
+ features,
1321
+ handleNext,
1322
+ handlePrevious,
1323
+ activeIndex,
1324
+ handleFeatureClick,
1325
+ isPreviousDisabled,
1326
+ isNextDisabled
1327
+ }
1328
+ ),
1329
+ /* @__PURE__ */ jsxRuntime.jsx(
1330
+ FeaturesMobile,
1331
+ {
1332
+ features,
1333
+ handleNext,
1334
+ handlePrevious,
1335
+ activeIndex,
1336
+ direction,
1337
+ isPreviousDisabled,
1338
+ isNextDisabled
1339
+ }
1340
+ ),
1341
+ currentFeature?.image && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-[250px] md:h-auto md:absolute md:right-8 md:top-8 md:bottom-8 md:w-1/2", children: [
1342
+ currentFeature.href && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 right-4 z-10 rounded-full h-fit w-fit shadow-md hover:shadow-2xl flex items-center justify-center md:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
1343
+ Pressable,
1344
+ {
1345
+ href: currentFeature.href,
1346
+ size: "icon-lg",
1347
+ className: "bg-primary text-primary-foreground",
1348
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/arrow-up-right" })
1349
+ }
1350
+ ) }),
1351
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", custom: direction, children: /* @__PURE__ */ jsxRuntime.jsx(
1352
+ framerMotion.motion.div,
1353
+ {
1354
+ custom: direction,
1355
+ variants: imageVariants,
1356
+ initial: "enter",
1357
+ animate: "center",
1358
+ exit: "exit",
1359
+ transition: {
1360
+ x: { type: "spring", stiffness: 300, damping: 30 },
1361
+ opacity: { duration: 0.3 }
1362
+ },
1363
+ className: "h-full w-full shadow-xl overflow-hidden rounded-2xl",
1364
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1365
+ img.Img,
1366
+ {
1367
+ src: currentFeature.image,
1368
+ alt: currentFeature.imageAlt || (typeof currentFeature.title === "string" ? currentFeature.title : "Feature image"),
1369
+ className: "h-full w-full object-cover",
1370
+ optixFlowConfig
1371
+ }
1372
+ )
1373
+ },
1374
+ activeIndex
1375
+ ) })
1376
+ ] })
1377
+ ]
865
1378
  }
866
- ),
867
- currentFeature?.image && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex-1 overflow-hidden rounded-2xl md:absolute md:right-8 md:top-8 md:bottom-8 md:w-1/2", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", custom: direction, children: /* @__PURE__ */ jsxRuntime.jsx(
868
- framerMotion.motion.div,
869
- {
870
- custom: direction,
871
- variants: imageVariants,
872
- initial: "enter",
873
- animate: "center",
874
- exit: "exit",
875
- transition: {
876
- x: { type: "spring", stiffness: 300, damping: 30 },
877
- opacity: { duration: 0.2 }
878
- },
879
- className: "h-full w-full",
880
- children: /* @__PURE__ */ jsxRuntime.jsx(
881
- img.Img,
882
- {
883
- src: currentFeature.image,
884
- alt: currentFeature.imageAlt || (typeof currentFeature.title === "string" ? currentFeature.title : "Feature image"),
885
- className: "h-full w-full object-cover",
886
- optixFlowConfig
887
- }
888
- )
889
- },
890
- activeIndex
891
- ) }) })
1379
+ )
892
1380
  ] })
893
1381
  }
894
1382
  );