@opensite/ui 2.8.6 → 2.8.8

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 (143) 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-icon-sidebar.cjs +5 -4
  14. package/dist/carousel-icon-sidebar.js +5 -4
  15. package/dist/carousel-portfolio-hero.cjs +79 -25
  16. package/dist/carousel-portfolio-hero.d.cts +7 -2
  17. package/dist/carousel-portfolio-hero.d.ts +7 -2
  18. package/dist/carousel-portfolio-hero.js +79 -25
  19. package/dist/components.cjs +81 -42
  20. package/dist/components.d.cts +29 -2
  21. package/dist/components.d.ts +29 -2
  22. package/dist/components.js +81 -43
  23. package/dist/contact-map.cjs +46 -32
  24. package/dist/contact-map.js +46 -32
  25. package/dist/footer-accordion-social.cjs +17 -10
  26. package/dist/footer-accordion-social.js +17 -10
  27. package/dist/footer-animated-social.cjs +17 -10
  28. package/dist/footer-animated-social.js +17 -10
  29. package/dist/footer-brand-description.cjs +17 -10
  30. package/dist/footer-brand-description.js +17 -10
  31. package/dist/footer-brand-links-contact.cjs +17 -10
  32. package/dist/footer-brand-links-contact.js +17 -10
  33. package/dist/footer-comprehensive-links.cjs +17 -10
  34. package/dist/footer-comprehensive-links.js +17 -10
  35. package/dist/footer-contact-card.cjs +17 -10
  36. package/dist/footer-contact-card.js +17 -10
  37. package/dist/footer-cta-banner.cjs +17 -10
  38. package/dist/footer-cta-banner.js +17 -10
  39. package/dist/footer-cta-social.cjs +17 -10
  40. package/dist/footer-cta-social.js +17 -10
  41. package/dist/footer-info-cards-accordion.cjs +17 -10
  42. package/dist/footer-info-cards-accordion.js +17 -10
  43. package/dist/footer-nav-social.cjs +17 -10
  44. package/dist/footer-nav-social.js +17 -10
  45. package/dist/footer-newsletter-contact.cjs +17 -10
  46. package/dist/footer-newsletter-contact.js +17 -10
  47. package/dist/footer-newsletter-grid.cjs +17 -10
  48. package/dist/footer-newsletter-grid.js +17 -10
  49. package/dist/footer-newsletter-minimal.cjs +17 -10
  50. package/dist/footer-newsletter-minimal.js +17 -10
  51. package/dist/footer-social-apps.cjs +17 -10
  52. package/dist/footer-social-apps.js +17 -10
  53. package/dist/footer-social-newsletter.cjs +17 -10
  54. package/dist/footer-social-newsletter.js +17 -10
  55. package/dist/footer-split-image-accordion.cjs +17 -10
  56. package/dist/footer-split-image-accordion.js +17 -10
  57. package/dist/geo-map.cjs +46 -32
  58. package/dist/geo-map.js +46 -32
  59. package/dist/hero-coming-soon-countdown.cjs +17 -10
  60. package/dist/hero-coming-soon-countdown.js +17 -10
  61. package/dist/hero-video-background-dark.cjs +78 -16
  62. package/dist/hero-video-background-dark.d.cts +7 -2
  63. package/dist/hero-video-background-dark.d.ts +7 -2
  64. package/dist/hero-video-background-dark.js +78 -16
  65. package/dist/index.cjs +81 -42
  66. package/dist/index.d.cts +1 -0
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.js +81 -43
  69. package/dist/link-page-bento-layout.cjs +17 -10
  70. package/dist/link-page-bento-layout.js +17 -10
  71. package/dist/link-page-grid-cards.cjs +17 -10
  72. package/dist/link-page-grid-cards.js +17 -10
  73. package/dist/link-page-minimal-profile.cjs +17 -10
  74. package/dist/link-page-minimal-profile.js +17 -10
  75. package/dist/link-page-newsletter-social.cjs +17 -10
  76. package/dist/link-page-newsletter-social.js +17 -10
  77. package/dist/link-tree-block.cjs +17 -10
  78. package/dist/link-tree-block.js +17 -10
  79. package/dist/navbar-fullscreen-menu.cjs +17 -10
  80. package/dist/navbar-fullscreen-menu.js +17 -10
  81. package/dist/navbar-transparent-overlay.cjs +17 -10
  82. package/dist/navbar-transparent-overlay.js +17 -10
  83. package/dist/registry.cjs +967 -620
  84. package/dist/registry.js +967 -620
  85. package/dist/social-link-icon.cjs +17 -10
  86. package/dist/social-link-icon.d.cts +5 -0
  87. package/dist/social-link-icon.d.ts +5 -0
  88. package/dist/social-link-icon.js +17 -10
  89. package/dist/testimonials-bento-grid.cjs +1 -1
  90. package/dist/testimonials-bento-grid.js +1 -1
  91. package/dist/testimonials-carousel-image.cjs +16 -2
  92. package/dist/testimonials-carousel-image.d.cts +5 -1
  93. package/dist/testimonials-carousel-image.d.ts +5 -1
  94. package/dist/testimonials-carousel-image.js +16 -2
  95. package/dist/testimonials-centered-avatars.cjs +1 -1
  96. package/dist/testimonials-centered-avatars.js +1 -1
  97. package/dist/testimonials-grid-add-review.cjs +51 -29
  98. package/dist/testimonials-grid-add-review.js +51 -29
  99. package/dist/testimonials-images-helpful.cjs +181 -160
  100. package/dist/testimonials-images-helpful.d.cts +9 -1
  101. package/dist/testimonials-images-helpful.d.ts +9 -1
  102. package/dist/testimonials-images-helpful.js +181 -159
  103. package/dist/testimonials-large-quote.cjs +74 -43
  104. package/dist/testimonials-large-quote.d.cts +5 -1
  105. package/dist/testimonials-large-quote.d.ts +5 -1
  106. package/dist/testimonials-large-quote.js +74 -43
  107. package/dist/testimonials-list-verified.cjs +63 -44
  108. package/dist/testimonials-list-verified.d.cts +5 -1
  109. package/dist/testimonials-list-verified.d.ts +5 -1
  110. package/dist/testimonials-list-verified.js +64 -45
  111. package/dist/testimonials-logo-cards.cjs +55 -25
  112. package/dist/testimonials-logo-cards.d.cts +5 -1
  113. package/dist/testimonials-logo-cards.d.ts +5 -1
  114. package/dist/testimonials-logo-cards.js +55 -25
  115. package/dist/testimonials-marquee.cjs +440 -28
  116. package/dist/testimonials-marquee.js +441 -26
  117. package/dist/testimonials-masonry-grid.cjs +486 -69
  118. package/dist/testimonials-masonry-grid.d.cts +5 -1
  119. package/dist/testimonials-masonry-grid.d.ts +5 -1
  120. package/dist/testimonials-masonry-grid.js +483 -63
  121. package/dist/testimonials-mini-dividers.cjs +119 -83
  122. package/dist/testimonials-mini-dividers.d.cts +10 -6
  123. package/dist/testimonials-mini-dividers.d.ts +10 -6
  124. package/dist/testimonials-mini-dividers.js +119 -83
  125. package/dist/testimonials-minimal-numbered.cjs +9 -7
  126. package/dist/testimonials-minimal-numbered.d.cts +5 -1
  127. package/dist/testimonials-minimal-numbered.d.ts +5 -1
  128. package/dist/testimonials-minimal-numbered.js +9 -7
  129. package/dist/testimonials-parallax-number.cjs +14 -9
  130. package/dist/testimonials-parallax-number.js +14 -9
  131. package/dist/testimonials-scrolling-columns.cjs +100 -21
  132. package/dist/testimonials-scrolling-columns.js +100 -21
  133. package/dist/testimonials-simple-grid.cjs +22 -5
  134. package/dist/testimonials-simple-grid.js +22 -5
  135. package/dist/testimonials-slider-minimal.cjs +1 -1
  136. package/dist/testimonials-slider-minimal.js +1 -1
  137. package/dist/testimonials-stats-header.cjs +528 -87
  138. package/dist/testimonials-stats-header.d.cts +39 -3
  139. package/dist/testimonials-stats-header.d.ts +39 -3
  140. package/dist/testimonials-stats-header.js +523 -82
  141. package/dist/testimonials-twitter-cards.cjs +20 -12
  142. package/dist/testimonials-twitter-cards.js +20 -12
  143. package/package.json +11 -1
