@opensite/ui 1.2.2 → 1.2.4

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.
Files changed (51) hide show
  1. package/dist/auto-scroll-carousel.cjs +2 -2
  2. package/dist/auto-scroll-carousel.js +2 -2
  3. package/dist/blur-vignette-grid.cjs +13 -17
  4. package/dist/blur-vignette-grid.d.cts +2 -2
  5. package/dist/blur-vignette-grid.d.ts +2 -2
  6. package/dist/blur-vignette-grid.js +13 -17
  7. package/dist/carousel-gradient-text.cjs +8 -10
  8. package/dist/carousel-gradient-text.js +8 -10
  9. package/dist/carousel-icon-sidebar.cjs +48 -29
  10. package/dist/carousel-icon-sidebar.js +48 -29
  11. package/dist/carousel-scale-focus.cjs +27 -1
  12. package/dist/carousel-scale-focus.js +27 -1
  13. package/dist/carousel-tabs-content.cjs +46 -36
  14. package/dist/carousel-tabs-content.js +46 -36
  15. package/dist/expandable-case-study-cards.cjs +1 -0
  16. package/dist/expandable-case-study-cards.js +1 -0
  17. package/dist/feature-capabilities-grid.cjs +525 -54
  18. package/dist/feature-capabilities-grid.d.cts +4 -0
  19. package/dist/feature-capabilities-grid.d.ts +4 -0
  20. package/dist/feature-capabilities-grid.js +525 -54
  21. package/dist/feature-card-grid-linked.cjs +40 -35
  22. package/dist/feature-card-grid-linked.d.cts +9 -1
  23. package/dist/feature-card-grid-linked.d.ts +9 -1
  24. package/dist/feature-card-grid-linked.js +40 -35
  25. package/dist/feature-carousel-progress.cjs +129 -56
  26. package/dist/feature-carousel-progress.d.cts +13 -1
  27. package/dist/feature-carousel-progress.d.ts +13 -1
  28. package/dist/feature-carousel-progress.js +129 -56
  29. package/dist/feature-checklist-image.cjs +61 -105
  30. package/dist/feature-checklist-image.d.cts +1 -1
  31. package/dist/feature-checklist-image.d.ts +1 -1
  32. package/dist/feature-checklist-image.js +61 -105
  33. package/dist/feature-icon-grid-bordered.cjs +457 -35
  34. package/dist/feature-icon-grid-bordered.d.cts +4 -0
  35. package/dist/feature-icon-grid-bordered.d.ts +4 -0
  36. package/dist/feature-icon-grid-bordered.js +457 -35
  37. package/dist/feature-numbered-cards.cjs +519 -35
  38. package/dist/feature-numbered-cards.d.cts +18 -2
  39. package/dist/feature-numbered-cards.d.ts +18 -2
  40. package/dist/feature-numbered-cards.js +520 -36
  41. package/dist/feature-split-image.cjs +1 -1
  42. package/dist/feature-split-image.js +1 -1
  43. package/dist/masonry-motion-grid.cjs +2 -2
  44. package/dist/masonry-motion-grid.js +2 -2
  45. package/dist/registry.cjs +10264 -9952
  46. package/dist/registry.js +10262 -9950
  47. package/dist/testimonial-carousel-cards.cjs +28 -8
  48. package/dist/testimonial-carousel-cards.d.cts +8 -0
  49. package/dist/testimonial-carousel-cards.d.ts +8 -0
  50. package/dist/testimonial-carousel-cards.js +28 -8
  51. package/package.json +1 -1
@@ -6,6 +6,7 @@ var framerMotion = require('framer-motion');
6
6
  var clsx = require('clsx');
7
7
  var tailwindMerge = require('tailwind-merge');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
+ var classVarianceAuthority = require('class-variance-authority');
9
10
 
