@opensite/ui 2.8.5 → 2.8.7

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 (141) hide show
  1. package/dist/about-developer-profile.cjs +17 -10
  2. package/dist/about-developer-profile.js +17 -10
  3. package/dist/article-chapters-author.cjs +17 -10
  4. package/dist/article-chapters-author.js +17 -10
  5. package/dist/carousel-animated-sections.cjs +79 -25
  6. package/dist/carousel-animated-sections.d.cts +7 -2
  7. package/dist/carousel-animated-sections.d.ts +7 -2
  8. package/dist/carousel-animated-sections.js +79 -25
  9. package/dist/carousel-gallery-thumbnails.cjs +79 -25
  10. package/dist/carousel-gallery-thumbnails.d.cts +7 -2
  11. package/dist/carousel-gallery-thumbnails.d.ts +7 -2
  12. package/dist/carousel-gallery-thumbnails.js +79 -25
  13. package/dist/carousel-portfolio-hero.cjs +79 -25
  14. package/dist/carousel-portfolio-hero.d.cts +7 -2
  15. package/dist/carousel-portfolio-hero.d.ts +7 -2
  16. package/dist/carousel-portfolio-hero.js +79 -25
  17. package/dist/components.cjs +35 -10
  18. package/dist/components.d.cts +29 -2
  19. package/dist/components.d.ts +29 -2
  20. package/dist/components.js +35 -11
  21. package/dist/footer-accordion-social.cjs +17 -10
  22. package/dist/footer-accordion-social.js +17 -10
  23. package/dist/footer-animated-social.cjs +17 -10
  24. package/dist/footer-animated-social.js +17 -10
  25. package/dist/footer-brand-description.cjs +17 -10
  26. package/dist/footer-brand-description.js +17 -10
  27. package/dist/footer-brand-links-contact.cjs +17 -10
  28. package/dist/footer-brand-links-contact.js +17 -10
  29. package/dist/footer-comprehensive-links.cjs +17 -10
  30. package/dist/footer-comprehensive-links.js +17 -10
  31. package/dist/footer-contact-card.cjs +17 -10
  32. package/dist/footer-contact-card.js +17 -10
  33. package/dist/footer-cta-banner.cjs +17 -10
  34. package/dist/footer-cta-banner.js +17 -10
  35. package/dist/footer-cta-social.cjs +17 -10
  36. package/dist/footer-cta-social.js +17 -10
  37. package/dist/footer-info-cards-accordion.cjs +17 -10
  38. package/dist/footer-info-cards-accordion.js +17 -10
  39. package/dist/footer-nav-social.cjs +17 -10
  40. package/dist/footer-nav-social.js +17 -10
  41. package/dist/footer-newsletter-contact.cjs +17 -10
  42. package/dist/footer-newsletter-contact.js +17 -10
  43. package/dist/footer-newsletter-grid.cjs +17 -10
  44. package/dist/footer-newsletter-grid.js +17 -10
  45. package/dist/footer-newsletter-minimal.cjs +17 -10
  46. package/dist/footer-newsletter-minimal.js +17 -10
  47. package/dist/footer-social-apps.cjs +17 -10
  48. package/dist/footer-social-apps.js +17 -10
  49. package/dist/footer-social-newsletter.cjs +17 -10
  50. package/dist/footer-social-newsletter.js +17 -10
  51. package/dist/footer-split-image-accordion.cjs +17 -10
  52. package/dist/footer-split-image-accordion.js +17 -10
  53. package/dist/hero-badge-shadow-overlay.cjs +1 -1
  54. package/dist/hero-badge-shadow-overlay.js +1 -1
  55. package/dist/hero-coming-soon-countdown.cjs +17 -10
  56. package/dist/hero-coming-soon-countdown.js +17 -10
  57. package/dist/hero-video-background-dark.cjs +78 -16
  58. package/dist/hero-video-background-dark.d.cts +7 -2
  59. package/dist/hero-video-background-dark.d.ts +7 -2
  60. package/dist/hero-video-background-dark.js +78 -16
  61. package/dist/index.cjs +35 -10
  62. package/dist/index.d.cts +1 -0
  63. package/dist/index.d.ts +1 -0
  64. package/dist/index.js +35 -11
  65. package/dist/link-page-bento-layout.cjs +17 -10
  66. package/dist/link-page-bento-layout.js +17 -10
  67. package/dist/link-page-grid-cards.cjs +17 -10
  68. package/dist/link-page-grid-cards.js +17 -10
  69. package/dist/link-page-minimal-profile.cjs +17 -10
  70. package/dist/link-page-minimal-profile.js +17 -10
  71. package/dist/link-page-newsletter-social.cjs +17 -10
  72. package/dist/link-page-newsletter-social.js +17 -10
  73. package/dist/link-tree-block.cjs +17 -10
  74. package/dist/link-tree-block.js +17 -10
  75. package/dist/navbar-fullscreen-menu.cjs +17 -10
  76. package/dist/navbar-fullscreen-menu.js +17 -10
  77. package/dist/navbar-transparent-overlay.cjs +17 -10
  78. package/dist/navbar-transparent-overlay.js +17 -10
  79. package/dist/registry.cjs +1398 -851
  80. package/dist/registry.js +1398 -851
  81. package/dist/social-link-icon.cjs +17 -10
  82. package/dist/social-link-icon.d.cts +5 -0
  83. package/dist/social-link-icon.d.ts +5 -0
  84. package/dist/social-link-icon.js +17 -10
  85. package/dist/testimonials-animated-split.cjs +5 -5
  86. package/dist/testimonials-animated-split.js +5 -5
  87. package/dist/testimonials-bento-grid.cjs +48 -56
  88. package/dist/testimonials-bento-grid.js +48 -56
  89. package/dist/testimonials-carousel-image.cjs +608 -96
  90. package/dist/testimonials-carousel-image.d.cts +26 -2
  91. package/dist/testimonials-carousel-image.d.ts +26 -2
  92. package/dist/testimonials-carousel-image.js +609 -97
  93. package/dist/testimonials-centered-avatars.cjs +89 -62
  94. package/dist/testimonials-centered-avatars.d.cts +5 -1
  95. package/dist/testimonials-centered-avatars.d.ts +5 -1
  96. package/dist/testimonials-centered-avatars.js +89 -62
  97. package/dist/testimonials-company-logo.cjs +6 -6
  98. package/dist/testimonials-company-logo.js +6 -6
  99. package/dist/testimonials-grid-add-review.cjs +51 -29
  100. package/dist/testimonials-grid-add-review.js +51 -29
  101. package/dist/testimonials-images-helpful.cjs +181 -160
  102. package/dist/testimonials-images-helpful.d.cts +9 -1
  103. package/dist/testimonials-images-helpful.d.ts +9 -1
  104. package/dist/testimonials-images-helpful.js +181 -159
  105. package/dist/testimonials-list-verified.cjs +63 -44
  106. package/dist/testimonials-list-verified.d.cts +5 -1
  107. package/dist/testimonials-list-verified.d.ts +5 -1
  108. package/dist/testimonials-list-verified.js +64 -45
  109. package/dist/testimonials-logo-cards.cjs +53 -29
  110. package/dist/testimonials-logo-cards.d.cts +5 -1
  111. package/dist/testimonials-logo-cards.d.ts +5 -1
  112. package/dist/testimonials-logo-cards.js +53 -29
  113. package/dist/testimonials-marquee.cjs +524 -102
  114. package/dist/testimonials-marquee.d.cts +5 -1
  115. package/dist/testimonials-marquee.d.ts +5 -1
  116. package/dist/testimonials-marquee.js +525 -100
  117. package/dist/testimonials-mini-dividers.cjs +120 -83
  118. package/dist/testimonials-mini-dividers.d.cts +10 -6
  119. package/dist/testimonials-mini-dividers.d.ts +10 -6
  120. package/dist/testimonials-mini-dividers.js +120 -83
  121. package/dist/testimonials-minimal-numbered.cjs +7 -6
  122. package/dist/testimonials-minimal-numbered.d.cts +5 -1
  123. package/dist/testimonials-minimal-numbered.d.ts +5 -1
  124. package/dist/testimonials-minimal-numbered.js +7 -6
  125. package/dist/testimonials-parallax-number.cjs +14 -8
  126. package/dist/testimonials-parallax-number.js +14 -8
  127. package/dist/testimonials-scrolling-columns.cjs +97 -13
  128. package/dist/testimonials-scrolling-columns.js +97 -13
  129. package/dist/testimonials-simple-grid.cjs +513 -68
  130. package/dist/testimonials-simple-grid.d.cts +9 -5
  131. package/dist/testimonials-simple-grid.d.ts +9 -5
  132. package/dist/testimonials-simple-grid.js +510 -62
  133. package/dist/testimonials-slider-minimal.cjs +604 -90
  134. package/dist/testimonials-slider-minimal.d.cts +17 -1
  135. package/dist/testimonials-slider-minimal.d.ts +17 -1
  136. package/dist/testimonials-slider-minimal.js +598 -81
  137. package/dist/testimonials-split-image.cjs +452 -17
  138. package/dist/testimonials-split-image.js +448 -13
  139. package/dist/testimonials-twitter-cards.cjs +26 -14
  140. package/dist/testimonials-twitter-cards.js +26 -14
  141. package/package.json +11 -1