@@ -5,11 +5,11 @@ import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { Icon } from '@page-speed/icon';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio';
9
8
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
10
9
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
11
10
  import { cva } from 'class-variance-authority';
12
11
  import { Img } from '@page-speed/img';
12
+ import { Lightbox } from '@page-speed/lightbox';
13
13
 
14
14
  // components/blocks/testimonials/testimonials-images-helpful.tsx
15
15
  function cn(...inputs) {
@@ -23,10 +23,22 @@ var DynamicIcon = React2.memo(function DynamicIcon2({
23
23
  return /* @__PURE__ */ jsx(Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
24
24
  });
25
25
  DynamicIcon.displayName = "DynamicIcon";
26
- function AspectRatio({
27
- ...props
26
+ function StarRating({
27
+ rating,
28
+ size = 18,
29
+ className
28
30
  }) {
29
- return /* @__PURE__ */ jsx(AspectRatioPrimitive.Root, { "data-slot": "aspect-ratio", ...props });
31
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", className), children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx(
32
+ DynamicIcon,
33
+ {
34
+ name: "icon-park-solid/star",
35
+ size,
36
+ className: cn(
37
+ star <= rating ? "fill-primary text-primary" : "fill-muted text-muted"
38
+ )
39
+ },
40
+ star
41
+ )) });
30
42
  }
31
43
  function Avatar({
32
44
  className,
@@ -73,29 +85,6 @@ function AvatarFallback({
73
85
  }
74
86
  );
75
87
  }
76
- function Card({ className, ...props }) {
77
- return /* @__PURE__ */ jsx(
78
- "div",
79
- {
80
- "data-slot": "card",
81
- className: cn(
82
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
83
- className
84
- ),
85
- ...props
86
- }
87
- );
88
- }
89
- function CardContent({ className, ...props }) {
90
- return /* @__PURE__ */ jsx(
91
- "div",
92
- {
93
- "data-slot": "card-content",
94
- className: cn("px-6", className),
95
- ...props
96
- }
97
- );
98
- }
99
88
  function Separator({
100
89
  className,
101
90
  orientation = "horizontal",
@@ -910,23 +899,11 @@ var Section = React2__default.forwardRef(
910
899
  }
911
900
  );
912
901
  Section.displayName = "Section";
913
- function StarRating({ rating, size = 16 }) {
914
- return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5", children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx(
915
- DynamicIcon,
916
- {
917
- name: "lucide/star",
918
- size,
919
- className: cn(
920
- star <= rating ? "fill-primary text-primary" : "fill-muted text-muted"
921
- )
922
- },
923
- star
924
- )) });
925
- }
926
902
  function TestimonialsImagesHelpful({
927
903
  reviews,
928
904
  reviewsSlot,
929
905
  heading,
906
+ verifiedPurchaseLabel,
930
907
  writeReviewLabel,
931
908
  reportButtonLabel,
932
909
  className,
@@ -938,12 +915,16 @@ function TestimonialsImagesHelpful({
938
915
  imagesClassName,
939
916
  onWriteReview,
940
917
  background,
941
- spacing = "py-6 md:py-32",
918
+ spacing = "lg",
919
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
942
920
  pattern,
943
921
  patternOpacity,
944
922
  optixFlowConfig
945
923
  }) {
946
924
  const [helpfulClicked, setHelpfulClicked] = useState(/* @__PURE__ */ new Set());
925
+ const [lightboxOpen, setLightboxOpen] = useState(false);
926
+ const [lightboxItems, setLightboxItems] = useState([]);
927
+ const [lightboxIndex, setLightboxIndex] = useState(0);
947
928
  const totalReviews = reviews?.length ?? 0;
948
929
  const averageRating = totalReviews > 0 ? (reviews?.reduce((sum, review) => sum + review.rating, 0) ?? 0) / totalReviews : 0;
949
930
  const handleHelpful = useCallback((reviewIndex) => {
@@ -957,6 +938,25 @@ function TestimonialsImagesHelpful({
957
938
  return newSet;
958
939
  });
959
940
  }, []);
941
+ const handleImageClick = useCallback(
942
+ (reviewImages, imageIndex) => {
943
+ const items = reviewImages.map((src, i) => ({
944
+ id: `review-image-${i}`,
945
+ type: "image",
946
+ src,
947
+ alt: `Review image ${i + 1}`,
948
+ download: true,
949
+ share: true
950
+ }));
951
+ setLightboxItems(items);
952
+ setLightboxIndex(imageIndex);
953
+ setLightboxOpen(true);
954
+ },
955
+ []
956
+ );
957
+ const handleLightboxClose = useCallback(() => {
958
+ setLightboxOpen(false);
959
+ }, []);
960
960
  const getAuthorName = useCallback((review) => {
961
961
  if (typeof review.author === "string") return review.author;
962
962
  return "";
@@ -970,54 +970,28 @@ function TestimonialsImagesHelpful({
970
970
  return /* @__PURE__ */ jsx("div", { className: "space-y-0", children: reviews.map((review, index) => {
971
971
  const authorName = getAuthorName(review);
972
972
  return /* @__PURE__ */ jsxs("div", { className: reviewClassName, children: [
973
- index > 0 && /* @__PURE__ */ jsx(Separator, { className: "my-6" }),
974
- /* @__PURE__ */ jsx(Card, { className: "border-0 p-0 shadow-none", children: /* @__PURE__ */ jsxs(CardContent, { className: cn("space-y-4 p-0", contentClassName), children: [
975
- /* @__PURE__ */ jsxs(
976
- "div",
977
- {
978
- className: cn(
979
- "flex items-start justify-between gap-4",
980
- authorClassName
981
- ),
982
- children: [
983
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
984
- /* @__PURE__ */ jsxs(Avatar, { className: "size-10", children: [
985
- /* @__PURE__ */ jsx(AvatarImage, { src: review.avatarSrc, alt: authorName }),
986
- /* @__PURE__ */ jsx(AvatarFallback, { children: getInitials(authorName) })
987
- ] }),
988
- /* @__PURE__ */ jsxs("div", { children: [
989
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
990
- review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: review.author }) : review.author),
991
- review.verified && /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1 text-emerald-600", children: /* @__PURE__ */ jsx(
992
- DynamicIcon,
993
- {
994
- name: "lucide/badge-check",
995
- size: 16
996
- }
997
- ) })
998
- ] }),
999
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
1000
- review.date && /* @__PURE__ */ jsx("span", { children: review.date }),
1001
- review.variant && /* @__PURE__ */ jsxs(Fragment, { children: [
1002
- /* @__PURE__ */ jsx("span", { children: "\xB7" }),
1003
- /* @__PURE__ */ jsx("span", { children: review.variant })
1004
- ] })
1005
- ] })
1006
- ] })
1007
- ] }),
1008
- /* @__PURE__ */ jsx(StarRating, { rating: review.rating, size: 16 })
1009
- ]
1010
- }
1011
- ),
1012
- /* @__PURE__ */ jsxs("div", { children: [
1013
- review.title && (typeof review.title === "string" ? /* @__PURE__ */ jsx("h3", { className: "font-medium", children: review.title }) : review.title),
1014
- review.content && (typeof review.content === "string" ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm leading-relaxed text-muted-foreground", children: review.content }) : /* @__PURE__ */ jsx("div", { className: "mt-2", children: review.content }))
973
+ index > 0 && /* @__PURE__ */ jsx(Separator, { className: "bg-border/50 shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px my-12 md:my-16" }),
974
+ /* @__PURE__ */ jsxs("div", { className: cn("space-y-6 md:space-y-12", contentClassName), children: [
975
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
976
+ /* @__PURE__ */ jsx(StarRating, { rating: review.rating, size: 22 }),
977
+ review.title && (typeof review.title === "string" ? /* @__PURE__ */ jsx("h3", { className: "font-medium", children: review.title }) : review.title)
1015
978
  ] }),
1016
- review.images && review.images.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("flex gap-2", imagesClassName), children: review.images.map((image, imgIndex) => /* @__PURE__ */ jsx(
979
+ review.content && (typeof review.content === "string" ? /* @__PURE__ */ jsx("p", { className: "text-base md:text-lg leading-relaxed font-light", children: review.content }) : review.content),
980
+ review.images && review.images.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("flex gap-3", imagesClassName), children: review.images.map((image, imgIndex) => /* @__PURE__ */ jsx(
1017
981
  "div",
1018
982
  {
1019
- className: "size-20 overflow-hidden rounded-lg sm:size-24",
1020
- children: /* @__PURE__ */ jsx(AspectRatio, { ratio: 1, children: /* @__PURE__ */ jsx(
983
+ className: "size-20 cursor-pointer overflow-hidden rounded-lg sm:size-24 transition-transform duration-300 hover:scale-[1.03] shadow-sm hover:shadow-lg",
984
+ onClick: () => handleImageClick(review.images, imgIndex),
985
+ role: "button",
986
+ tabIndex: 0,
987
+ onKeyDown: (e) => {
988
+ if (e.key === "Enter" || e.key === " ") {
989
+ e.preventDefault();
990
+ handleImageClick(review.images, imgIndex);
991
+ }
992
+ },
993
+ "aria-label": `View review image ${imgIndex + 1} in lightbox`,
994
+ children: /* @__PURE__ */ jsx(
1021
995
  Img,
1022
996
  {
1023
997
  src: image,
@@ -1025,54 +999,85 @@ function TestimonialsImagesHelpful({
1025
999
  className: "size-full object-cover",
1026
1000
  optixFlowConfig
1027
1001
  }
1028
- ) })
1002
+ )
1029
1003
  },
1030
1004
  imgIndex
1031
1005
  )) }),
1032
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
1006
+ /* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between w-full"), children: [
1033
1007
  /* @__PURE__ */ jsxs(
1034
- Pressable,
1008
+ "div",
1035
1009
  {
1036
- asButton: true,
1037
- variant: "ghost",
1038
- size: "sm",
1039
- className: cn(
1040
- "h-8 gap-1.5 text-muted-foreground",
1041
- helpfulClicked.has(index) && "text-foreground"
1042
- ),
1043
- onClick: () => handleHelpful(index),
1010
+ className: cn("flex items-center gap-5", authorClassName),
1044
1011
  children: [
1045
- /* @__PURE__ */ jsx(
1046
- DynamicIcon,
1047
- {
1048
- name: "lucide/thumbs-up",
1049
- size: 16,
1050
- className: cn(
1051
- helpfulClicked.has(index) && "fill-current"
1052
- )
1053
- }
1054
- ),
1055
- "Helpful",
1056
- review.helpful !== void 0 && /* @__PURE__ */ jsxs("span", { children: [
1057
- "(",
1058
- review.helpful + (helpfulClicked.has(index) ? 1 : 0),
1059
- ")"
1012
+ /* @__PURE__ */ jsxs(Avatar, { className: "size-12 ring-4 ring-primary shadow-lg", children: [
1013
+ /* @__PURE__ */ jsx(AvatarImage, { src: review.avatarSrc, alt: authorName }),
1014
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-md", children: getInitials(authorName) })
1015
+ ] }),
1016
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-0", children: [
1017
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1018
+ review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: review.author }) : review.author),
1019
+ review.verified && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
1020
+ /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
1021
+ verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
1022
+ !verifiedPurchaseLabel && /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Verified Purchase" })
1023
+ ] })
1024
+ ] }),
1025
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
1026
+ review.date && /* @__PURE__ */ jsx("span", { children: review.date }),
1027
+ review.variant && /* @__PURE__ */ jsxs(Fragment, { children: [
1028
+ /* @__PURE__ */ jsx("span", { children: "\xB7" }),
1029
+ /* @__PURE__ */ jsx("span", { children: review.variant })
1030
+ ] })
1031
+ ] })
1060
1032
  ] })
1061
1033
  ]