10
11
  function _interopNamespace(e) {
11
12
  if (e && e.__esModule) return e;
@@ -31,32 +32,6 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
31
32
  function cn(...inputs) {
32
33
  return tailwindMerge.twMerge(clsx.clsx(inputs));
33
34
  }
34
- function getTextColor(parentBg, variant = "default", options) {
35
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
36
- if (isDark) {
37
- switch (variant) {
38
- case "default":
39
- return "text-foreground";
40
- case "muted":
41
- return "text-foreground/80";
42
- case "subtle":
43
- return "text-foreground/60";
44
- case "accent":
45
- return "text-accent-foreground";
46
- }
47
- } else {
48
- switch (variant) {
49
- case "default":
50
- return "text-foreground";
51
- case "muted":
52
- return "text-muted-foreground";
53
- case "subtle":
54
- return "text-muted-foreground/70";
55
- case "accent":
56
- return "text-primary";
57
- }
58
- }
59
- }
60
35
  var svgCache = /* @__PURE__ */ new Map();
61
36
  function DynamicIcon({
62
37
  name,
@@ -188,16 +163,6 @@ function CardHeader({ className, ...props }) {
188
163
  }
189
164
  );
190
165
  }
191
- function CardTitle({ className, ...props }) {
192
- return /* @__PURE__ */ jsxRuntime.jsx(
193
- "div",
194
- {
195
- "data-slot": "card-title",
196
- className: cn("leading-none font-semibold", className),
197
- ...props
198
- }
199
- );
200
- }
201
166
  function CardContent({ className, ...props }) {
202
167
  return /* @__PURE__ */ jsxRuntime.jsx(
203
168
  "div",
@@ -583,6 +548,424 @@ var Section = React__namespace.default.forwardRef(
583
548
  }
584
549
  );
585
550
  Section.displayName = "Section";
551
+ var baseStyles = [
552
+ // Layout
553
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
554
+ // Typography - using CSS variables with sensible defaults
555
+ "font-[var(--button-font-family,inherit)]",
556
+ "font-[var(--button-font-weight,500)]",
557
+ "tracking-[var(--button-letter-spacing,0)]",
558
+ "leading-[var(--button-line-height,1.25)]",
559
+ "[text-transform:var(--button-text-transform,none)]",
560
+ "text-sm",
561
+ // Border radius
562
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
563
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
564
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
565
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
566
+ "[box-shadow:var(--button-shadow,none)]",
567
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
568
+ // Disabled state
569
+ "disabled:pointer-events-none disabled:opacity-50",
570
+ // SVG handling
571
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
572
+ // Focus styles
573
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
574
+ // Invalid state
575
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
576
+ ].join(" ");
577
+ var buttonVariants = classVarianceAuthority.cva(baseStyles, {
578
+ variants: {
579
+ variant: {
580
+ // Default (Primary) variant - full customization
581
+ default: [
582
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
583
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
584
+ "border-[length:var(--button-default-border-width,0px)]",
585
+ "border-[color:var(--button-default-border,transparent)]",
586
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
587
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
588
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
589
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
590
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
591
+ ].join(" "),
592
+ // Destructive variant - full customization
593
+ destructive: [
594
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
595
+ "text-[var(--button-destructive-fg,white)]",
596
+ "border-[length:var(--button-destructive-border-width,0px)]",
597
+ "border-[color:var(--button-destructive-border,transparent)]",
598
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
599
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
600
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
601
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
602
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
603
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
604
+ "dark:bg-destructive/60"
605
+ ].join(" "),
606
+ // Outline variant - full customization with proper border handling
607
+ outline: [
608
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
609
+ "text-[var(--button-outline-fg,inherit)]",
610
+ "border-[length:var(--button-outline-border-width,1px)]",
611
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
612
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
613
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
614
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
615
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
616
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
617
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
618
+ ].join(" "),
619
+ // Secondary variant - full customization
620
+ secondary: [
621
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
622
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
623
+ "border-[length:var(--button-secondary-border-width,0px)]",
624
+ "border-[color:var(--button-secondary-border,transparent)]",
625
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
626
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
627
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
628
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
629
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
630
+ ].join(" "),
631
+ // Ghost variant - full customization
632
+ ghost: [
633
+ "bg-[var(--button-ghost-bg,transparent)]",
634
+ "text-[var(--button-ghost-fg,inherit)]",
635
+ "border-[length:var(--button-ghost-border-width,0px)]",
636
+ "border-[color:var(--button-ghost-border,transparent)]",
637
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
638
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
639
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
640
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
641
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
642
+ "dark:hover:bg-accent/50"
643
+ ].join(" "),
644
+ // Link variant - full customization
645
+ link: [
646
+ "bg-[var(--button-link-bg,transparent)]",
647
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
648
+ "border-[length:var(--button-link-border-width,0px)]",
649
+ "border-[color:var(--button-link-border,transparent)]",
650
+ "[box-shadow:var(--button-link-shadow,none)]",
651
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
652
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
653
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
654
+ "underline-offset-4 hover:underline"
655
+ ].join(" ")
656
+ },
657
+ size: {
658
+ default: [
659
+ "h-[var(--button-height-md,2.25rem)]",
660
+ "px-[var(--button-padding-x-md,1rem)]",
661
+ "py-[var(--button-padding-y-md,0.5rem)]",
662
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
663
+ ].join(" "),
664
+ sm: [
665
+ "h-[var(--button-height-sm,2rem)]",
666
+ "px-[var(--button-padding-x-sm,0.75rem)]",
667
+ "py-[var(--button-padding-y-sm,0.25rem)]",
668
+ "gap-1.5",
669
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
670
+ ].join(" "),
671
+ md: [
672
+ "h-[var(--button-height-md,2.25rem)]",
673
+ "px-[var(--button-padding-x-md,1rem)]",
674
+ "py-[var(--button-padding-y-md,0.5rem)]",
675
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
676
+ ].join(" "),
677
+ lg: [
678
+ "h-[var(--button-height-lg,2.5rem)]",
679
+ "px-[var(--button-padding-x-lg,1.5rem)]",
680
+ "py-[var(--button-padding-y-lg,0.5rem)]",
681
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
682
+ ].join(" "),
683
+ icon: "size-[var(--button-height-md,2.25rem)]",
684
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
685
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
686
+ }
687
+ },
688
+ defaultVariants: {
689
+ variant: "default",
690
+ size: "default"
691
+ }
692
+ });
693
+ function normalizePhoneNumber(input) {
694
+ const trimmed = input.trim();
695
+ if (trimmed.toLowerCase().startsWith("tel:")) {
696
+ return trimmed;
697
+ }
698
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
699
+ if (match) {
700
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
701
+ const extension = match[3];
702
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
703
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
704
+ return `tel:${withExtension}`;
705
+ }
706
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
707
+ return `tel:${cleaned}`;
708
+ }
709
+ function normalizeEmail(input) {
710
+ const trimmed = input.trim();
711
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
712
+ return trimmed;
713
+ }
714
+ return `mailto:${trimmed}`;
715
+ }
716
+ function isEmail(input) {
717
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
718
+ return emailRegex.test(input.trim());
719
+ }
720
+ function isPhoneNumber(input) {
721
+ const trimmed = input.trim();
722
+ if (trimmed.toLowerCase().startsWith("tel:")) {
723
+ return true;
724
+ }
725
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
726
+ return phoneRegex.test(trimmed);
727
+ }
728
+ function isInternalUrl(href) {
729
+ if (typeof window === "undefined") {
730
+ return href.startsWith("/") && !href.startsWith("//");
731
+ }
732
+ const trimmed = href.trim();
733
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
734
+ return true;
735
+ }
736
+ try {
737
+ const url = new URL(trimmed, window.location.href);
738
+ const currentOrigin = window.location.origin;
739
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
740
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
741
+ } catch {
742
+ return false;
743
+ }
744
+ }
745
+ function toRelativePath(href) {
746
+ if (typeof window === "undefined") {
747
+ return href;
748
+ }
749
+ const trimmed = href.trim();
750
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
751
+ return trimmed;
752
+ }
753
+ try {
754
+ const url = new URL(trimmed, window.location.href);
755
+ const currentOrigin = window.location.origin;
756
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
757
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
758
+ return url.pathname + url.search + url.hash;
759
+ }
760
+ } catch {
761
+ }
762
+ return trimmed;
763
+ }
764
+ function useNavigation({
765
+ href,
766
+ onClick
767
+ } = {}) {
768
+ const linkType = React__namespace.useMemo(() => {
769
+ if (!href || href.trim() === "") {
770
+ return onClick ? "none" : "none";
771
+ }
772
+ const trimmed = href.trim();
773
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
774
+ return "mailto";
775
+ }
776
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
777
+ return "tel";
778
+ }
779
+ if (isInternalUrl(trimmed)) {
780
+ return "internal";
781
+ }
782
+ try {
783
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
784
+ return "external";
785
+ } catch {
786
+ return "internal";
787
+ }
788
+ }, [href, onClick]);
789
+ const normalizedHref = React__namespace.useMemo(() => {
790
+ if (!href || href.trim() === "") {
791
+ return void 0;
792
+ }
793
+ const trimmed = href.trim();
794
+ switch (linkType) {
795
+ case "tel":
796
+ return normalizePhoneNumber(trimmed);
797
+ case "mailto":
798
+ return normalizeEmail(trimmed);
799
+ case "internal":
800
+ return toRelativePath(trimmed);
801
+ case "external":
802
+ return trimmed;
803
+ default:
804
+ return trimmed;
805
+ }
806
+ }, [href, linkType]);
807
+ const target = React__namespace.useMemo(() => {
808
+ switch (linkType) {
809
+ case "external":
810
+ return "_blank";
811
+ case "internal":
812
+ return "_self";
813
+ case "mailto":
814
+ case "tel":
815
+ return void 0;
816
+ default:
817
+ return void 0;
818
+ }
819
+ }, [linkType]);
820
+ const rel = React__namespace.useMemo(() => {
821
+ if (linkType === "external") {
822
+ return "noopener noreferrer";
823
+ }
824
+ return void 0;
825
+ }, [linkType]);
826
+ const isExternal = linkType === "external";
827
+ const isInternal = linkType === "internal";
828
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
829
+ const handleClick = React__namespace.useCallback(
830
+ (event) => {
831
+ if (onClick) {
832
+ try {
833
+ onClick(event);
834
+ } catch (error) {
835
+ console.error("Error in user onClick handler:", error);
836
+ }
837
+ }
838
+ if (event.defaultPrevented) {
839
+ return;
840
+ }
841
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
842
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
843
+ if (typeof window !== "undefined") {
844
+ const handler = window.__opensiteNavigationHandler;
845
+ if (typeof handler === "function") {
846
+ try {
847
+ const handled = handler(normalizedHref, event.nativeEvent || event);
848
+ if (handled !== false) {
849
+ event.preventDefault();
850
+ }
851
+ } catch (error) {
852
+ console.error("Error in navigation handler:", error);
853
+ }
854
+ }
855
+ }
856
+ }
857
+ },
858
+ [onClick, shouldUseRouter, normalizedHref]
859
+ );
860
+ return {
861
+ linkType,
862
+ normalizedHref,
863
+ target,
864
+ rel,
865
+ isExternal,
866
+ isInternal,
867
+ shouldUseRouter,
868
+ handleClick
869
+ };
870
+ }
871
+ var Pressable = React__namespace.forwardRef(
872
+ ({
873
+ children,
874
+ className,
875
+ href,
876
+ onClick,
877
+ variant,
878
+ size,
879
+ asButton = false,
880
+ fallbackComponentType = "span",
881
+ componentType,
882
+ "aria-label": ariaLabel,
883
+ "aria-describedby": ariaDescribedby,
884
+ id,
885
+ ...props
886
+ }, ref) => {
887
+ const navigation = useNavigation({ href, onClick });
888
+ const {
889
+ normalizedHref,
890
+ target,
891
+ rel,
892
+ linkType,
893
+ isInternal,
894
+ handleClick
895
+ } = navigation;
896
+ const shouldRenderLink = normalizedHref && linkType !== "none";
897
+ const shouldRenderButton = !shouldRenderLink && onClick;
898
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
899
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
900
+ const shouldApplyButtonStyles = asButton || variant || size;
901
+ const combinedClassName = cn(
902
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
903
+ className
904
+ );
905
+ const dataProps = Object.fromEntries(
906
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
907
+ );
908
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
909
+ "data-slot": "button",
910
+ "data-variant": variant ?? "default",
911
+ "data-size": size ?? "default"
912
+ } : {};
913
+ const commonProps = {
914
+ className: combinedClassName,
915
+ onClick: handleClick,
916
+ "aria-label": ariaLabel,
917
+ "aria-describedby": ariaDescribedby,
918
+ id,
919
+ ...dataProps,
920
+ ...buttonDataAttributes
921
+ };
922
+ if (finalComponentType === "a" && shouldRenderLink) {
923
+ return /* @__PURE__ */ jsxRuntime.jsx(
924
+ "a",
925
+ {
926
+ ref,
927
+ href: normalizedHref,
928
+ target,
929
+ rel,
930
+ ...commonProps,
931
+ ...props,
932
+ children
933
+ }
934
+ );
935
+ }
936
+ if (finalComponentType === "button") {
937
+ return /* @__PURE__ */ jsxRuntime.jsx(
938
+ "button",
939
+ {
940
+ ref,
941
+ type: props.type || "button",
942
+ ...commonProps,
943
+ ...props,
944
+ children
945
+ }
946
+ );
947
+ }
948
+ if (finalComponentType === "div") {
949
+ return /* @__PURE__ */ jsxRuntime.jsx(
950
+ "div",
951
+ {
952
+ ref,
953
+ ...commonProps,
954
+ children
955
+ }
956
+ );
957
+ }
958
+ return /* @__PURE__ */ jsxRuntime.jsx(
959
+ "span",
960
+ {
961
+ ref,
962
+ ...commonProps,
963
+ children
964
+ }
965
+ );
966
+ }
967
+ );
968
+ Pressable.displayName = "Pressable";
586
969
  function FeatureCapabilitiesGrid({
587
970
  eyebrow,
588
971
  heading,
@@ -600,11 +983,14 @@ function FeatureCapabilitiesGrid({
600
983
  patternOpacity,
601
984
  patternClassName
602
985
  }) {
603
- const renderItemIcon = React__namespace.useCallback((item) => {
604
- if (item.icon) return item.icon;
605
- if (item.iconName) return /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: item.iconName, size: 20 });
606
- return null;
607
- }, []);
986
+ const renderItemIcon = React__namespace.useCallback(
987
+ (item) => {
988
+ if (item.icon) return item.icon;
989
+ if (item.iconName) return /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: item.iconName, size: 20 });
990
+ return null;
991
+ },
992
+ []
993
+ );
608
994
  const itemsContent = React.useMemo(() => {
609
995
  if (itemsSlot) return itemsSlot;
610
996
  if (!items || items.length === 0) return null;
@@ -613,7 +999,11 @@ function FeatureCapabilitiesGrid({
613
999
  return /* @__PURE__ */ jsxRuntime.jsxs(
614
1000
  Card,
615
1001
  {
616
- className: cn("group relative overflow-visible border-border/10 bg-background/5 p-0 transition-colors duration-300 hover:border-border/20", cardClassName, item.className),
1002
+ className: cn(
1003
+ "group relative overflow-visible border-border/10 bg-background/5 p-0 transition-colors duration-300 hover:border-border/20",
1004
+ cardClassName,
1005
+ item.className
1006
+ ),
617
1007
  children: [
618
1008
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -inset-px rounded-xl bg-linear-to-br from-background/10 via-background/5 to-transparent" }) }),
619
1009
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-0 rounded-xl bg-linear-to-tr from-background/0 to-background/0 transition-colors group-hover:from-background/3 group-hover:to-background/6" }),
@@ -624,13 +1014,59 @@ function FeatureCapabilitiesGrid({
624
1014
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -right-2 -bottom-2 h-3 w-3 bg-background" })
625
1015
  ] }),
626
1016
  /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "relative z-10 flex flex-row items-start gap-3 p-6", children: [
627
- iconContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex h-10 w-10 items-center justify-center rounded-xl border border-border/15 bg-background/5", item.iconClassName), children: iconContent }),
628
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
629
- item.title && (typeof item.title === "string" ? /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: cn("text-lg font-medium", item.titleClassName), children: item.title }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-lg font-medium", item.titleClassName), children: item.title })),
630
- item.badge && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full border border-border/20 px-2 py-0.5 text-[10px] leading-none", getTextColor(background, "muted"), item.badgeClassName), children: item.badge })
631
- ] }) })
1017
+ iconContent && /* @__PURE__ */ jsxRuntime.jsx(
1018
+ "div",
1019
+ {
1020
+ className: cn(
1021
+ "flex h-10 w-10 items-center justify-center rounded-xl border border-border/15 bg-background/5",
1022
+ item.iconClassName
1023
+ ),
1024
+ children: iconContent
1025
+ }
1026
+ ),
1027
+ /* @__PURE__ */ jsxRuntime.jsx(
1028
+ Pressable,
1029
+ {
1030
+ href: item.href,
1031
+ className: "flex-1 h-full flex items-center",
1032
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1033
+ item.title && (typeof item.title === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1034
+ "h3",
1035
+ {
1036
+ className: cn("text-lg font-medium", item.titleClassName),
1037
+ children: item.title
1038
+ }
1039
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1040
+ "div",
1041
+ {
1042
+ className: cn("text-lg font-medium", item.titleClassName),
1043
+ children: item.title
1044
+ }
1045
+ )),
1046
+ item.badge && /* @__PURE__ */ jsxRuntime.jsx(
1047
+ "span",
1048
+ {
1049
+ className: cn(
1050
+ "rounded-full border border-border/20 px-2 py-0.5 text-[10px] leading-none",
1051
+ item.badgeClassName
1052
+ ),
1053
+ children: item.badge
1054
+ }
1055
+ )
1056
+ ] })
1057
+ }
1058
+ )
632
1059
  ] }),
