@opensite/ui 2.9.0 → 2.9.2

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/carousel-feature-badge.cjs +4 -3
  2. package/dist/carousel-feature-badge.d.cts +1 -1
  3. package/dist/carousel-feature-badge.d.ts +1 -1
  4. package/dist/carousel-feature-badge.js +4 -3
  5. package/dist/carousel-scrolling-feature-showcase.cjs +47 -38
  6. package/dist/carousel-scrolling-feature-showcase.js +47 -38
  7. package/dist/registry.cjs +454 -265
  8. package/dist/registry.js +454 -265
  9. package/dist/testimonials-grid-add-review.cjs +578 -39
  10. package/dist/testimonials-grid-add-review.d.cts +26 -26
  11. package/dist/testimonials-grid-add-review.d.ts +26 -26
  12. package/dist/testimonials-grid-add-review.js +577 -38
  13. package/dist/testimonials-images-helpful.cjs +85 -74
  14. package/dist/testimonials-images-helpful.js +85 -74
  15. package/dist/testimonials-list-verified.cjs +1 -0
  16. package/dist/testimonials-list-verified.js +1 -0
  17. package/dist/testimonials-logo-cards.cjs +8 -5
  18. package/dist/testimonials-logo-cards.js +8 -5
  19. package/dist/testimonials-masonry-grid.cjs +87 -11
  20. package/dist/testimonials-masonry-grid.d.cts +14 -1
  21. package/dist/testimonials-masonry-grid.d.ts +14 -1
  22. package/dist/testimonials-masonry-grid.js +88 -12
  23. package/dist/testimonials-mini-dividers.cjs +438 -26
  24. package/dist/testimonials-mini-dividers.js +434 -22
  25. package/dist/testimonials-minimal-numbered.cjs +1 -1
  26. package/dist/testimonials-minimal-numbered.js +1 -1
  27. package/dist/testimonials-parallax-number.cjs +1 -1
  28. package/dist/testimonials-parallax-number.js +1 -1
  29. package/dist/testimonials-quote-carousel.cjs +39 -37
  30. package/dist/testimonials-quote-carousel.d.cts +5 -1
  31. package/dist/testimonials-quote-carousel.d.ts +5 -1
  32. package/dist/testimonials-quote-carousel.js +39 -37
  33. package/dist/testimonials-scrolling-columns.cjs +438 -8
  34. package/dist/testimonials-scrolling-columns.js +436 -6
  35. package/dist/testimonials-simple-grid.cjs +82 -6
  36. package/dist/testimonials-simple-grid.d.cts +14 -1
  37. package/dist/testimonials-simple-grid.d.ts +14 -1
  38. package/dist/testimonials-simple-grid.js +83 -7
  39. package/dist/testimonials-stats-header.cjs +88 -8
  40. package/dist/testimonials-stats-header.d.cts +14 -1
  41. package/dist/testimonials-stats-header.d.ts +14 -1
  42. package/dist/testimonials-stats-header.js +89 -9
  43. package/dist/testimonials-twitter-cards.cjs +150 -25
  44. package/dist/testimonials-twitter-cards.d.cts +14 -1
  45. package/dist/testimonials-twitter-cards.d.ts +14 -1
  46. package/dist/testimonials-twitter-cards.js +151 -26
  47. package/dist/testimonials-wall-compact.cjs +529 -50
  48. package/dist/testimonials-wall-compact.d.cts +14 -1
  49. package/dist/testimonials-wall-compact.d.ts +14 -1
  50. package/dist/testimonials-wall-compact.js +526 -44
  51. package/package.json +1 -1
@@ -1,7 +1,7 @@
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');
@@ -9,8 +9,6 @@ var jsxRuntime = require('react/jsx-runtime');
9
9
  var reactSlot = require('@radix-ui/react-slot');
10
10
  var classVarianceAuthority = require('class-variance-authority');
11
11
 
