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