633
- item.description && /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: cn("relative z-10 px-6 pb-6 text-sm", getTextColor(background, "muted"), item.descriptionClassName), children: item.description }),
1060
+ item.description && /* @__PURE__ */ jsxRuntime.jsx(
1061
+ CardContent,
1062
+ {
1063
+ className: cn(
1064
+ "relative z-10 px-6 pb-6 text-sm",
1065
+ item.descriptionClassName
1066
+ ),
1067
+ children: item.description
1068
+ }
1069
+ ),
634
1070
  /* @__PURE__ */ jsxRuntime.jsx(
635
1071
  framerMotion.motion.div,
636
1072
  {
@@ -646,7 +1082,7 @@ function FeatureCapabilitiesGrid({
646
1082
  );
647
1083
  });
648
1084
  }, [itemsSlot, items, cardClassName, renderItemIcon]);
649
- return /* @__PURE__ */ jsxRuntime.jsxs(
1085
+ return /* @__PURE__ */ jsxRuntime.jsx(
650
1086
  Section,
651
1087
  {
652
1088
  background,
@@ -656,11 +1092,46 @@ function FeatureCapabilitiesGrid({
656
1092
  patternClassName,
657
1093
  className,
658
1094
  containerClassName,
659
- children: [
660
- eyebrow && (typeof eyebrow === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-xs tracking-widest", getTextColor(background, "muted"), eyebrowClassName), children: eyebrow }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-xs tracking-widest", getTextColor(background, "muted"), eyebrowClassName), children: eyebrow })),
661
- heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: cn("mt-3 text-4xl font-semibold tracking-tight sm:text-5xl", headingClassName), children: heading }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-3 text-4xl font-semibold tracking-tight sm:text-5xl", headingClassName), children: heading })),
662
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-10 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", gridClassName), children: itemsContent })
663
- ]
1095
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-6 md:space-y-16", children: [
1096
+ eyebrow || heading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
1097
+ eyebrow && (typeof eyebrow === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-xs tracking-widest", eyebrowClassName), children: eyebrow }) : /* @__PURE__ */ jsxRuntime.jsx(
1098
+ "div",
1099
+ {
1100
+ className: cn("text-xs tracking-widest", eyebrowClassName),
1101
+ children: eyebrow
1102
+ }
1103
+ )),
1104
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1105
+ "h2",
1106
+ {
1107
+ className: cn(
1108
+ "mt-3 text-4xl font-semibold tracking-tight sm:text-5xl",
1109
+ headingClassName
1110
+ ),
1111
+ children: heading
1112
+ }
1113
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1114
+ "div",
1115
+ {
1116
+ className: cn(
1117
+ "mt-3 text-4xl font-semibold tracking-tight sm:text-5xl",
1118
+ headingClassName
1119
+ ),
1120
+ children: heading
1121
+ }
1122
+ ))
1123
+ ] }) : null,
1124
+ /* @__PURE__ */ jsxRuntime.jsx(
1125
+ "div",
1126
+ {
1127
+ className: cn(
1128
+ "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
1129
+ gridClassName
1130
+ ),
1131
+ children: itemsContent
1132
+ }
1133
+ )
1134
+ ] })
664
1135
  }
665
1136
  );
666
1137
  }
@@ -47,6 +47,10 @@ interface FeatureCapabilitiesGridItem {
47
47
  * Additional CSS classes for the badge
48
48
  */
49
49
  badgeClassName?: string;
50
+ /**
51
+ * Optional href for the item
52
+ */
53
+ href?: string;
50
54
  }
51
55
  interface FeatureCapabilitiesGridProps {
52
56
  /**
@@ -47,6 +47,10 @@ interface FeatureCapabilitiesGridItem {
47
47
  * Additional CSS classes for the badge
48
48
  */
49
49
  badgeClassName?: string;
50
+ /**
51
+ * Optional href for the item
52
+ */
53
+ href?: string;
50
54
  }
51
55
  interface FeatureCapabilitiesGridProps {
52
56
  /**