@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,11 +1,12 @@
1
1
  "use client";
2
- import * as React from 'react';
3
- import React__default, { useCallback, useMemo } from 'react';
2
+ import * as React2 from 'react';
3
+ import React2__default, { useCallback, useMemo } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { Icon } from '@page-speed/icon';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
8
8
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
9
+ import { cva } from 'class-variance-authority';
9
10
  import { Img } from '@page-speed/img';
10
11
 
11
12
  // components/blocks/testimonials/testimonials-split-image.tsx
@@ -13,7 +14,7 @@ function cn(...inputs) {
13
14
  return twMerge(clsx(inputs));
14
15
  }
15
16
  var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
16
- var DynamicIcon = React.memo(function DynamicIcon2({
17
+ var DynamicIcon = React2.memo(function DynamicIcon2({
17
18
  apiKey,
18
19
  ...props
19
20
  }) {
@@ -65,6 +66,424 @@ function AvatarFallback({
65
66
  }
66
67
  );
67
68
  }
69
+ function normalizePhoneNumber(input) {
70
+ const trimmed = input.trim();
71
+ if (trimmed.toLowerCase().startsWith("tel:")) {
72
+ return trimmed;
73
+ }
74
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
75
+ if (match) {
76
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
77
+ const extension = match[3];
78
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
79
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
80
+ return `tel:${withExtension}`;
81
+ }
82
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
83
+ return `tel:${cleaned}`;
84
+ }
85
+ function normalizeEmail(input) {
86
+ const trimmed = input.trim();
87
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
88
+ return trimmed;
89
+ }
90
+ return `mailto:${trimmed}`;
91
+ }
92
+ function isEmail(input) {
93
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
94
+ return emailRegex.test(input.trim());
95
+ }
96
+ function isPhoneNumber(input) {
97
+ const trimmed = input.trim();
98
+ if (trimmed.toLowerCase().startsWith("tel:")) {
99
+ return true;
100
+ }
101
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
102
+ return phoneRegex.test(trimmed);
103
+ }
104
+ function isInternalUrl(href) {
105
+ if (typeof window === "undefined") {
106
+ return href.startsWith("/") && !href.startsWith("//");
107
+ }
108
+ const trimmed = href.trim();
109
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
110
+ return true;
111
+ }
112
+ try {
113
+ const url = new URL(trimmed, window.location.href);
114
+ const currentOrigin = window.location.origin;
115
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
116
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
117
+ } catch {
118
+ return false;
119
+ }
120
+ }
121
+ function toRelativePath(href) {
122
+ if (typeof window === "undefined") {
123
+ return href;
124
+ }
125
+ const trimmed = href.trim();
126
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
127
+ return trimmed;
128
+ }
129
+ try {
130
+ const url = new URL(trimmed, window.location.href);
131
+ const currentOrigin = window.location.origin;
132
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
133
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
134
+ return url.pathname + url.search + url.hash;
135
+ }
136
+ } catch {
137
+ }
138
+ return trimmed;
139
+ }
140
+ function useNavigation({
141
+ href,
142
+ onClick
143
+ } = {}) {
144
+ const linkType = React2.useMemo(() => {
145
+ if (!href || href.trim() === "") {
146
+ return onClick ? "none" : "none";
147
+ }
148
+ const trimmed = href.trim();
149
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
150
+ return "mailto";
151
+ }
152
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
153
+ return "tel";
154
+ }
155
+ if (isInternalUrl(trimmed)) {
156
+ return "internal";
157
+ }
158
+ try {
159
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
160
+ return "external";
161
+ } catch {
162
+ return "internal";
163
+ }
164
+ }, [href, onClick]);
165
+ const normalizedHref = React2.useMemo(() => {
166
+ if (!href || href.trim() === "") {
167
+ return void 0;
168
+ }
169
+ const trimmed = href.trim();
170
+ switch (linkType) {
171
+ case "tel":
172
+ return normalizePhoneNumber(trimmed);
173
+ case "mailto":
174
+ return normalizeEmail(trimmed);
175
+ case "internal":
176
+ return toRelativePath(trimmed);
177
+ case "external":
178
+ return trimmed;
179
+ default:
180
+ return trimmed;
181
+ }
182
+ }, [href, linkType]);
183
+ const target = React2.useMemo(() => {
184
+ switch (linkType) {
185
+ case "external":
186
+ return "_blank";
187
+ case "internal":
188
+ return "_self";
189
+ case "mailto":
190
+ case "tel":
191
+ return void 0;
192
+ default:
193
+ return void 0;
194
+ }
195
+ }, [linkType]);
196
+ const rel = React2.useMemo(() => {
197
+ if (linkType === "external") {
198
+ return "noopener noreferrer";
199
+ }
200
+ return void 0;
201
+ }, [linkType]);
202
+ const isExternal = linkType === "external";
203
+ const isInternal = linkType === "internal";
204
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
205
+ const handleClick = React2.useCallback(
206
+ (event) => {
207
+ if (onClick) {
208
+ try {
209
+ onClick(event);
210
+ } catch (error) {
211
+ console.error("Error in user onClick handler:", error);
212
+ }
213
+ }
214
+ if (event.defaultPrevented) {
215
+ return;
216
+ }
217
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
218
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
219
+ if (typeof window !== "undefined") {
220
+ const handler = window.__opensiteNavigationHandler;
221
+ if (typeof handler === "function") {
222
+ try {
223
+ const handled = handler(normalizedHref, event.nativeEvent || event);
224
+ if (handled !== false) {
225
+ event.preventDefault();
226
+ }
227
+ } catch (error) {
228
+ console.error("Error in navigation handler:", error);
229
+ }
230
+ }
231
+ }
232
+ }
233
+ },
234
+ [onClick, shouldUseRouter, normalizedHref]
235
+ );
236
+ return {
237
+ linkType,
238
+ normalizedHref,
239
+ target,
240
+ rel,
241
+ isExternal,
242
+ isInternal,
243
+ shouldUseRouter,
244
+ handleClick
245
+ };
246
+ }
247
+ var baseStyles = [
248
+ // Layout
249
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
250
+ // Typography - using CSS variables with sensible defaults
251
+ "font-[var(--button-font-family,inherit)]",
252
+ "font-[var(--button-font-weight,500)]",
253
+ "tracking-[var(--button-letter-spacing,0)]",
254
+ "leading-[var(--button-line-height,1.25)]",
255
+ "[text-transform:var(--button-text-transform,none)]",
256
+ "text-sm",
257
+ // Border radius
258
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
259
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
260
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
261
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
262
+ "[box-shadow:var(--button-shadow,none)]",
263
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
264
+ // Disabled state
265
+ "disabled:pointer-events-none disabled:opacity-50",
266
+ // SVG handling
267
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
268
+ // Focus styles
269
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
270
+ // Invalid state
271
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
272
+ ].join(" ");
273
+ var buttonVariants = cva(baseStyles, {
274
+ variants: {
275
+ variant: {
276
+ // Default (Primary) variant - full customization
277
+ default: [
278
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
279
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
280
+ "border-[length:var(--button-default-border-width,0px)]",
281
+ "border-[color:var(--button-default-border,transparent)]",
282
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
283
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
284
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
285
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
286
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
287
+ ].join(" "),
288
+ // Destructive variant - full customization
289
+ destructive: [
290
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
291
+ "text-[var(--button-destructive-fg,white)]",
292
+ "border-[length:var(--button-destructive-border-width,0px)]",
293
+ "border-[color:var(--button-destructive-border,transparent)]",
294
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
295
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
296
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
297
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
298
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
299
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
300
+ "dark:bg-destructive/60"
301
+ ].join(" "),
302
+ // Outline variant - full customization with proper border handling
303
+ outline: [
304
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
305
+ "text-[var(--button-outline-fg,inherit)]",
306
+ "border-[length:var(--button-outline-border-width,1px)]",
307
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
308
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
309
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
310
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
311
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
312
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
313
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
314
+ ].join(" "),
315
+ // Secondary variant - full customization
316
+ secondary: [
317
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
318
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
319
+ "border-[length:var(--button-secondary-border-width,0px)]",
320
+ "border-[color:var(--button-secondary-border,transparent)]",
321
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
322
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
323
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
324
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
325
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
326
+ ].join(" "),
327
+ // Ghost variant - full customization
328
+ ghost: [
329
+ "bg-[var(--button-ghost-bg,transparent)]",
330
+ "text-[var(--button-ghost-fg,inherit)]",
331
+ "border-[length:var(--button-ghost-border-width,0px)]",
332
+ "border-[color:var(--button-ghost-border,transparent)]",
333
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
334
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
335
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
336
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
337
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
338
+ "dark:hover:bg-accent/50"
339
+ ].join(" "),
340
+ // Link variant - full customization
341
+ link: [
342
+ "bg-[var(--button-link-bg,transparent)]",
343
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
344
+ "border-[length:var(--button-link-border-width,0px)]",
345
+ "border-[color:var(--button-link-border,transparent)]",
346
+ "[box-shadow:var(--button-link-shadow,none)]",
347
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
348
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
349
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
350
+ "underline-offset-4 hover:underline"
351
+ ].join(" ")
352
+ },
353
+ size: {
354
+ default: [
355
+ "h-[var(--button-height-md,2.25rem)]",
356
+ "px-[var(--button-padding-x-md,1rem)]",
357
+ "py-[var(--button-padding-y-md,0.5rem)]",
358
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
359
+ ].join(" "),
360
+ sm: [
361
+ "h-[var(--button-height-sm,2rem)]",
362
+ "px-[var(--button-padding-x-sm,0.75rem)]",
363
+ "py-[var(--button-padding-y-sm,0.25rem)]",
364
+ "gap-1.5",
365
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
366
+ ].join(" "),
367
+ md: [
368
+ "h-[var(--button-height-md,2.25rem)]",
369
+ "px-[var(--button-padding-x-md,1rem)]",
370
+ "py-[var(--button-padding-y-md,0.5rem)]",
371
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
372
+ ].join(" "),
373
+ lg: [
374
+ "h-[var(--button-height-lg,2.5rem)]",
375
+ "px-[var(--button-padding-x-lg,1.5rem)]",
376
+ "py-[var(--button-padding-y-lg,0.5rem)]",
377
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
378
+ ].join(" "),
379
+ icon: "size-[var(--button-height-md,2.25rem)]",
380
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
381
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
382
+ }
383
+ },
384
+ defaultVariants: {
385
+ variant: "default",
386
+ size: "default"
387
+ }
388
+ });
389
+ var Pressable = React2.forwardRef(
390
+ ({
391
+ children,
392
+ className,
393
+ href,
394
+ onClick,
395
+ variant,
396
+ size,
397
+ asButton = false,
398
+ fallbackComponentType = "span",
399
+ componentType,
400
+ "aria-label": ariaLabel,
401
+ "aria-describedby": ariaDescribedby,
402
+ id,
403
+ ...props
404
+ }, ref) => {
405
+ const navigation = useNavigation({ href, onClick });
406
+ const {
407
+ normalizedHref,
408
+ target,
409
+ rel,
410
+ linkType,
411
+ isInternal,
412
+ handleClick
413
+ } = navigation;
414
+ const shouldRenderLink = normalizedHref && linkType !== "none";
415
+ const shouldRenderButton = !shouldRenderLink && onClick;
416
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
417
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
418
+ const shouldApplyButtonStyles = asButton || variant || size;
419
+ const combinedClassName = cn(
420
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
421
+ className
422
+ );
423
+ const dataProps = Object.fromEntries(
424
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
425
+ );
426
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
427
+ "data-slot": "button",
428
+ "data-variant": variant ?? "default",
429
+ "data-size": size ?? "default"
430
+ } : {};
431
+ const commonProps = {
432
+ className: combinedClassName,
433
+ onClick: handleClick,
434
+ "aria-label": ariaLabel,
435
+ "aria-describedby": ariaDescribedby,
436
+ id,
437
+ ...dataProps,
438
+ ...buttonDataAttributes
439
+ };
440
+ if (finalComponentType === "a" && shouldRenderLink) {
441
+ return /* @__PURE__ */ jsx(
442
+ "a",
443
+ {
444
+ ref,
445
+ href: normalizedHref,
446
+ target,
447
+ rel,
448
+ ...commonProps,
449
+ ...props,
450
+ children
451
+ }
452
+ );
453
+ }
454
+ if (finalComponentType === "button") {
455
+ return /* @__PURE__ */ jsx(
456
+ "button",
457
+ {
458
+ ref,
459
+ type: props.type || "button",
460
+ ...commonProps,
461
+ ...props,
462
+ children
463
+ }
464
+ );
465
+ }
466
+ if (finalComponentType === "div") {
467
+ return /* @__PURE__ */ jsx(
468
+ "div",
469
+ {
470
+ ref,
471
+ ...commonProps,
472
+ children
473
+ }
474
+ );
475
+ }
476
+ return /* @__PURE__ */ jsx(
477
+ "span",
478
+ {
479
+ ref,
480
+ ...commonProps,
481
+ children
482
+ }
483
+ );
484
+ }
485
+ );
486
+ Pressable.displayName = "Pressable";
68
487
  var maxWidthStyles = {
69
488
  sm: "max-w-screen-sm",
70
489
  md: "max-w-screen-md",
@@ -74,7 +493,7 @@ var maxWidthStyles = {
74
493
  "4xl": "max-w-[1536px]",
75
494
  full: "max-w-full"
76
495
  };
77
- var Container = React__default.forwardRef(
496
+ var Container = React2__default.forwardRef(
78
497
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
79
498
  const Component = as;
80
499
  return /* @__PURE__ */ jsx(
@@ -380,7 +799,7 @@ var spacingStyles = {
380
799
  };
381
800
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
382
801
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
383
- var Section = React__default.forwardRef(
802
+ var Section = React2__default.forwardRef(
384
803
  ({
385
804
  id,
386
805
  title,
@@ -489,32 +908,44 @@ function TestimonialsSplitImage({
489
908
  /* @__PURE__ */ jsx(
490
909
  DynamicIcon,
491
910
  {
492
- name: "lucide/quote",
911
+ name: "mdi/comment-quote-outline",
493
912
  size: 48,
494
- className: cn("text-primary/20", quoteIconClassName)
913
+ className: quoteIconClassName
495
914
  }
496
915
  ),
497
916
  testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsx(
498
917
  "blockquote",
499
918
  {
500
919
  className: cn(
501
- "text-xl font-medium leading-relaxed md:text-2xl",
920
+ "text-lg font-light leading-relaxed md:text-2xl lg:text-3xl",
502
921
  quoteClassName
503
922
  ),
504
923
  children: testimonial.quote
505
924
  }
506
925
  ) : /* @__PURE__ */ jsx("div", { className: quoteClassName, children: testimonial.quote })),
507
926
  /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-4 pt-4", authorClassName), children: [
508
- /* @__PURE__ */ jsxs(Avatar, { className: "size-12", children: [
927
+ /* @__PURE__ */ jsxs(Avatar, { className: "relative flex shrink-0 overflow-hidden shadow-xl rounded-2xl size-18", children: [
509
928
  /* @__PURE__ */ jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
510
929
  /* @__PURE__ */ jsx(AvatarFallback, { children: getInitials(authorName) })
511
930
  ] }),
512
- /* @__PURE__ */ jsxs("div", { children: [
931
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0", children: [
513
932
  testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsx("p", { className: "font-semibold", children: testimonial.author }) : testimonial.author),
514
933
  (testimonial.role || testimonial.company) && /* @__PURE__ */ jsxs("p", { className: "text-sm ", children: [
515
934
  testimonial.role && (typeof testimonial.role === "string" ? testimonial.role : testimonial.role),
516
935
  testimonial.company && (typeof testimonial.company === "string" ? ` at ${testimonial.company}` : testimonial.company)
517
- ] })
936
+ ] }),
937
+ testimonial.linkConfig?.href && /* @__PURE__ */ jsx(
938
+ Pressable,
939
+ {
940
+ href: testimonial.linkConfig.href,
941
+ className: cn(
942
+ testimonial.linkConfig.className,
943
+ "text-sm font-bold tracking-wide uppercase",
944
+ "hover:underline hover:underline-offset-2"
945
+ ),
946
+ children: testimonial.linkConfig.label
947
+ }
948
+ )
518
949
  ] })
519
950
  ] })
520
951
  ]
@@ -544,13 +975,17 @@ function TestimonialsSplitImage({
544
975
  children: /* @__PURE__ */ jsxs(
545
976
  "div",
546
977
  {
547
- className: cn("grid items-center gap-12 lg:grid-cols-2", gridClassName),
978
+ className: cn(
979
+ "grid items-center gap-10 md:gap-12 grid-cols-1 lg:grid-cols-2",
980
+ gridClassName
981
+ ),
548
982
  children: [
549
983
  imageSrc && /* @__PURE__ */ jsx(
550
984
  "div",
551
985
  {
552
986
  className: cn(
553
- "relative aspect-4/3 overflow-hidden rounded-2xl lg:aspect-square",
987
+ "shadow-xl rounded-2xl",
988
+ "relative aspect-4/3 overflow-hidden lg:aspect-square",
554
989
  effectiveImagePosition === "right" && "lg:order-2",
555
990
  imageClassName
556
991
  ),
@@ -935,6 +935,7 @@ var SocialLinkIcon = React__namespace.forwardRef(
935
935
  iconClassName,
936
936
  className,
937
937
  iconNameOverride,
938
+ iconOnly = false,
938
939
  ...pressableProps
939
940
  }, ref) => {
940
941
  const platform = usePlatformFromUrl.usePlatformFromUrl(href);
@@ -947,6 +948,21 @@ var SocialLinkIcon = React__namespace.forwardRef(
947
948
  const accessibleLabel = React__namespace.useMemo(() => {
948
949
  return label || platformName;
949
950
  }, [label, platformName]);
951
+ const icon = React__namespace.useMemo(() => {
952
+ return /* @__PURE__ */ jsxRuntime.jsx(
953
+ DynamicIcon,
954
+ {
955
+ name: iconName,
956
+ size: iconSize,
957
+ color: iconColor,
958
+ className: iconClassName,
959
+ alt: accessibleLabel
960
+ }
961
+ );
962
+ }, [iconName, iconSize, iconColor, iconClassName, accessibleLabel]);
963
+ if (iconOnly) {
964
+ return icon;
965
+ }
950
966
  return /* @__PURE__ */ jsxRuntime.jsx(
951
967
  Pressable,
952
968
  {
@@ -958,16 +974,7 @@ var SocialLinkIcon = React__namespace.forwardRef(
958
974
  className
959
975
  ),
960
976
  ...pressableProps,
961
- children: /* @__PURE__ */ jsxRuntime.jsx(
962
- DynamicIcon,
963
- {
964
- name: iconName,
965
- size: iconSize,
966
- color: iconColor,
967
- className: iconClassName,
968
- alt: accessibleLabel
969
- }
970
- )
977
+ children: icon
971
978
  }
972
979
  );
973
980
  }
@@ -1009,7 +1016,7 @@ function TestimonialsTwitterCards({
1009
1016
  "div",
1010
1017
  {
1011
1018
  className: cn(
1012
- "grid gap-4 md:gap-6 lg:gap-8 md:grid-cols-2 lg:grid-cols-3",
1019
+ "grid gap-6 lg:gap-8 md:grid-cols-2 lg:grid-cols-3",
1013
1020
  gridClassName
1014
1021
  ),
1015
1022
  children: testimonials.map((testimonial, index) => {
@@ -1019,14 +1026,18 @@ function TestimonialsTwitterCards({
1019
1026
  {
1020
1027
  href: testimonial.linkConfig?.href,
1021
1028
  className: cn(
1022
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-xl group hover:bg-primary hover:text-primary-foreground transition-all duration-500",
1029
+ "bg-card text-card-foreground",
1030
+ "flex flex-col gap-6",
1031
+ testimonial.linkConfig?.href ? "cursor-pointer hover:bg-primary hover:text-primary-foreground transition-all duration-500" : "",
1032
+ "rounded-2xl py-6 shadow-xl group",
1033
+ "ring-4 ring-primary",
1023
1034
  cardClassName
1024
1035
  ),
1025
1036
  children: /* @__PURE__ */ jsxRuntime.jsxs(
1026
1037
  CardContent,
1027
1038
  {
1028
1039
  className: cn(
1029
- "px-6 h-full flex flex-col-reverse items-stretch justify-between",
1040
+ "px-6 h-full flex flex-col-reverse items-stretch justify-between gap-12",
1030
1041
  cardContentClassName
1031
1042
  ),
1032
1043
  children: [
@@ -1058,7 +1069,8 @@ function TestimonialsTwitterCards({
1058
1069
  SocialLinkIcon,
1059
1070
  {
1060
1071
  href: testimonial.linkConfig.href,
1061
- iconSize: 18
1072
+ iconSize: 24,
1073
+ iconOnly: true
1062
1074
  }
1063
1075
  )
1064
1076
  ]