@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
@@ -1,9 +1,11 @@
1
1
  "use client";
2
- import React, { useCallback, useMemo } from 'react';
2
+ import * as React from 'react';
3
+ import React__default, { useCallback, useMemo } from 'react';
3
4
  import { clsx } from 'clsx';
4
5
  import { twMerge } from 'tailwind-merge';
5
6
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
6
7
  import { jsx, jsxs } from 'react/jsx-runtime';
8
+ import { cva } from 'class-variance-authority';
7
9
 
8
10
  // components/blocks/testimonials/testimonials-marquee.tsx
9
11
  function cn(...inputs) {
@@ -54,19 +56,6 @@ function AvatarFallback({
54
56
  }
55
57
  );
56
58
  }
57
- function Card({ className, ...props }) {
58
- return /* @__PURE__ */ jsx(
59
- "div",
60
- {
61
- "data-slot": "card",
62
- className: cn(
63
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
64
- className
65
- ),
66
- ...props
67
- }
68
- );
69
- }
70
59
  function CardContent({ className, ...props }) {
71
60
  return /* @__PURE__ */ jsx(
72
61
  "div",
@@ -77,6 +66,424 @@ function CardContent({ className, ...props }) {
77
66
  }
78
67
  );
79
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 = React.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 = React.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 = React.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 = React.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 = React.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 = React.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";
80
487
  var maxWidthStyles = {
81
488
  sm: "max-w-screen-sm",
82
489
  md: "max-w-screen-md",
@@ -86,7 +493,7 @@ var maxWidthStyles = {
86
493
  "4xl": "max-w-[1536px]",
87
494
  full: "max-w-full"
88
495
  };
89
- var Container = React.forwardRef(
496
+ var Container = React__default.forwardRef(
90
497
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
91
498
  const Component = as;
92
499
  return /* @__PURE__ */ jsx(
@@ -392,7 +799,7 @@ var spacingStyles = {
392
799
  };
393
800
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
394
801
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
395
- var Section = React.forwardRef(
802
+ var Section = React__default.forwardRef(
396
803
  ({
397
804
  id,
398
805
  title,
@@ -516,10 +923,18 @@ function TestimonialsMarquee({
516
923
  const authorName = getAuthorName(testimonial);
517
924
  const avatarSrc = getAvatarSrc(testimonial);
518
925
  return /* @__PURE__ */ jsx(
519
- Card,
926
+ Pressable,
520
927
  {
521
- className: cn("w-80 shrink-0", cardClassName),
522
- children: /* @__PURE__ */ jsxs(CardContent, { className: "p-6", children: [
928
+ href: testimonial?.linkConfig?.href,
929
+ className: cn(
930
+ "bg-card text-card-foreground",
931
+ "rounded-2xl border shadow-xl",
932
+ "cursor-pointer transition-all duration-500",
933
+ "hover:bg-primary hover:text-primary-foreground",
934
+ "flex flex-col gap-6 w-80 shrink-0",
935
+ cardClassName
936
+ ),
937
+ children: /* @__PURE__ */ jsxs(CardContent, { className: "p-6 h-full flex flex-col justify-between gap-12", children: [
523
938
  testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxs(
524
939
  "p",
525
940
  {
@@ -537,15 +952,15 @@ function TestimonialsMarquee({
537
952
  /* @__PURE__ */ jsxs(
538
953
  "div",
539
954
  {
540
- className: cn("flex items-center gap-3", authorClassName),
955
+ className: cn("flex items-center gap-4", authorClassName),
541
956
  children: [
542
- /* @__PURE__ */ jsxs(Avatar, { className: "size-9", children: [
957
+ /* @__PURE__ */ jsxs(Avatar, { className: "relative flex shrink-0 overflow-hidden rounded-full size-10 ring-4 ring-primary shadow-lg", children: [
543
958
  /* @__PURE__ */ jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
544
959
  /* @__PURE__ */ jsx(AvatarFallback, { className: "text-xs", children: getInitials(authorName) })
545
960
  ] }),
546
961
  /* @__PURE__ */ jsxs("div", { children: [
547
- testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: testimonial.author }) : testimonial.author),
548
- testimonial.role && (typeof testimonial.role === "string" ? /* @__PURE__ */ jsx("p", { className: "text-xs", children: testimonial.role }) : testimonial.role)
962
+ testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsx("p", { className: "text-base font-medium", children: testimonial.author }) : testimonial.author),
963
+ testimonial.role && (typeof testimonial.role === "string" ? /* @__PURE__ */ jsx("p", { className: "text-sm", children: testimonial.role }) : testimonial.role)
549
964
  ] })
550
965
  ]
551
966
  }
@@ -583,18 +998,18 @@ function TestimonialsMarquee({
583
998
  className: cn("overflow-hidden", className),
584
999
  containerClassName,
585
1000
  children: [
586
- /* @__PURE__ */ jsx("div", { className: cn("mb-12", headerClassName), children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-2xl text-center", children: [
1001
+ /* @__PURE__ */ jsx("div", { className: cn("mb-12", headerClassName), children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-full md:max-w-2xl text-center space-y-2", children: [
587
1002
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
588
1003
  "h2",
589
1004
  {
590
1005
  className: cn(
591
- "text-3xl font-semibold tracking-tight md:text-4xl",
1006
+ "text-3xl font-semibold tracking-tight md:text-4xl lg:text-6xl text-pretty",
592
1007
  headingClassName
593
1008
  ),
594
1009
  children: heading
595
1010
  }
596
1011
  ) : heading),
597
- description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("mt-4 text-lg", descriptionClassName), children: description }) : description)
1012
+ description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description)
598
1013
  ] }) }),
599
1014
  renderedTestimonials,
600
1015
  /* @__PURE__ */ jsx("style", { children: `