1062
1034
  }
1063
1035
  ),
1064
- /* @__PURE__ */ jsx(
1065
- Pressable,
1066
- {
1067
- asButton: true,
1068
- variant: "ghost",
1069
- size: "sm",
1070
- className: "h-8 text-muted-foreground",
1071
- children: reportButtonLabel ?? "Report"
1072
- }
1073
- )
1036
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
1037
+ /* @__PURE__ */ jsxs(
1038
+ Pressable,
1039
+ {
1040
+ asButton: true,
1041
+ variant: "ghost",
1042
+ size: "sm",
1043
+ className: cn(
1044
+ "h-8 gap-1.5",
1045
+ helpfulClicked.has(index) ? "text-foreground" : "text-muted-foreground"
1046
+ ),
1047
+ onClick: () => handleHelpful(index),
1048
+ children: [
1049
+ /* @__PURE__ */ jsx(
1050
+ DynamicIcon,
1051
+ {
1052
+ name: "lucide/thumbs-up",
1053
+ size: 16,
1054
+ className: cn(
1055
+ helpfulClicked.has(index) && "fill-current"
1056
+ )
1057
+ }
1058
+ ),
1059
+ "Helpful",
1060
+ review.helpful !== void 0 && /* @__PURE__ */ jsxs("span", { children: [
1061
+ "(",
1062
+ review.helpful + (helpfulClicked.has(index) ? 1 : 0),
1063
+ ")"
1064
+ ] })
1065
+ ]
1066
+ }
1067
+ ),
1068
+ /* @__PURE__ */ jsx(
1069
+ Pressable,
1070
+ {
1071
+ asButton: true,
1072
+ variant: "ghost",
1073
+ size: "sm",
1074
+ className: "h-8 text-muted-foreground",
1075
+ children: reportButtonLabel ?? "Report"
1076
+ }
1077
+ )
1078
+ ] })
1074
1079
  ] })