@@ -1,13 +1,12 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React = require('react');
4
+ var React3 = require('react');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var AvatarPrimitive = require('@radix-ui/react-avatar');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
-
10
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+ var classVarianceAuthority = require('class-variance-authority');
11
10
 
12
11
  function _interopNamespace(e) {
13
12
  if (e && e.__esModule) return e;
@@ -27,7 +26,7 @@ function _interopNamespace(e) {
27
26
  return Object.freeze(n);
28
27
  }
29
28
 
30
- var React__default = /*#__PURE__*/_interopDefault(React);
29
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
31
30
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
32
31
 
33
32
  // components/blocks/testimonials/testimonials-simple-grid.tsx
@@ -79,19 +78,6 @@ function AvatarFallback({
79
78
  }
80
79
  );
81
80
  }
82
- function Card({ className, ...props }) {
83
- return /* @__PURE__ */ jsxRuntime.jsx(
84
- "div",
85
- {
86
- "data-slot": "card",
87
- className: cn(
88
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
89
- className
90
- ),
91
- ...props
92
- }
93
- );
94
- }
95
81
  function CardContent({ className, ...props }) {
96
82
  return /* @__PURE__ */ jsxRuntime.jsx(
97
83
  "div",
@@ -111,7 +97,7 @@ var maxWidthStyles = {
111
97
  "4xl": "max-w-[1536px]",
112
98
  full: "max-w-full"
113
99
  };
114
- var Container = React__default.default.forwardRef(
100
+ var Container = React3__namespace.default.forwardRef(
115
101
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
116
102
  const Component = as;
117
103
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -417,7 +403,7 @@ var spacingStyles = {
417
403
  };
418
404
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
419
405
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
420
- var Section = React__default.default.forwardRef(
406
+ var Section = React3__namespace.default.forwardRef(
421
407
  ({
422
408
  id,
423
409
  title,
@@ -478,6 +464,424 @@ var Section = React__default.default.forwardRef(
478
464
  }
479
465
  );
480
466
  Section.displayName = "Section";
467
+ function normalizePhoneNumber(input) {
468
+ const trimmed = input.trim();
469
+ if (trimmed.toLowerCase().startsWith("tel:")) {
470
+ return trimmed;
471
+ }
472
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
473
+ if (match) {
474
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
475
+ const extension = match[3];
476
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
477
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
478
+ return `tel:${withExtension}`;
479
+ }
480
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
481
+ return `tel:${cleaned}`;
482
+ }
483
+ function normalizeEmail(input) {
484
+ const trimmed = input.trim();
485
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
486
+ return trimmed;
487
+ }
488
+ return `mailto:${trimmed}`;
489
+ }
490
+ function isEmail(input) {
491
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
492
+ return emailRegex.test(input.trim());
493
+ }
494
+ function isPhoneNumber(input) {
495
+ const trimmed = input.trim();
496
+ if (trimmed.toLowerCase().startsWith("tel:")) {
497
+ return true;
498
+ }
499
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
500
+ return phoneRegex.test(trimmed);
501
+ }
502
+ function isInternalUrl(href) {
503
+ if (typeof window === "undefined") {
504
+ return href.startsWith("/") && !href.startsWith("//");
505
+ }
506
+ const trimmed = href.trim();
507
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
508
+ return true;
509
+ }
510
+ try {
511
+ const url = new URL(trimmed, window.location.href);
512
+ const currentOrigin = window.location.origin;
513
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
514
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
515
+ } catch {
516
+ return false;
517
+ }
518
+ }
519
+ function toRelativePath(href) {
520
+ if (typeof window === "undefined") {
521
+ return href;
522
+ }
523
+ const trimmed = href.trim();
524
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
525
+ return trimmed;
526
+ }
527
+ try {
528
+ const url = new URL(trimmed, window.location.href);
529
+ const currentOrigin = window.location.origin;
530
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
531
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
532
+ return url.pathname + url.search + url.hash;
533
+ }
534
+ } catch {
535
+ }
536
+ return trimmed;
537
+ }
538
+ function useNavigation({
539
+ href,
540
+ onClick
541
+ } = {}) {
542
+ const linkType = React3__namespace.useMemo(() => {
543
+ if (!href || href.trim() === "") {
544
+ return onClick ? "none" : "none";
545
+ }
546
+ const trimmed = href.trim();
547
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
548
+ return "mailto";
549
+ }
550
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
551
+ return "tel";
552
+ }
553
+ if (isInternalUrl(trimmed)) {
554
+ return "internal";
555
+ }
556
+ try {
557
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
558
+ return "external";
559
+ } catch {
560
+ return "internal";
561
+ }
562
+ }, [href, onClick]);
563
+ const normalizedHref = React3__namespace.useMemo(() => {
564
+ if (!href || href.trim() === "") {
565
+ return void 0;
566
+ }
567
+ const trimmed = href.trim();
568
+ switch (linkType) {
569
+ case "tel":
570
+ return normalizePhoneNumber(trimmed);
571
+ case "mailto":
572
+ return normalizeEmail(trimmed);
573
+ case "internal":
574
+ return toRelativePath(trimmed);
575
+ case "external":
576
+ return trimmed;
577
+ default:
578
+ return trimmed;
579
+ }
580
+ }, [href, linkType]);
581
+ const target = React3__namespace.useMemo(() => {
582
+ switch (linkType) {
583
+ case "external":
584
+ return "_blank";
585
+ case "internal":
586
+ return "_self";
587
+ case "mailto":
588
+ case "tel":
589
+ return void 0;
590
+ default:
591
+ return void 0;
592
+ }
593
+ }, [linkType]);
594
+ const rel = React3__namespace.useMemo(() => {
595
+ if (linkType === "external") {
596
+ return "noopener noreferrer";
597
+ }
598
+ return void 0;
599
+ }, [linkType]);
600
+ const isExternal = linkType === "external";
601
+ const isInternal = linkType === "internal";
602
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
603
+ const handleClick = React3__namespace.useCallback(
604
+ (event) => {
605
+ if (onClick) {
606
+ try {
607
+ onClick(event);
608
+ } catch (error) {
609
+ console.error("Error in user onClick handler:", error);
610
+ }
611
+ }
612
+ if (event.defaultPrevented) {
613
+ return;
614
+ }
615
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
616
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
617
+ if (typeof window !== "undefined") {
618
+ const handler = window.__opensiteNavigationHandler;
619
+ if (typeof handler === "function") {
620
+ try {
621
+ const handled = handler(normalizedHref, event.nativeEvent || event);
622
+ if (handled !== false) {
623
+ event.preventDefault();
624
+ }
625
+ } catch (error) {
626
+ console.error("Error in navigation handler:", error);
627
+ }
628
+ }
629
+ }
630
+ }
631
+ },
632
+ [onClick, shouldUseRouter, normalizedHref]
633
+ );
634
+ return {
635
+ linkType,
636
+ normalizedHref,
637
+ target,
638
+ rel,
639
+ isExternal,
640
+ isInternal,
641
+ shouldUseRouter,
642
+ handleClick
643
+ };
644
+ }
645
+ var baseStyles = [
646
+ // Layout
647
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
648
+ // Typography - using CSS variables with sensible defaults
649
+ "font-[var(--button-font-family,inherit)]",
650
+ "font-[var(--button-font-weight,500)]",
651
+ "tracking-[var(--button-letter-spacing,0)]",
652
+ "leading-[var(--button-line-height,1.25)]",
653
+ "[text-transform:var(--button-text-transform,none)]",
654
+ "text-sm",
655
+ // Border radius
656
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
657
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
658
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
659
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
660
+ "[box-shadow:var(--button-shadow,none)]",
661
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
662
+ // Disabled state
663
+ "disabled:pointer-events-none disabled:opacity-50",
664
+ // SVG handling
665
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
666
+ // Focus styles
667
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
668
+ // Invalid state
669
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
670
+ ].join(" ");
671
+ var buttonVariants = classVarianceAuthority.cva(baseStyles, {
672
+ variants: {
673
+ variant: {
674
+ // Default (Primary) variant - full customization
675
+ default: [
676
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
677
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
678
+ "border-[length:var(--button-default-border-width,0px)]",
679
+ "border-[color:var(--button-default-border,transparent)]",
680
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
681
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
682
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
683
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
684
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
685
+ ].join(" "),
686
+ // Destructive variant - full customization
687
+ destructive: [
688
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
689
+ "text-[var(--button-destructive-fg,white)]",
690
+ "border-[length:var(--button-destructive-border-width,0px)]",
691
+ "border-[color:var(--button-destructive-border,transparent)]",
692
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
693
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
694
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
695
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
696
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
697
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
698
+ "dark:bg-destructive/60"
699
+ ].join(" "),
700
+ // Outline variant - full customization with proper border handling
701
+ outline: [
702
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
703
+ "text-[var(--button-outline-fg,inherit)]",
704
+ "border-[length:var(--button-outline-border-width,1px)]",
705
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
706
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
707
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
708
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
709
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
710
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
711
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
712
+ ].join(" "),
713
+ // Secondary variant - full customization
714
+ secondary: [
715
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
716
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
717
+ "border-[length:var(--button-secondary-border-width,0px)]",
718
+ "border-[color:var(--button-secondary-border,transparent)]",
719
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
720
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
721
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
722
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
723
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
724
+ ].join(" "),
725
+ // Ghost variant - full customization
726
+ ghost: [
727
+ "bg-[var(--button-ghost-bg,transparent)]",
728
+ "text-[var(--button-ghost-fg,inherit)]",
729
+ "border-[length:var(--button-ghost-border-width,0px)]",
730
+ "border-[color:var(--button-ghost-border,transparent)]",
731
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
732
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
733
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
734
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
735
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
736
+ "dark:hover:bg-accent/50"
737
+ ].join(" "),
738
+ // Link variant - full customization
739
+ link: [
740
+ "bg-[var(--button-link-bg,transparent)]",
741
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
742
+ "border-[length:var(--button-link-border-width,0px)]",
743
+ "border-[color:var(--button-link-border,transparent)]",
744
+ "[box-shadow:var(--button-link-shadow,none)]",
745
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
746
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
747
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
748
+ "underline-offset-4 hover:underline"
749
+ ].join(" ")
750
+ },
751
+ size: {
752
+ default: [
753
+ "h-[var(--button-height-md,2.25rem)]",
754
+ "px-[var(--button-padding-x-md,1rem)]",
755
+ "py-[var(--button-padding-y-md,0.5rem)]",
756
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
757
+ ].join(" "),
758
+ sm: [
759
+ "h-[var(--button-height-sm,2rem)]",
760
+ "px-[var(--button-padding-x-sm,0.75rem)]",
761
+ "py-[var(--button-padding-y-sm,0.25rem)]",
762
+ "gap-1.5",
763
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
764
+ ].join(" "),
765
+ md: [
766
+ "h-[var(--button-height-md,2.25rem)]",
767
+ "px-[var(--button-padding-x-md,1rem)]",
768
+ "py-[var(--button-padding-y-md,0.5rem)]",
769
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
770
+ ].join(" "),
771
+ lg: [
772
+ "h-[var(--button-height-lg,2.5rem)]",
773
+ "px-[var(--button-padding-x-lg,1.5rem)]",
774
+ "py-[var(--button-padding-y-lg,0.5rem)]",
775
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
776
+ ].join(" "),
777
+ icon: "size-[var(--button-height-md,2.25rem)]",
778
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
779
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
780
+ }
781
+ },
782
+ defaultVariants: {
783
+ variant: "default",
784
+ size: "default"
785
+ }
786
+ });
787
+ var Pressable = React3__namespace.forwardRef(
788
+ ({
789
+ children,
790
+ className,
791
+ href,
792
+ onClick,
793
+ variant,
794
+ size,
795
+ asButton = false,
796
+ fallbackComponentType = "span",
797
+ componentType,
798
+ "aria-label": ariaLabel,
799
+ "aria-describedby": ariaDescribedby,
800
+ id,
801
+ ...props
802
+ }, ref) => {
803
+ const navigation = useNavigation({ href, onClick });
804
+ const {
805
+ normalizedHref,
806
+ target,
807
+ rel,
808
+ linkType,
809
+ isInternal,
810
+ handleClick
811
+ } = navigation;
812
+ const shouldRenderLink = normalizedHref && linkType !== "none";
813
+ const shouldRenderButton = !shouldRenderLink && onClick;
814
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
815
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
816
+ const shouldApplyButtonStyles = asButton || variant || size;
817
+ const combinedClassName = cn(
818
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
819
+ className
820
+ );
821
+ const dataProps = Object.fromEntries(
822
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
823
+ );
824
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
825
+ "data-slot": "button",
826
+ "data-variant": variant ?? "default",
827
+ "data-size": size ?? "default"
828
+ } : {};
829
+ const commonProps = {
830
+ className: combinedClassName,
831
+ onClick: handleClick,
832
+ "aria-label": ariaLabel,
833
+ "aria-describedby": ariaDescribedby,
834
+ id,
835
+ ...dataProps,
836
+ ...buttonDataAttributes
837
+ };
838
+ if (finalComponentType === "a" && shouldRenderLink) {
839
+ return /* @__PURE__ */ jsxRuntime.jsx(
840
+ "a",
841
+ {
842
+ ref,
843
+ href: normalizedHref,
844
+ target,
845
+ rel,
846
+ ...commonProps,
847
+ ...props,
848
+ children
849
+ }
850
+ );
851
+ }
852
+ if (finalComponentType === "button") {
853
+ return /* @__PURE__ */ jsxRuntime.jsx(
854
+ "button",
855
+ {
856
+ ref,
857
+ type: props.type || "button",
858
+ ...commonProps,
859
+ ...props,
860
+ children
861
+ }
862
+ );
863
+ }
864
+ if (finalComponentType === "div") {
865
+ return /* @__PURE__ */ jsxRuntime.jsx(
866
+ "div",
867
+ {
868
+ ref,
869
+ ...commonProps,
870
+ children
871
+ }
872
+ );
873
+ }
874
+ return /* @__PURE__ */ jsxRuntime.jsx(
875
+ "span",
876
+ {
877
+ ref,
878
+ ...commonProps,
879
+ children
880
+ }
881
+ );
882
+ }
883
+ );
884
+ Pressable.displayName = "Pressable";
481
885
  function TestimonialsSimpleGrid({
482
886
  testimonials,
483
887
  testimonialsSlot,
@@ -488,6 +892,7 @@ function TestimonialsSimpleGrid({
488
892
  headerClassName,
489
893
  headingClassName,
490
894
  descriptionClassName,
895
+ cardContentClassName,
491
896
  gridClassName,
492
897
  cardClassName,
493
898
  quoteClassName,
@@ -498,78 +903,108 @@ function TestimonialsSimpleGrid({
498
903
  pattern,
499
904
  patternOpacity
500
905
  }) {
501
- const gridCols = {
502
- 2: "sm:grid-cols-2",
503
- 3: "sm:grid-cols-2 lg:grid-cols-3",
504
- 4: "sm:grid-cols-2 lg:grid-cols-4"
505
- };
506
- const effectiveColumns = columns || 3;
507
- const getAuthorName = React.useCallback((testimonial) => {
906
+ const getAuthorName = React3.useCallback((testimonial) => {
508
907
  if (typeof testimonial.author === "string") return testimonial.author;
509
908
  return "";
510
909
  }, []);
511
- const getAvatarSrc = React.useCallback(
910
+ React3.useCallback(
512
911
  (testimonial) => {
513
912
  return testimonial.avatarSrc || testimonial.avatar?.src;
514
913
  },
515
914
  []
516
915
  );
517
- const getInitials = React.useCallback((name) => {
916
+ const getInitials = React3.useCallback((name) => {
518
917
  return name.split(" ").map((n) => n[0]).join("");
519
918
  }, []);
520
- const renderedTestimonials = React.useMemo(() => {
919
+ const renderedTestimonials = React3.useMemo(() => {
521
920
  if (testimonialsSlot) return testimonialsSlot;
522
921
  if (!testimonials || testimonials.length === 0) return null;
523
922
  return /* @__PURE__ */ jsxRuntime.jsx(
524
923
  "div",
525
924
  {
526
- className: cn("grid gap-6", gridCols[effectiveColumns], gridClassName),
925
+ className: cn(
926
+ "grid gap-4 md:gap-6 lg:gap-8 md:grid-cols-2 lg:grid-cols-3",
927
+ gridClassName
928
+ ),
527
929
  children: testimonials.map((testimonial, index) => {
528
930
  const authorName = getAuthorName(testimonial);
529
- const avatarSrc = getAvatarSrc(testimonial);
530
- return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cardClassName, children: /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "p-6", children: [
531
- testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsxs(
532
- "p",
533
- {
534
- className: cn(
535
- "mb-6 text-sm leading-relaxed ",
536
- quoteClassName
537
- ),
538
- children: [
539
- "\u201C",
540
- testimonial.quote,
541
- "\u201D"
542
- ]
543
- }
544
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-6", quoteClassName), children: testimonial.quote })),
545
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-3", authorClassName), children: [
546
- /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-10", children: [
547
- /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
548
- /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: getInitials(authorName) })
549
- ] }),
550
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
551
- testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: testimonial.author }) : testimonial.author),
552
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs ", children: [
553
- testimonial.role && (typeof testimonial.role === "string" ? testimonial.role : null),
554
- testimonial.company && (typeof testimonial.company === "string" ? `, ${testimonial.company}` : null)
555
- ] })
556
- ] })
557
- ] })
558
- ] }) }, index);
931
+ return /* @__PURE__ */ jsxRuntime.jsx(
932
+ Pressable,
933
+ {
934
+ href: testimonial.linkConfig?.href,
935
+ className: cn(
936
+ "bg-card text-card-foreground",
937
+ "flex flex-col gap-6",
938
+ testimonial.linkConfig?.href ? "cursor-pointer hover:bg-black hover:text-white transition-all duration-500" : "",
939
+ "rounded-2xl py-0 shadow-xl group",
940
+ "ring-4 ring-ring",
941
+ cardClassName
942
+ ),
943
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
944
+ CardContent,
945
+ {
946
+ className: cn(
947
+ "px-0 h-full flex flex-col-reverse items-stretch justify-between gap-12",
948
+ cardContentClassName
949
+ ),
950
+ children: [
951
+ /* @__PURE__ */ jsxRuntime.jsx(
952
+ "div",
953
+ {
954
+ className: cn(
955
+ "flex items-center justify-between",
956
+ authorClassName
957
+ ),
958
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
959
+ /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "relative flex shrink-0 size-24 border-t-4 border-r-4 border-primary rounded-tr-xl rounded-tl-none rounded-br-none rounded-bl-none shadow-xl", children: [
960
+ /* @__PURE__ */ jsxRuntime.jsx(
961
+ AvatarImage,
962
+ {
963
+ src: testimonial.avatarSrc,
964
+ alt: authorName
965
+ }
966
+ ),
967
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: getInitials(authorName) })
968
+ ] }),
969
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 pt-2 pr-6 pb-2", children: [
970
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0", children: [
971
+ testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold leading-relaxed", children: testimonial.author }) : testimonial.author),
972
+ testimonial.role && (typeof testimonial.role === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base", children: testimonial.role }) : testimonial.role)
973
+ ] }),
974
+ testimonial.linkConfig?.href && /* @__PURE__ */ jsxRuntime.jsx(
975
+ Pressable,
976
+ {
977
+ href: testimonial.linkConfig.href,
978
+ className: cn(
979
+ "text-base transition-all duration-300",
980
+ "underline underline-offset-4",
981
+ testimonial.linkConfig.className
982
+ ),
983
+ children: testimonial.linkConfig.label
984
+ }
985
+ )
986
+ ] })
987
+ ] })
988
+ }
989
+ ),
990
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-6 md: pt-8 px-6 md:px-8", children: testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-relaxed", children: testimonial.quote }) : testimonial.quote) })
991
+ ]
992
+ }
993
+ )
994
+ },
995
+ index
996
+ );
559
997
  })