12
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
-
14
12
  function _interopNamespace(e) {
15
13
  if (e && e.__esModule) return e;
16
14
  var n = Object.create(null);
@@ -29,43 +27,13 @@ function _interopNamespace(e) {
29
27
  return Object.freeze(n);
30
28
  }
31
29
 
32
- var React__default = /*#__PURE__*/_interopDefault(React);
30
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
33
31
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
34
32
 
35
33
  // components/blocks/testimonials/testimonials-wall-compact.tsx
36
34
  function cn(...inputs) {
37
35
  return tailwindMerge.twMerge(clsx.clsx(inputs));
38
36
  }
39
- function getNestedCardBg(parentBg, variant = "muted", options) {
40
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
41
- if (isDark) {
42
- switch (variant) {
43
- case "muted":
44
- return "bg-background";
45
- case "card":
46
- return "bg-card";
47
- case "accent":
48
- return "bg-accent";
49
- case "subtle":
50
- return "bg-background/50";
51
- }
52
- } else {
53
- switch (variant) {
54
- case "muted":
55
- return "bg-muted";
56
- case "card":
57
- return "bg-card";
58
- case "accent":
59
- return "bg-accent";
60
- case "subtle":
61
- return "bg-muted/50";
62
- }
63
- }
64
- }
65
- function getNestedCardTextColor(parentBg, options) {
66
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
67
- return isDark ? "text-foreground" : "";
68
- }
69
37
  function Avatar({
70
38
  className,
71
39
  ...props
@@ -152,7 +120,7 @@ var maxWidthStyles = {
152
120
  "4xl": "max-w-[1536px]",
153
121
  full: "max-w-full"
154
122
  };
155
- var Container = React__default.default.forwardRef(
123
+ var Container = React3__namespace.default.forwardRef(
156
124
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
157
125
  const Component = as;
158
126
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -458,7 +426,7 @@ var spacingStyles = {
458
426
  };
459
427
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
460
428
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
461
- var Section = React__default.default.forwardRef(
429
+ var Section = React3__namespace.default.forwardRef(
462
430
  ({
463
431
  id,
464
432
  title,
@@ -519,6 +487,488 @@ var Section = React__default.default.forwardRef(
519
487
  }
520
488
  );
521
489
  Section.displayName = "Section";
490
+ var baseStyles = [
491
+ // Layout
492
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
493
+ // Typography - using CSS variables with sensible defaults
494
+ "font-[var(--button-font-family,inherit)]",
495
+ "font-[var(--button-font-weight,500)]",
496
+ "tracking-[var(--button-letter-spacing,0)]",
497
+ "leading-[var(--button-line-height,1.25)]",
498
+ "[text-transform:var(--button-text-transform,none)]",
499
+ "text-sm",
500
+ // Border radius
501
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
502
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
503
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
504
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
505
+ "[box-shadow:var(--button-shadow,none)]",
506
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
507
+ // Disabled state
508
+ "disabled:pointer-events-none disabled:opacity-50",
509
+ // SVG handling
510
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
511
+ // Focus styles
512
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
513
+ // Invalid state
514
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
515
+ ].join(" ");
516
+ var buttonVariants = classVarianceAuthority.cva(baseStyles, {
517
+ variants: {
518
+ variant: {
519
+ // Default (Primary) variant - full customization
520
+ default: [
521
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
522
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
523
+ "border-[length:var(--button-default-border-width,0px)]",
524
+ "border-[color:var(--button-default-border,transparent)]",
525
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
526
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
527
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
528
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
529
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
530
+ ].join(" "),
531
+ // Destructive variant - full customization
532
+ destructive: [
533
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
534
+ "text-[var(--button-destructive-fg,white)]",
535
+ "border-[length:var(--button-destructive-border-width,0px)]",
536
+ "border-[color:var(--button-destructive-border,transparent)]",
537
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
538
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
539
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
540
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
541
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
542
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
543
+ "dark:bg-destructive/60"
544
+ ].join(" "),
545
+ // Outline variant - full customization with proper border handling
546
+ outline: [
547
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
548
+ "text-[var(--button-outline-fg,inherit)]",
549
+ "border-[length:var(--button-outline-border-width,1px)]",
550
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
551
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
552
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
553
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
554
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
555
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
556
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
557
+ ].join(" "),
558
+ // Secondary variant - full customization
559
+ secondary: [
560
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
561
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
562
+ "border-[length:var(--button-secondary-border-width,0px)]",
563
+ "border-[color:var(--button-secondary-border,transparent)]",
564
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
565
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
566
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
567
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
568
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
569
+ ].join(" "),
570
+ // Ghost variant - full customization
571
+ ghost: [
572
+ "bg-[var(--button-ghost-bg,transparent)]",
573
+ "text-[var(--button-ghost-fg,inherit)]",
574
+ "border-[length:var(--button-ghost-border-width,0px)]",
575
+ "border-[color:var(--button-ghost-border,transparent)]",
576
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
577
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
578
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
579
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
580
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
581
+ "dark:hover:bg-accent/50"
582
+ ].join(" "),
583
+ // Link variant - full customization
584
+ link: [
585
+ "bg-[var(--button-link-bg,transparent)]",
586
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
587
+ "border-[length:var(--button-link-border-width,0px)]",
588
+ "border-[color:var(--button-link-border,transparent)]",
589
+ "[box-shadow:var(--button-link-shadow,none)]",
590
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
591
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
592
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
593
+ "underline-offset-4 hover:underline"
594
+ ].join(" ")
595
+ },
596
+ size: {
597
+ default: [
598
+ "h-[var(--button-height-md,2.25rem)]",
599
+ "px-[var(--button-padding-x-md,1rem)]",
600
+ "py-[var(--button-padding-y-md,0.5rem)]",
601
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
602
+ ].join(" "),
603
+ sm: [
604
+ "h-[var(--button-height-sm,2rem)]",
605
+ "px-[var(--button-padding-x-sm,0.75rem)]",
606
+ "py-[var(--button-padding-y-sm,0.25rem)]",
607
+ "gap-1.5",
608
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
609
+ ].join(" "),
610
+ md: [
611
+ "h-[var(--button-height-md,2.25rem)]",
612
+ "px-[var(--button-padding-x-md,1rem)]",
613
+ "py-[var(--button-padding-y-md,0.5rem)]",
614
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
615
+ ].join(" "),
616
+ lg: [
617
+ "h-[var(--button-height-lg,2.5rem)]",
618
+ "px-[var(--button-padding-x-lg,1.5rem)]",
619
+ "py-[var(--button-padding-y-lg,0.5rem)]",
620
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
621
+ ].join(" "),
622
+ icon: "size-[var(--button-height-md,2.25rem)]",
623
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
624
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
625
+ }
626
+ },
627
+ defaultVariants: {
628
+ variant: "default",
629
+ size: "default"
630
+ }
631
+ });
632
+ function normalizePhoneNumber(input) {
633
+ const trimmed = input.trim();
634
+ if (trimmed.toLowerCase().startsWith("tel:")) {
635
+ return trimmed;
636
+ }
637
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
638
+ if (match) {
639
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
640
+ const extension = match[3];
641
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
642
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
643
+ return `tel:${withExtension}`;
644
+ }
645
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
646
+ return `tel:${cleaned}`;
647
+ }
648
+ function normalizeEmail(input) {
649
+ const trimmed = input.trim();
650
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
651
+ return trimmed;
652
+ }
653
+ return `mailto:${trimmed}`;
654
+ }
655
+ function isEmail(input) {
656
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
657
+ return emailRegex.test(input.trim());
658
+ }
659
+ function isPhoneNumber(input) {
660
+ const trimmed = input.trim();
661
+ if (trimmed.toLowerCase().startsWith("tel:")) {
662
+ return true;
663
+ }
664
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
665
+ return phoneRegex.test(trimmed);
666
+ }
667
+ function isInternalUrl(href) {
668
+ if (typeof window === "undefined") {
669
+ return href.startsWith("/") && !href.startsWith("//");
670
+ }
671
+ const trimmed = href.trim();
672
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
673
+ return true;
674
+ }
675
+ try {
676
+ const url = new URL(trimmed, window.location.href);
677
+ const currentOrigin = window.location.origin;
678
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
679
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
680
+ } catch {
681
+ return false;
682
+ }
683
+ }
684
+ function toRelativePath(href) {
685
+ if (typeof window === "undefined") {
686
+ return href;
687
+ }
688
+ const trimmed = href.trim();
689
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
690
+ return trimmed;
691
+ }
692
+ try {
693
+ const url = new URL(trimmed, window.location.href);
694
+ const currentOrigin = window.location.origin;
695
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
696
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
697
+ return url.pathname + url.search + url.hash;
698
+ }
699
+ } catch {
700
+ }
701
+ return trimmed;
702
+ }
703
+ function useNavigation({
704
+ href,
705
+ onClick
706
+ } = {}) {
707
+ const linkType = React3__namespace.useMemo(() => {
708
+ if (!href || href.trim() === "") {
709
+ return onClick ? "none" : "none";
710
+ }
711
+ const trimmed = href.trim();
712
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
713
+ return "mailto";
714
+ }
715
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
716
+ return "tel";
717
+ }
718
+ if (isInternalUrl(trimmed)) {
719
+ return "internal";
720
+ }
721
+ try {
722
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
723
+ return "external";
724
+ } catch {
725
+ return "internal";
726
+ }
727
+ }, [href, onClick]);
728
+ const normalizedHref = React3__namespace.useMemo(() => {
729
+ if (!href || href.trim() === "") {
730
+ return void 0;
731
+ }
732
+ const trimmed = href.trim();
733
+ switch (linkType) {
734
+ case "tel":
735
+ return normalizePhoneNumber(trimmed);
736
+ case "mailto":
737
+ return normalizeEmail(trimmed);
738
+ case "internal":
739
+ return toRelativePath(trimmed);
740
+ case "external":
741
+ return trimmed;
742
+ default:
743
+ return trimmed;
744
+ }
745
+ }, [href, linkType]);
746
+ const target = React3__namespace.useMemo(() => {
747
+ switch (linkType) {
748
+ case "external":
749
+ return "_blank";
750
+ case "internal":
751
+ return "_self";
752
+ case "mailto":
753
+ case "tel":
754
+ return void 0;
755
+ default:
756
+ return void 0;
757
+ }
758
+ }, [linkType]);
759
+ const rel = React3__namespace.useMemo(() => {
760
+ if (linkType === "external") {
761
+ return "noopener noreferrer";
762
+ }
763
+ return void 0;
764
+ }, [linkType]);
765
+ const isExternal = linkType === "external";
766
+ const isInternal = linkType === "internal";
767
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
768
+ const handleClick = React3__namespace.useCallback(
769
+ (event) => {
770
+ if (onClick) {
771
+ try {
772
+ onClick(event);
773
+ } catch (error) {
774
+ console.error("Error in user onClick handler:", error);
775
+ }
776
+ }
777
+ if (event.defaultPrevented) {
778
+ return;
779
+ }
780
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
781
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
782
+ if (typeof window !== "undefined") {
783
+ const handler = window.__opensiteNavigationHandler;
784
+ if (typeof handler === "function") {
785
+ try {
786
+ const handled = handler(normalizedHref, event.nativeEvent || event);
787
+ if (handled !== false) {
788
+ event.preventDefault();
789
+ }
790
+ } catch (error) {
791
+ console.error("Error in navigation handler:", error);
792
+ }
793
+ }
794
+ }
795
+ }
796
+ },
797
+ [onClick, shouldUseRouter, normalizedHref]
798
+ );
799
+ return {
800
+ linkType,
801
+ normalizedHref,
802
+ target,
803
+ rel,
804
+ isExternal,
805
+ isInternal,
806
+ shouldUseRouter,
807
+ handleClick
808
+ };
809
+ }
810
+ var Pressable = React3__namespace.forwardRef(
811
+ ({
812
+ children,
813
+ className,
814
+ href,
815
+ onClick,
816
+ variant,
817
+ size,
818
+ asButton = false,
819
+ fallbackComponentType = "span",
820
+ componentType,
821
+ "aria-label": ariaLabel,
822
+ "aria-describedby": ariaDescribedby,
823
+ id,
824
+ ...props
825
+ }, ref) => {
826
+ const navigation = useNavigation({ href, onClick });
827
+ const {
828
+ normalizedHref,
829
+ target,
830
+ rel,
831
+ linkType,
832
+ isInternal,
833
+ handleClick
834
+ } = navigation;
835
+ const shouldRenderLink = normalizedHref && linkType !== "none";
836
+ const shouldRenderButton = !shouldRenderLink && onClick;
837
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
838
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
839
+ const shouldApplyButtonStyles = asButton || variant || size;
840
+ const combinedClassName = cn(
841
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
842
+ className
843
+ );
844
+ const dataProps = Object.fromEntries(
845
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
846
+ );
847
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
848
+ "data-slot": "button",
849
+ "data-variant": variant ?? "default",
850
+ "data-size": size ?? "default"
851
+ } : {};
852
+ const commonProps = {
853
+ className: combinedClassName,
854
+ onClick: handleClick,
855
+ "aria-label": ariaLabel,
856
+ "aria-describedby": ariaDescribedby,
857
+ id,
858
+ ...dataProps,
859
+ ...buttonDataAttributes
860
+ };
861
+ if (finalComponentType === "a" && shouldRenderLink) {
862
+ return /* @__PURE__ */ jsxRuntime.jsx(
863
+ "a",
864
+ {
865
+ ref,
866
+ href: normalizedHref,
867
+ target,
868
+ rel,
869
+ ...commonProps,
870
+ ...props,
871
+ children
872
+ }
873
+ );
874
+ }
875
+ if (finalComponentType === "button") {
876
+ return /* @__PURE__ */ jsxRuntime.jsx(
877
+ "button",
878
+ {
879
+ ref,
880
+ type: props.type || "button",
881
+ ...commonProps,
882
+ ...props,
883
+ children
884
+ }
885
+ );
886
+ }
887
+ if (finalComponentType === "div") {
888
+ return /* @__PURE__ */ jsxRuntime.jsx(
889
+ "div",
890
+ {
891
+ ref,
892
+ ...commonProps,
893
+ children
894
+ }
895
+ );
896
+ }
897
+ return /* @__PURE__ */ jsxRuntime.jsx(
898
+ "span",
899
+ {
900
+ ref,
901
+ ...commonProps,
902
+ children
903
+ }
904
+ );
905
+ }
906
+ );
907
+ Pressable.displayName = "Pressable";
908
+ var MOBILE_CLASSES = {
909
+ "fit-left": "items-start md:items-center",
910
+ "fit-center": "items-center",
911
+ "fit-right": "items-end md:items-center",
912
+ "full-left": "items-stretch md:items-center",
913
+ "full-center": "items-stretch md:items-center",
914
+ "full-right": "items-stretch md:items-center"
915
+ };
916
+ function BlockActions({
917
+ mobileConfig,
918
+ actionsClassName,
919
+ verticalSpacing = "mt-4 md:mt-8",
920
+ actions,
921
+ actionsSlot
922
+ }) {
923
+ const width = mobileConfig?.width ?? "full";
924
+ const position = mobileConfig?.position ?? "center";
925
+ const mobileLayoutClass = MOBILE_CLASSES[`${width}-${position}`];
926
+ if (actionsSlot) {
927
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: actionsSlot });
928
+ } else if (actions && actions?.length > 0) {
929
+ return /* @__PURE__ */ jsxRuntime.jsx(
930
+ "div",
931
+ {
932
+ className: cn(
933
+ "flex flex-col md:flex-row flex-wrap gap-4",
934
+ mobileLayoutClass,
935
+ actionsClassName,
936
+ verticalSpacing
937
+ ),
938
+ children: actions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsx(ActionComponent, { action }, index))
939
+ }
940
+ );
941
+ } else {
942
+ return null;
943
+ }
944
+ }
945
+ function ActionComponent({ action }) {
946
+ const {
947
+ label,
948
+ icon,
949
+ iconAfter,
950
+ children,
951
+ href,
952
+ onClick,
953
+ className: actionClassName,
954
+ ...pressableProps
955
+ } = action;
956
+ return /* @__PURE__ */ jsxRuntime.jsx(
957
+ Pressable,
958
+ {
959
+ href,
960
+ onClick,
961
+ asButton: action.asButton ?? true,
962
+ className: actionClassName,
963
+ ...pressableProps,
964
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
965
+ icon,
966
+ label,
967
+ iconAfter
968
+ ] })
969
+ }
970
+ );
971
+ }
522
972
  function TestimonialsWallCompact({
523
973
  testimonials,
524
974
  testimonialsSlot,
@@ -534,27 +984,30 @@ function TestimonialsWallCompact({
534
984
  quoteClassName,
535
985
  background,
536
986
  containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
537
- spacing = "xl",
987
+ spacing = "lg",
538
988
  pattern,
539
- patternOpacity
989
+ patternOpacity,
990
+ actions,
991
+ actionsSlot,
992
+ actionsClassName
540
993
  }) {
541
- const getAuthorName = React.useCallback(
994
+ const getAuthorName = React3.useCallback(
542
995
  (testimonial) => {
543
996
  if (typeof testimonial.author === "string") return testimonial.author;
544
997
  return "";
545
998
  },
546
999
  []
547
1000
  );
548
- const getAvatarSrc = React.useCallback(
1001
+ const getAvatarSrc = React3.useCallback(
549
1002
  (testimonial) => {
550
1003
  return testimonial.avatarSrc || testimonial.avatar?.src;
551
1004
  },
552
1005
  []
553
1006
  );
554
- const getInitials = React.useCallback((name) => {
1007
+ const getInitials = React3.useCallback((name) => {
555
1008
  return name.split(" ").map((n) => n[0]).join("");
556
1009
  }, []);
557
- const renderedTestimonials = React.useMemo(() => {
1010
+ const renderedTestimonials = React3.useMemo(() => {
558
1011
  if (testimonialsSlot) return testimonialsSlot;
559
1012
  if (!testimonials || testimonials.length === 0) return null;
560
1013
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -571,9 +1024,8 @@ function TestimonialsWallCompact({
571
1024
  "div",
572
1025
  {
573
1026
  className: cn(
1027
+ "bg-card text-card-foreground",
574
1028
  "rounded-lg border p-4 transition-shadow hover:shadow-md",
575
- getNestedCardBg(background, "card"),
576
- getNestedCardTextColor(background),
577
1029
  cardClassName
578
1030
  ),
579
1031
  children: [
@@ -592,14 +1044,23 @@ function TestimonialsWallCompact({
592
1044
  ] }),
593
1045
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
594
1046
  testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-medium", children: testimonial.author }) : testimonial.author),
595
- testimonial.handle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs ", children: testimonial.handle })
1047
+ testimonial.handle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs font-semibold opacity-75", children: testimonial.handle })
596
1048
  ] })
597
1049
  ] }),
598
1050
  testimonial.badge && (typeof testimonial.badge === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", className: "shrink-0 text-xs", children: testimonial.badge }) : testimonial.badge)
599
1051
  ]
600
1052
  }
601
1053
  ),
602
- testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-sm leading-relaxed", quoteClassName), children: testimonial.quote }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: quoteClassName, children: testimonial.quote }))
1054
+ testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1055
+ "p",
1056
+ {
1057
+ className: cn(
1058
+ "text-sm leading-relaxed pt-2",
1059
+ quoteClassName
1060
+ ),
1061
+ children: testimonial.quote
1062
+ }
1063
+ ) : testimonial.quote)
603
1064
  ]
604
1065
  },
605
1066
  index
@@ -631,23 +1092,41 @@ function TestimonialsWallCompact({
631
1092
  /* @__PURE__ */ jsxRuntime.jsxs(
632
1093
  "div",
633
1094
  {
634
- className: cn("mx-auto mb-12 max-w-2xl text-center", headerClassName),
1095
+ className: cn(
1096
+ "mx-auto mb-12 max-w-full md:max-w-md text-center",
1097
+ headerClassName
1098
+ ),
635
1099
  children: [
636
1100
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
637
1101
  "h2",
638
1102
  {
639
1103
  className: cn(
640
- "text-3xl font-semibold tracking-tight md:text-4xl",
1104
+ "text-3xl font-semibold tracking-tight md:text-4xl text-pretty",
641
1105
  headingClassName
642
1106
  ),
643
1107
  children: heading
644
1108
  }
645
1109
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
646
- 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 }))
1110
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1111
+ "p",
1112
+ {
1113
+ className: cn("mt-4 text-lg text-balance", descriptionClassName),
1114
+ children: description
1115
+ }
1116
+ ) : description)
647
1117
  ]
648
1118
  }
649
1119
  ),
650
- renderedTestimonials
1120
+ renderedTestimonials,
1121
+ /* @__PURE__ */ jsxRuntime.jsx(
1122
+ BlockActions,
1123
+ {
1124
+ actions,
1125
+ actionsSlot,
1126
+ actionsClassName: cn("mt-8 md:mt-12 justify-center", actionsClassName),
1127
+ mobileConfig: { width: "full", position: "center" }
1128
+ }
1129
+ )
651
1130
  ]
652
1131
  }
653
1132
  );