@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
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { f as SectionBackground, g as SectionSpacing, t as PatternName } from './community-initiatives-Bi_ClKrO.js';
3
- import { O as OptixFlowConfig } from './blocks-k17uluAz.js';
3
+ import { A as ActionConfig, O as OptixFlowConfig } from './blocks-k17uluAz.js';
4
4
  import 'react/jsx-runtime';
5
5
  import 'class-variance-authority';
6
6
  import './button-variants-lRElsmTc.js';
@@ -65,8 +65,24 @@ interface FeatureNumberedCardsItem {
65
65
  * Additional CSS classes for the image wrapper
66
66
  */
67
67
  imageWrapperClassName?: string;
68
+ /**
69
+ * Array of action configurations for CTA buttons
70
+ */
71
+ actions?: ActionConfig[];
72
+ /**
73
+ * Custom slot for rendering actions (overrides actions array)
74
+ */
75
+ actionsSlot?: React.ReactNode;
68
76
  }
69
77
  interface FeatureNumberedCardsProps {
78
+ /**
79
+ * Feature title content
80
+ */
81
+ title?: React.ReactNode;
82
+ /**
83
+ * Feature description content
84
+ */
85
+ description?: React.ReactNode;
70
86
  /**
71
87
  * Array of numbered feature cards
72
88
  */
@@ -154,6 +170,6 @@ interface FeatureNumberedCardsProps {
154
170
  * />
155
171
  * ```
156
172
  */
157
- declare function FeatureNumberedCards({ features, featuresSlot, className, containerClassName, cardsWrapperClassName, cardClassName, titleClassName, descriptionClassName, checklistClassName, badgeClassName, optixFlowConfig, background, spacing, pattern, patternOpacity, patternClassName, }: FeatureNumberedCardsProps): React.JSX.Element;
173
+ declare function FeatureNumberedCards({ title, description, features, featuresSlot, className, containerClassName, cardsWrapperClassName, cardClassName, titleClassName, descriptionClassName, checklistClassName, badgeClassName, optixFlowConfig, background, spacing, pattern, patternOpacity, patternClassName, }: FeatureNumberedCardsProps): React.JSX.Element;
158
174
 
159
175
  export { FeatureNumberedCards, type FeatureNumberedCardsProps };
@@ -3,8 +3,9 @@ import * as React from 'react';
3
3
  import React__default, { useCallback, useMemo } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
- import { jsx, jsxs } from 'react/jsx-runtime';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { Img } from '@page-speed/img';
8
+ import { cva } from 'class-variance-authority';
8
9
 
9
10
  // components/blocks/features/feature-numbered-cards.tsx
10
11
  function cn(...inputs) {
@@ -490,11 +491,431 @@ var Section = React__default.forwardRef(
490
491
  }
491
492
  );
492
493
  Section.displayName = "Section";
494
+ var baseStyles = [
495
+ // Layout
496
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
497
+ // Typography - using CSS variables with sensible defaults
498
+ "font-[var(--button-font-family,inherit)]",
499
+ "font-[var(--button-font-weight,500)]",
500
+ "tracking-[var(--button-letter-spacing,0)]",
501
+ "leading-[var(--button-line-height,1.25)]",
502
+ "[text-transform:var(--button-text-transform,none)]",
503
+ "text-sm",
504
+ // Border radius
505
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
506
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
507
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
508
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
509
+ "[box-shadow:var(--button-shadow,none)]",
510
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
511
+ // Disabled state
512
+ "disabled:pointer-events-none disabled:opacity-50",
513
+ // SVG handling
514
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
515
+ // Focus styles
516
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
517
+ // Invalid state
518
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
519
+ ].join(" ");
520
+ var buttonVariants = cva(baseStyles, {
521
+ variants: {
522
+ variant: {
523
+ // Default (Primary) variant - full customization
524
+ default: [
525
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
526
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
527
+ "border-[length:var(--button-default-border-width,0px)]",
528
+ "border-[color:var(--button-default-border,transparent)]",
529
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
530
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
531
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
532
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
533
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
534
+ ].join(" "),
535
+ // Destructive variant - full customization
536
+ destructive: [
537
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
538
+ "text-[var(--button-destructive-fg,white)]",
539
+ "border-[length:var(--button-destructive-border-width,0px)]",
540
+ "border-[color:var(--button-destructive-border,transparent)]",
541
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
542
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
543
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
544
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
545
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
546
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
547
+ "dark:bg-destructive/60"
548
+ ].join(" "),
549
+ // Outline variant - full customization with proper border handling
550
+ outline: [
551
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
552
+ "text-[var(--button-outline-fg,inherit)]",
553
+ "border-[length:var(--button-outline-border-width,1px)]",
554
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
555
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
556
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
557
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
558
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
559
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
560
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
561
+ ].join(" "),
562
+ // Secondary variant - full customization
563
+ secondary: [
564
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
565
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
566
+ "border-[length:var(--button-secondary-border-width,0px)]",
567
+ "border-[color:var(--button-secondary-border,transparent)]",
568
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
569
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
570
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
571
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
572
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
573
+ ].join(" "),
574
+ // Ghost variant - full customization
575
+ ghost: [
576
+ "bg-[var(--button-ghost-bg,transparent)]",
577
+ "text-[var(--button-ghost-fg,inherit)]",
578
+ "border-[length:var(--button-ghost-border-width,0px)]",
579
+ "border-[color:var(--button-ghost-border,transparent)]",
580
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
581
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
582
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
583
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
584
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
585
+ "dark:hover:bg-accent/50"
586
+ ].join(" "),
587
+ // Link variant - full customization
588
+ link: [
589
+ "bg-[var(--button-link-bg,transparent)]",
590
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
591
+ "border-[length:var(--button-link-border-width,0px)]",
592
+ "border-[color:var(--button-link-border,transparent)]",
593
+ "[box-shadow:var(--button-link-shadow,none)]",
594
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
595
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
596
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
597
+ "underline-offset-4 hover:underline"
598
+ ].join(" ")
599
+ },
600
+ size: {
601
+ default: [
602
+ "h-[var(--button-height-md,2.25rem)]",
603
+ "px-[var(--button-padding-x-md,1rem)]",
604
+ "py-[var(--button-padding-y-md,0.5rem)]",
605
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
606
+ ].join(" "),
607
+ sm: [
608
+ "h-[var(--button-height-sm,2rem)]",
609
+ "px-[var(--button-padding-x-sm,0.75rem)]",
610
+ "py-[var(--button-padding-y-sm,0.25rem)]",
611
+ "gap-1.5",
612
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
613
+ ].join(" "),
614
+ md: [
615
+ "h-[var(--button-height-md,2.25rem)]",
616
+ "px-[var(--button-padding-x-md,1rem)]",
617
+ "py-[var(--button-padding-y-md,0.5rem)]",
618
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
619
+ ].join(" "),
620
+ lg: [
621
+ "h-[var(--button-height-lg,2.5rem)]",
622
+ "px-[var(--button-padding-x-lg,1.5rem)]",
623
+ "py-[var(--button-padding-y-lg,0.5rem)]",
624
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
625
+ ].join(" "),
626
+ icon: "size-[var(--button-height-md,2.25rem)]",
627
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
628
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
629
+ }
630
+ },
631
+ defaultVariants: {
632
+ variant: "default",
633
+ size: "default"
634
+ }
635
+ });
636
+ function normalizePhoneNumber(input) {
637
+ const trimmed = input.trim();
638
+ if (trimmed.toLowerCase().startsWith("tel:")) {
639
+ return trimmed;
640
+ }
641
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
642
+ if (match) {
643
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
644
+ const extension = match[3];
645
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
646
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
647
+ return `tel:${withExtension}`;
648
+ }
649
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
650
+ return `tel:${cleaned}`;
651
+ }
652
+ function normalizeEmail(input) {
653
+ const trimmed = input.trim();
654
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
655
+ return trimmed;
656
+ }
657
+ return `mailto:${trimmed}`;
658
+ }
659
+ function isEmail(input) {
660
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
661
+ return emailRegex.test(input.trim());
662
+ }
663
+ function isPhoneNumber(input) {
664
+ const trimmed = input.trim();
665
+ if (trimmed.toLowerCase().startsWith("tel:")) {
666
+ return true;
667
+ }
668
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
669
+ return phoneRegex.test(trimmed);
670
+ }
671
+ function isInternalUrl(href) {
672
+ if (typeof window === "undefined") {
673
+ return href.startsWith("/") && !href.startsWith("//");
674
+ }
675
+ const trimmed = href.trim();
676
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
677
+ return true;
678
+ }
679
+ try {
680
+ const url = new URL(trimmed, window.location.href);
681
+ const currentOrigin = window.location.origin;
682
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
683
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
684
+ } catch {
685
+ return false;
686
+ }
687
+ }
688
+ function toRelativePath(href) {
689
+ if (typeof window === "undefined") {
690
+ return href;
691
+ }
692
+ const trimmed = href.trim();
693
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
694
+ return trimmed;
695
+ }
696
+ try {
697
+ const url = new URL(trimmed, window.location.href);
698
+ const currentOrigin = window.location.origin;
699
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
700
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
701
+ return url.pathname + url.search + url.hash;
702
+ }
703
+ } catch {
704
+ }
705
+ return trimmed;
706
+ }
707
+ function useNavigation({
708
+ href,
709
+ onClick
710
+ } = {}) {
711
+ const linkType = React.useMemo(() => {
712
+ if (!href || href.trim() === "") {
713
+ return onClick ? "none" : "none";
714
+ }
715
+ const trimmed = href.trim();
716
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
717
+ return "mailto";
718
+ }
719
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
720
+ return "tel";
721
+ }
722
+ if (isInternalUrl(trimmed)) {
723
+ return "internal";
724
+ }
725
+ try {
726
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
727
+ return "external";
728
+ } catch {
729
+ return "internal";
730
+ }
731
+ }, [href, onClick]);
732
+ const normalizedHref = React.useMemo(() => {
733
+ if (!href || href.trim() === "") {
734
+ return void 0;
735
+ }
736
+ const trimmed = href.trim();
737
+ switch (linkType) {
738
+ case "tel":
739
+ return normalizePhoneNumber(trimmed);
740
+ case "mailto":
741
+ return normalizeEmail(trimmed);
742
+ case "internal":
743
+ return toRelativePath(trimmed);
744
+ case "external":
745
+ return trimmed;
746
+ default:
747
+ return trimmed;
748
+ }
749
+ }, [href, linkType]);
750
+ const target = React.useMemo(() => {
751
+ switch (linkType) {
752
+ case "external":
753
+ return "_blank";
754
+ case "internal":
755
+ return "_self";
756
+ case "mailto":
757
+ case "tel":
758
+ return void 0;
759
+ default:
760
+ return void 0;
761
+ }
762
+ }, [linkType]);
763
+ const rel = React.useMemo(() => {
764
+ if (linkType === "external") {
765
+ return "noopener noreferrer";
766
+ }
767
+ return void 0;
768
+ }, [linkType]);
769
+ const isExternal = linkType === "external";
770
+ const isInternal = linkType === "internal";
771
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
772
+ const handleClick = React.useCallback(
773
+ (event) => {
774
+ if (onClick) {
775
+ try {
776
+ onClick(event);
777
+ } catch (error) {
778
+ console.error("Error in user onClick handler:", error);
779
+ }
780
+ }
781
+ if (event.defaultPrevented) {
782
+ return;
783
+ }
784
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
785
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
786
+ if (typeof window !== "undefined") {
787
+ const handler = window.__opensiteNavigationHandler;
788
+ if (typeof handler === "function") {
789
+ try {
790
+ const handled = handler(normalizedHref, event.nativeEvent || event);
791
+ if (handled !== false) {
792
+ event.preventDefault();
793
+ }
794
+ } catch (error) {
795
+ console.error("Error in navigation handler:", error);
796
+ }
797
+ }
798
+ }
799
+ }
800
+ },
801
+ [onClick, shouldUseRouter, normalizedHref]
802
+ );
803
+ return {
804
+ linkType,
805
+ normalizedHref,
806
+ target,
807
+ rel,
808
+ isExternal,
809
+ isInternal,
810
+ shouldUseRouter,
811
+ handleClick
812
+ };
813
+ }
814
+ var Pressable = React.forwardRef(
815
+ ({
816
+ children,
817
+ className,
818
+ href,
819
+ onClick,
820
+ variant,
821
+ size,
822
+ asButton = false,
823
+ fallbackComponentType = "span",
824
+ componentType,
825
+ "aria-label": ariaLabel,
826
+ "aria-describedby": ariaDescribedby,
827
+ id,
828
+ ...props
829
+ }, ref) => {
830
+ const navigation = useNavigation({ href, onClick });
831
+ const {
832
+ normalizedHref,
833
+ target,
834
+ rel,
835
+ linkType,
836
+ isInternal,
837
+ handleClick
838
+ } = navigation;
839
+ const shouldRenderLink = normalizedHref && linkType !== "none";
840
+ const shouldRenderButton = !shouldRenderLink && onClick;
841
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
842
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
843
+ const shouldApplyButtonStyles = asButton || variant || size;
844
+ const combinedClassName = cn(
845
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
846
+ className
847
+ );
848
+ const dataProps = Object.fromEntries(
849
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
850
+ );
851
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
852
+ "data-slot": "button",
853
+ "data-variant": variant ?? "default",
854
+ "data-size": size ?? "default"
855
+ } : {};
856
+ const commonProps = {
857
+ className: combinedClassName,
858
+ onClick: handleClick,
859
+ "aria-label": ariaLabel,
860
+ "aria-describedby": ariaDescribedby,
861
+ id,
862
+ ...dataProps,
863
+ ...buttonDataAttributes
864
+ };
865
+ if (finalComponentType === "a" && shouldRenderLink) {
866
+ return /* @__PURE__ */ jsx(
867
+ "a",
868
+ {
869
+ ref,
870
+ href: normalizedHref,
871
+ target,
872
+ rel,
873
+ ...commonProps,
874
+ ...props,
875
+ children
876
+ }
877
+ );
878
+ }
879
+ if (finalComponentType === "button") {
880
+ return /* @__PURE__ */ jsx(
881
+ "button",
882
+ {
883
+ ref,
884
+ type: props.type || "button",
885
+ ...commonProps,
886
+ ...props,
887
+ children
888
+ }
889
+ );
890
+ }
891
+ if (finalComponentType === "div") {
892
+ return /* @__PURE__ */ jsx(
893
+ "div",
894
+ {
895
+ ref,
896
+ ...commonProps,
897
+ children
898
+ }
899
+ );
900
+ }
901
+ return /* @__PURE__ */ jsx(
902
+ "span",
903
+ {
904
+ ref,
905
+ ...commonProps,
906
+ children
907
+ }
908
+ );
909
+ }
910
+ );
911
+ Pressable.displayName = "Pressable";
493
912
  function FeatureNumberedCards({
913
+ title,
914
+ description,
494
915
  features,
495
916
  featuresSlot,
496
917
  className,
497
- containerClassName,
918
+ containerClassName = "px-6 sm:px-6 md:mx-6 lg:px-8",
498
919
  cardsWrapperClassName,
499
920
  cardClassName,
500
921
  titleClassName,
@@ -503,7 +924,7 @@ function FeatureNumberedCards({
503
924
  badgeClassName,
504
925
  optixFlowConfig,
505
926
  background,
506
- spacing,
927
+ spacing = "py-6 md:py-32",
507
928
  pattern,
508
929
  patternOpacity,
509
930
  patternClassName
@@ -547,32 +968,61 @@ function FeatureNumberedCards({
547
968
  },
548
969
  []
549
970
  );
971
+ const actionsContent = useCallback(
972
+ (args) => {
973
+ if (args?.actionsSlot) return args.actionsSlot;
974
+ if (!args?.actions || args.actions.length === 0) return null;
975
+ return args.actions.map((action, index) => {
976
+ const {
977
+ label,
978
+ icon,
979
+ iconAfter,
980
+ children,
981
+ className: actionClassName,
982
+ ...pressableProps
983
+ } = action;
984
+ return /* @__PURE__ */ jsx(
985
+ Pressable,
986
+ {
987
+ asButton: true,
988
+ className: actionClassName,
989
+ ...pressableProps,
990
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
991
+ icon,
992
+ label,
993
+ iconAfter
994
+ ] })
995
+ },
996
+ index
997
+ );
998
+ });
999
+ },
1000
+ []
1001
+ );
1002
+ const cardImg = useCallback((feature) => {
1003
+ if (!feature.image || !feature.imageSlot) return null;
1004
+ if (feature.imageSlot) return feature.imageSlot;
1005
+ const imageAlt = feature.imageAlt || (typeof feature.title === "string" ? feature.title : "Feature image");
1006
+ return /* @__PURE__ */ jsx("div", { className: "overflow-hidden h-full w-full rounded-t-lg rounded-b-none md:rounded-t-none md:rounded-l-none md:rounded-r-lg", children: /* @__PURE__ */ jsx(
1007
+ Img,
1008
+ {
1009
+ src: feature.image,
1010
+ alt: imageAlt,
1011
+ className: "h-full w-full object-cover",
1012
+ loading: "lazy",
1013
+ optixFlowConfig
1014
+ }
1015
+ ) });
1016
+ }, []);
550
1017
  const featuresContent = useMemo(() => {
551
1018
  if (featuresSlot) return featuresSlot;
552
1019
  if (!features || features.length === 0) return null;
553
1020
  return features.map((feature, index) => {
554
- const imageAlt = feature.imageAlt || (typeof feature.title === "string" ? feature.title : "Feature image");
555
- const renderImage = () => {
556
- if (feature.imageSlot) return feature.imageSlot;
557
- if (feature.image) {
558
- return /* @__PURE__ */ jsx(
559
- Img,
560
- {
561
- src: feature.image,
562
- alt: imageAlt,
563
- className: "h-full w-full object-cover rounded-tr-lg rounded-tl-lg md:rounded-tl-0 rounded-br-0 md:rounded-br-lg",
564
- loading: "lazy",
565
- optixFlowConfig
566
- }
567
- );
568
- }
569
- return null;
570
- };
571
1021
  return /* @__PURE__ */ jsxs(
572
1022
  "div",
573
1023
  {
574
1024
  className: cn(
575
- "grid rounded-lg border md:grid-cols-2",
1025
+ "grid rounded-lg border md:grid-cols-2 bg-background text-foreground",
576
1026
  cardClassName,
577
1027
  feature.className
578
1028
  ),
@@ -581,7 +1031,7 @@ function FeatureNumberedCards({
581
1031
  "div",
582
1032
  {
583
1033
  className: cn(
584
- "flex flex-col px-6 py-8 lg:px-8 lg:py-12 xl:px-12 xl:py-20",
1034
+ "flex flex-col px-4 py-4 lg:px-8 lg:py-12 xl:px-12 xl:py-20",
585
1035
  feature.contentClassName
586
1036
  ),
587
1037
  children: [
@@ -589,7 +1039,7 @@ function FeatureNumberedCards({
589
1039
  "h3",
590
1040
  {
591
1041
  className: cn(
592
- "mb-3 text-2xl font-medium sm:mb-5 md:text-3xl lg:text-4xl",
1042
+ "mb-3 text-lg font-medium sm:mb-5 md:text-xl lg:text-2xl",
593
1043
  titleClassName
594
1044
  ),
595
1045
  children: feature.title
@@ -598,7 +1048,7 @@ function FeatureNumberedCards({
598
1048
  "div",
599
1049
  {
600
1050
  className: cn(
601
- "mb-3 text-2xl font-medium sm:mb-5 md:text-3xl lg:text-4xl",
1051
+ "mb-3 text-lg font-medium sm:mb-5 md:text-xl lg:text-2xl",
602
1052
  titleClassName
603
1053
  ),
604
1054
  children: feature.title
@@ -632,7 +1082,14 @@ function FeatureNumberedCards({
632
1082
  ),
633
1083
  children: renderChecklistItems(feature)
634
1084
  }
635
- ) : null
1085
+ ) : null,
1086
+ actionsContent({
1087
+ actions: feature.actions,
1088
+ actionsSlot: feature.actionsSlot
1089
+ }) && /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-4 md:gap-2", children: actionsContent({
1090
+ actions: feature.actions,
1091
+ actionsSlot: feature.actionsSlot
1092
+ }) })
636
1093
  ]
637
1094
  }
638
1095
  ),
@@ -644,7 +1101,7 @@ function FeatureNumberedCards({
644
1101
  feature.imageWrapperClassName
645
1102
  ),
646
1103
  children: [
647
- renderImage(),
1104
+ cardImg(feature),
648
1105
  /* @__PURE__ */ jsx(
649
1106
  "span",
650
1107
  {
@@ -683,16 +1140,43 @@ function FeatureNumberedCards({
683
1140
  patternClassName,
684
1141
  className,
685
1142
  containerClassName,
686
- children: /* @__PURE__ */ jsx(
687
- "div",
688
- {
689
- className: cn(
690
- "space-y-4 md:space-y-10 rounded-lg border-none md:border p-0 md:p-10",
691
- cardsWrapperClassName
692
- ),
693
- children: featuresContent
694
- }
695
- )
1143
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-6 md:space-y-16", children: [
1144
+ title || description ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
1145
+ title && (typeof title === "string" ? /* @__PURE__ */ jsx(
1146
+ "h2",
1147
+ {
1148
+ className: cn(
1149
+ "text-xl font-medium tracking-tight md:text-2xl lg:text-3xl text-balance",
1150
+ titleClassName
1151
+ ),
1152
+ children: title
1153
+ }
1154
+ ) : /* @__PURE__ */ jsx("div", { className: titleClassName, children: title })),
1155
+ description && (typeof description === "string" ? /* @__PURE__ */ jsx(
1156
+ "p",
1157
+ {
1158
+ className: cn("max-w-lg text-balance", descriptionClassName),
1159
+ children: description
1160
+ }
1161
+ ) : /* @__PURE__ */ jsx(
1162
+ "div",
1163
+ {
1164
+ className: cn("max-w-lg text-balance", descriptionClassName),
1165
+ children: description
1166
+ }
1167
+ ))
1168
+ ] }) : null,
1169
+ /* @__PURE__ */ jsx(
1170
+ "div",
1171
+ {
1172
+ className: cn(
1173
+ "space-y-4 md:space-y-10 rounded-lg border-none md:border p-0 md:p-10",
1174
+ cardsWrapperClassName
1175
+ ),
1176
+ children: featuresContent
1177
+ }
1178
+ )
1179
+ ] })
696
1180
  }
697
1181
  );
698
1182
  }
@@ -834,7 +834,7 @@ function FeatureSplitImage({
834
834
  actions,
835
835
  actionsSlot,
836
836
  className,
837
- containerClassName,
837
+ containerClassName = "px-4 sm:px-4 md:px-6 lg:px-8",
838
838
  gridClassName,
839
839
  contentClassName,
840
840
  titleClassName,
@@ -813,7 +813,7 @@ function FeatureSplitImage({
813
813
  actions,
814
814
  actionsSlot,
815
815
  className,
816
- containerClassName,
816
+ containerClassName = "px-4 sm:px-4 md:px-6 lg:px-8",
817
817
  gridClassName,
818
818
  contentClassName,
819
819
  titleClassName,