1075
- ] }) })
1080
+ ] })
1076
1081
  ] }, index);
1077
1082
  }) });
1078
1083
  }, [
@@ -1085,11 +1090,13 @@ function TestimonialsImagesHelpful({
1085
1090
  helpfulClicked,
1086
1091
  optixFlowConfig,
1087
1092
  reportButtonLabel,
1093
+ verifiedPurchaseLabel,
1088
1094
  getAuthorName,
1089
1095
  getInitials,
1090
- handleHelpful
1096
+ handleHelpful,
1097
+ handleImageClick
1091
1098
  ]);
1092
- return /* @__PURE__ */ jsx(
1099
+ return /* @__PURE__ */ jsxs(
1093
1100
  Section,
1094
1101
  {
1095
1102
  background,
@@ -1097,42 +1104,57 @@ function TestimonialsImagesHelpful({
1097
1104
  pattern,
1098
1105
  patternOpacity,
1099
1106
  className,
1100
- children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-3xl", children: [
1101
- /* @__PURE__ */ jsxs(
1102
- "div",
1103
- {
1104
- className: cn(
1105
- "mb-8 flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",
1106
- headerClassName
1107
- ),
1108
- children: [
1109
- /* @__PURE__ */ jsxs("div", { children: [
1110
- heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
1111
- "h2",
1112
- {
1113
- className: cn(
1114
- "text-2xl font-semibold tracking-tight md:text-3xl",
1115
- headingClassName
1116
- ),
1117
- children: heading
1118
- }
1119
- ) : /* @__PURE__ */ jsx("div", { className: headingClassName, children: heading })),
1120
- totalReviews > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
1121
- /* @__PURE__ */ jsx(StarRating, { rating: Math.round(averageRating), size: 20 }),
1122
- /* @__PURE__ */ jsx("span", { className: "text-lg font-semibold", children: averageRating.toFixed(1) }),
1123
- /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
1124
- "(",
1125
- totalReviews,
1126
- " reviews)"
1127
- ] })
1128
- ] })
1129
- ] }),
1107
+ containerClassName,
1108
+ children: [
1109
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-full md:max-w-3xl", children: [
1110
+ /* @__PURE__ */ jsxs("div", { className: cn("mb-12 md:mb-24 space-y-6", headerClassName), children: [
1111
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between", children: [
1112
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
1113
+ "h2",
1114
+ {
1115
+ className: cn(
1116
+ "text-2xl font-semibold tracking-tight md:text-3xl lg:text-4xl",
1117
+ headingClassName
1118
+ ),
1119
+ children: heading
1120
+ }
1121
+ ) : heading),
1130
1122
  (writeReviewLabel || onWriteReview) && /* @__PURE__ */ jsx(Pressable, { asButton: true, variant: "outline", onClick: onWriteReview, children: writeReviewLabel })
1131
- ]
1123
+ ] }),
1124
+ totalReviews > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-center gap-3", children: [
1125
+ /* @__PURE__ */ jsx(StarRating, { rating: Math.round(averageRating), size: 22 }),
1126
+ /* @__PURE__ */ jsxs("span", { className: "text-sm", children: [
1127
+ averageRating.toFixed(1),
1128
+ " out of 5 \xB7 ",
1129
+ totalReviews,
1130
+ " reviews"
1131
+ ] })
1132
+ ] })
1133
+ ] }),
1134
+ renderedReviews
1135
+ ] }),
1136
+ lightboxOpen && /* @__PURE__ */ jsx(
1137
+ Lightbox,
1138
+ {
1139
+ items: lightboxItems,
1140
+ initialIndex: lightboxIndex,
1141
+ layout: "horizontal",
1142
+ controls: {
1143
+ navigation: true,
1144
+ thumbnails: true,
1145
+ download: true,
1146
+ share: true,
1147
+ fullscreen: true,
1148
+ captions: true,
1149
+ counter: true
1150
+ },
1151
+ onClose: handleLightboxClose,
1152
+ enableKeyboardShortcuts: true,
1153
+ closeOnEscape: true,
1154
+ closeOnBackdropClick: true
1132
1155
  }
1133
- ),
1134
- renderedReviews
1135
- ] })
1156
+ )
1157
+ ]
1136
1158
  }
