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