560
998
  }
561
999
  );
562
1000
  }, [
563
1001
  testimonialsSlot,
564
- gridCols,
565
- effectiveColumns,
566
1002
  gridClassName,
567
1003
  testimonials,
568
1004
  cardClassName,
569
- quoteClassName,
1005
+ cardContentClassName,
570
1006
  authorClassName,
571
1007
  getAuthorName,
572
- getAvatarSrc,
573
1008
  getInitials
574
1009
  ]);
575
1010
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -585,19 +1020,29 @@ function TestimonialsSimpleGrid({
585
1020
  /* @__PURE__ */ jsxRuntime.jsxs(
586
1021
  "div",
587
1022
  {
588
- className: cn("mx-auto mb-12 max-w-2xl text-center", headerClassName),
1023
+ className: cn(
1024
+ "mx-auto mb-12 max-w-full md:max-w-2xl text-center",
1025
+ headerClassName
1026
+ ),
589
1027
  children: [
590
1028
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
591
1029
  "h2",
592
1030
  {
593
1031
  className: cn(
594
- "text-3xl font-semibold tracking-tight md:text-4xl",
1032
+ "text-pretty text-3xl md:text-4xl lg:text-6xl",
1033
+ "font-semibold tracking-tight",
595
1034
  headingClassName
596
1035
  ),
597
1036
  children: heading
598
1037
  }
599
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
600
- description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-4 text-lg ", descriptionClassName), children: description }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-4", descriptionClassName), children: description }))
1038
+ ) : heading),
1039
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1040
+ "p",
1041
+ {
1042
+ className: cn("mt-4 text-lg text-balance", descriptionClassName),
1043
+ children: description
1044
+ }
1045
+ ) : description)
601
1046
  ]
602
1047
  }
603
1048
  ),