1137
1159
  );
1138
1160
  }
@@ -472,7 +472,8 @@ function TestimonialsLargeQuote({
472
472
  authorClassName,
473
473
  avatarClassName,
474
474
  background,
475
- spacing,
475
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
476
+ spacing = "xl",
476
477
  pattern,
477
478
  patternOpacity
478
479
  }) {
@@ -491,49 +492,78 @@ function TestimonialsLargeQuote({
491
492
  if (!testimonial) return null;
492
493
  const authorName = getAuthorName();
493
494
  const avatarSrc = getAvatarSrc();
494
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mx-auto max-w-4xl text-center", contentClassName), children: [
495
- /* @__PURE__ */ jsxRuntime.jsx(
496
- DynamicIcon,
497
- {
498
- name: "lucide/quote",
499
- size: 64,
500
- className: cn("mx-auto mb-8 text-primary/20", quoteIconClassName)
501
- }
502
- ),
503
- testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
504
- "blockquote",
505
- {
506
- className: cn(
507
- "text-2xl font-medium leading-relaxed md:text-3xl lg:text-4xl",
508
- quoteClassName
509
- ),
510
- children: testimonial.quote
511
- }
512
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: quoteClassName, children: testimonial.quote })),
513
- /* @__PURE__ */ jsxRuntime.jsxs(
514
- "div",
515
- {
516
- className: cn(
517
- "mt-10 flex flex-col items-center gap-4",
518
- authorClassName
495
+ return /* @__PURE__ */ jsxRuntime.jsxs(
496
+ "div",
497
+ {
498
+ className: cn(
499
+ "mx-auto max-full md:max-w-lg text-center",
500
+ contentClassName
501
+ ),
502
+ children: [
503
+ /* @__PURE__ */ jsxRuntime.jsx(
504
+ DynamicIcon,
505
+ {
506
+ name: "mdi/comment-quote-outline",
507
+ size: 48,
508
+ className: cn("mx-auto mb-8 ", quoteIconClassName)
509
+ }
519
510
  ),
520
- children: [
521
- /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: cn("size-16", avatarClassName), children: [
522
- /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
523
- /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "text-lg", children: getInitials(authorName) })
524
- ] }),
525
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
526
- testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold", children: testimonial.author }) : testimonial.author),
527
- (testimonial.role || testimonial.company) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground", children: [
528
- testimonial.role && (typeof testimonial.role === "string" ? testimonial.role : testimonial.role),
529
- testimonial.company && (typeof testimonial.company === "string" ? ` at ${testimonial.company}` : testimonial.company)
530
- ] })
531
- ] })
532
- ]
533
- }
534
- )
535
- ] });
536
- }, [testimonialSlot, contentClassName, quoteIconClassName, testimonial, quoteClassName, authorClassName, avatarClassName, getAuthorName, getAvatarSrc, getInitials]);
511
+ testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
512
+ "blockquote",
513
+ {
514
+ className: cn(
515
+ "text-2xl font-light leading-relaxed md:text-3xl lg:text-4xl text-balance",
516
+ quoteClassName
517
+ ),
518
+ children: testimonial.quote
519
+ }
520
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: quoteClassName, children: testimonial.quote })),
521
+ /* @__PURE__ */ jsxRuntime.jsxs(
522
+ "div",
523
+ {
524
+ className: cn(
525
+ "mt-10 md:mt-16 flex flex-col items-center gap-4 md:gap-8",
526
+ authorClassName
527
+ ),
528
+ children: [
529
+ /* @__PURE__ */ jsxRuntime.jsxs(
530
+ Avatar,
531
+ {
532
+ className: cn(
533
+ "relative flex shrink-0 overflow-hidden rounded-full size-16 ring-4 ring-primary shadow-lg",
534
+ avatarClassName
535
+ ),
536
+ children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
538
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "text-lg", children: getInitials(authorName) })
539
+ ]
540
+ }
541
+ ),
542
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-4", children: [
543
+ testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold", children: testimonial.author }) : testimonial.author),
544
+ (testimonial.role || testimonial.company) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
545
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base font-normal opacity-75", children: testimonial.role && (typeof testimonial.role === "string" ? testimonial.role : testimonial.role) }),
546
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm uppercase font-semibold opacity-75", children: testimonial.company && (typeof testimonial.company === "string" ? ` at ${testimonial.company}` : testimonial.company) })
547
+ ] })
548
+ ] })
549
+ ]
550
+ }
551
+ )
552
+ ]
553
+ }
554
+ );
555
+ }, [
556
+ testimonialSlot,
557
+ contentClassName,
558
+ quoteIconClassName,
559
+ testimonial,
560
+ quoteClassName,
561
+ authorClassName,
562
+ avatarClassName,
563
+ getAuthorName,
564
+ getAvatarSrc,
565
+ getInitials
566
+ ]);
537
567
  return /* @__PURE__ */ jsxRuntime.jsx(
538
568
  Section,
539
569
  {
@@ -542,6 +572,7 @@ function TestimonialsLargeQuote({
542
572
  pattern,
543
573
  patternOpacity,
544
574
  className,
575
+ containerClassName,
545
576
  children: renderedTestimonial
546
577
  }
547
578
  );
@@ -56,6 +56,10 @@ interface TestimonialsLargeQuoteProps {
56
56
  * Pattern overlay opacity (0-1)
57
57
  */
58
58
  patternOpacity?: number;
59
+ /**
60
+ * Additional CSS classes for the container
61
+ */
62
+ containerClassName?: string;
59
63
  }
60
64
  /**
61
65
  * TestimonialsLargeQuote - A centered, single testimonial section featuring an oversized
@@ -79,6 +83,6 @@ interface TestimonialsLargeQuoteProps {
79
83
  * />
80
84
  * ```
81
85
  */
82
- declare function TestimonialsLargeQuote({ testimonial, testimonialSlot, className, contentClassName, quoteIconClassName, quoteClassName, authorClassName, avatarClassName, background, spacing, pattern, patternOpacity, }: TestimonialsLargeQuoteProps): React.JSX.Element;
86
+ declare function TestimonialsLargeQuote({ testimonial, testimonialSlot, className, contentClassName, quoteIconClassName, quoteClassName, authorClassName, avatarClassName, background, containerClassName, spacing, pattern, patternOpacity, }: TestimonialsLargeQuoteProps): React.JSX.Element;
83
87
 
84
88
  export { TestimonialsLargeQuote, type TestimonialsLargeQuoteProps };
@@ -56,6 +56,10 @@ interface TestimonialsLargeQuoteProps {
56
56
  * Pattern overlay opacity (0-1)
57
57
  */
58
58
  patternOpacity?: number;
59
+ /**
60
+ * Additional CSS classes for the container
61
+ */
62
+ containerClassName?: string;
59
63
  }
60
64
  /**
61
65
  * TestimonialsLargeQuote - A centered, single testimonial section featuring an oversized
@@ -79,6 +83,6 @@ interface TestimonialsLargeQuoteProps {
79
83
  * />
80
84
  * ```
81
85
  */
82
- declare function TestimonialsLargeQuote({ testimonial, testimonialSlot, className, contentClassName, quoteIconClassName, quoteClassName, authorClassName, avatarClassName, background, spacing, pattern, patternOpacity, }: TestimonialsLargeQuoteProps): React.JSX.Element;
86
+ declare function TestimonialsLargeQuote({ testimonial, testimonialSlot, className, contentClassName, quoteIconClassName, quoteClassName, authorClassName, avatarClassName, background, containerClassName, spacing, pattern, patternOpacity, }: TestimonialsLargeQuoteProps): React.JSX.Element;
83
87
 
84
88
  export { TestimonialsLargeQuote, type TestimonialsLargeQuoteProps };