@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
@@ -6,8 +6,7 @@ var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var AvatarPrimitive = require('@radix-ui/react-avatar');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
-
10
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+ var classVarianceAuthority = require('class-variance-authority');
11
10
 
12
11
  function _interopNamespace(e) {
13
12
  if (e && e.__esModule) return e;
@@ -27,7 +26,7 @@ function _interopNamespace(e) {
27
26
  return Object.freeze(n);
28
27
  }
29
28
 
30
- var React__default = /*#__PURE__*/_interopDefault(React);
29
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
31
30
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
32
31
 
33
32
  // components/blocks/testimonials/testimonials-marquee.tsx
@@ -79,19 +78,6 @@ function AvatarFallback({
79
78
  }
80
79
  );
81
80
  }
82
- function Card({ className, ...props }) {
83
- return /* @__PURE__ */ jsxRuntime.jsx(
84
- "div",
85
- {
86
- "data-slot": "card",
87
- className: cn(
88
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
89
- className
90
- ),
91
- ...props
92
- }
93
- );
94
- }
95
81
  function CardContent({ className, ...props }) {
96
82
  return /* @__PURE__ */ jsxRuntime.jsx(
97
83
  "div",
@@ -102,6 +88,424 @@ function CardContent({ className, ...props }) {
102
88
  }
103
89
  );
104
90
  }
91
+ function normalizePhoneNumber(input) {
92
+ const trimmed = input.trim();
93
+ if (trimmed.toLowerCase().startsWith("tel:")) {
94
+ return trimmed;
95
+ }
96
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
97
+ if (match) {
98
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
99
+ const extension = match[3];
100
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
101
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
102
+ return `tel:${withExtension}`;
103
+ }
104
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
105
+ return `tel:${cleaned}`;
106
+ }
107
+ function normalizeEmail(input) {
108
+ const trimmed = input.trim();
109
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
110
+ return trimmed;
111
+ }
112
+ return `mailto:${trimmed}`;
113
+ }
114
+ function isEmail(input) {
115
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
116
+ return emailRegex.test(input.trim());
117
+ }
118
+ function isPhoneNumber(input) {
119
+ const trimmed = input.trim();
120
+ if (trimmed.toLowerCase().startsWith("tel:")) {
121
+ return true;
122
+ }
123
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
124
+ return phoneRegex.test(trimmed);
125
+ }
126
+ function isInternalUrl(href) {
127
+ if (typeof window === "undefined") {
128
+ return href.startsWith("/") && !href.startsWith("//");
129
+ }
130
+ const trimmed = href.trim();
131
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
132
+ return true;
133
+ }
134
+ try {
135
+ const url = new URL(trimmed, window.location.href);
136
+ const currentOrigin = window.location.origin;
137
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
138
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
143
+ function toRelativePath(href) {
144
+ if (typeof window === "undefined") {
145
+ return href;
146
+ }
147
+ const trimmed = href.trim();
148
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
149
+ return trimmed;
150
+ }
151
+ try {
152
+ const url = new URL(trimmed, window.location.href);
153
+ const currentOrigin = window.location.origin;
154
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
155
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
156
+ return url.pathname + url.search + url.hash;
157
+ }
158
+ } catch {
159
+ }
160
+ return trimmed;
161
+ }
162
+ function useNavigation({
163
+ href,
164
+ onClick
165
+ } = {}) {
166
+ const linkType = React__namespace.useMemo(() => {
167
+ if (!href || href.trim() === "") {
168
+ return onClick ? "none" : "none";
169
+ }
170
+ const trimmed = href.trim();
171
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
172
+ return "mailto";
173
+ }
174
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
175
+ return "tel";
176
+ }
177
+ if (isInternalUrl(trimmed)) {
178
+ return "internal";
179
+ }
180
+ try {
181
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
182
+ return "external";
183
+ } catch {
184
+ return "internal";
185
+ }
186
+ }, [href, onClick]);
187
+ const normalizedHref = React__namespace.useMemo(() => {
188
+ if (!href || href.trim() === "") {
189
+ return void 0;
190
+ }
191
+ const trimmed = href.trim();
192
+ switch (linkType) {
193
+ case "tel":
194
+ return normalizePhoneNumber(trimmed);
195
+ case "mailto":
196
+ return normalizeEmail(trimmed);
197
+ case "internal":
198
+ return toRelativePath(trimmed);
199
+ case "external":
200
+ return trimmed;
201
+ default:
202
+ return trimmed;
203
+ }
204
+ }, [href, linkType]);
205
+ const target = React__namespace.useMemo(() => {
206
+ switch (linkType) {
207
+ case "external":
208
+ return "_blank";
209
+ case "internal":
210
+ return "_self";
211
+ case "mailto":
212
+ case "tel":
213
+ return void 0;
214
+ default:
215
+ return void 0;
216
+ }
217
+ }, [linkType]);
218
+ const rel = React__namespace.useMemo(() => {
219
+ if (linkType === "external") {
220
+ return "noopener noreferrer";
221
+ }
222
+ return void 0;
223
+ }, [linkType]);
224
+ const isExternal = linkType === "external";
225
+ const isInternal = linkType === "internal";
226
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
227
+ const handleClick = React__namespace.useCallback(
228
+ (event) => {
229
+ if (onClick) {
230
+ try {
231
+ onClick(event);
232
+ } catch (error) {
233
+ console.error("Error in user onClick handler:", error);
234
+ }
235
+ }
236
+ if (event.defaultPrevented) {
237
+ return;
238
+ }
239
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
240
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
241
+ if (typeof window !== "undefined") {
242
+ const handler = window.__opensiteNavigationHandler;
243
+ if (typeof handler === "function") {
244
+ try {
245
+ const handled = handler(normalizedHref, event.nativeEvent || event);
246
+ if (handled !== false) {
247
+ event.preventDefault();
248
+ }
249
+ } catch (error) {
250
+ console.error("Error in navigation handler:", error);
251
+ }
252
+ }
253
+ }
254
+ }
255
+ },
256
+ [onClick, shouldUseRouter, normalizedHref]
257
+ );
258
+ return {
259
+ linkType,
260
+ normalizedHref,
261
+ target,
262
+ rel,
263
+ isExternal,
264
+ isInternal,
265
+ shouldUseRouter,
266
+ handleClick
267
+ };
268
+ }
269
+ var baseStyles = [
270
+ // Layout
271
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
272
+ // Typography - using CSS variables with sensible defaults
273
+ "font-[var(--button-font-family,inherit)]",
274
+ "font-[var(--button-font-weight,500)]",
275
+ "tracking-[var(--button-letter-spacing,0)]",
276
+ "leading-[var(--button-line-height,1.25)]",
277
+ "[text-transform:var(--button-text-transform,none)]",
278
+ "text-sm",
279
+ // Border radius
280
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
281
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
282
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
283
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
284
+ "[box-shadow:var(--button-shadow,none)]",
285
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
286
+ // Disabled state
287
+ "disabled:pointer-events-none disabled:opacity-50",
288
+ // SVG handling
289
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
290
+ // Focus styles
291
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
292
+ // Invalid state
293
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
294
+ ].join(" ");
295
+ var buttonVariants = classVarianceAuthority.cva(baseStyles, {
296
+ variants: {
297
+ variant: {
298
+ // Default (Primary) variant - full customization
299
+ default: [
300
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
301
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
302
+ "border-[length:var(--button-default-border-width,0px)]",
303
+ "border-[color:var(--button-default-border,transparent)]",
304
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
305
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
306
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
307
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
308
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
309
+ ].join(" "),
310
+ // Destructive variant - full customization
311
+ destructive: [
312
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
313
+ "text-[var(--button-destructive-fg,white)]",
314
+ "border-[length:var(--button-destructive-border-width,0px)]",
315
+ "border-[color:var(--button-destructive-border,transparent)]",
316
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
317
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
318
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
319
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
320
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
321
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
322
+ "dark:bg-destructive/60"
323
+ ].join(" "),
324
+ // Outline variant - full customization with proper border handling
325
+ outline: [
326
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
327
+ "text-[var(--button-outline-fg,inherit)]",
328
+ "border-[length:var(--button-outline-border-width,1px)]",
329
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
330
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
331
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
332
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
333
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
334
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
335
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
336
+ ].join(" "),
337
+ // Secondary variant - full customization
338
+ secondary: [
339
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
340
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
341
+ "border-[length:var(--button-secondary-border-width,0px)]",
342
+ "border-[color:var(--button-secondary-border,transparent)]",
343
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
344
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
345
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
346
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
347
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
348
+ ].join(" "),
349
+ // Ghost variant - full customization
350
+ ghost: [
351
+ "bg-[var(--button-ghost-bg,transparent)]",
352
+ "text-[var(--button-ghost-fg,inherit)]",
353
+ "border-[length:var(--button-ghost-border-width,0px)]",
354
+ "border-[color:var(--button-ghost-border,transparent)]",
355
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
356
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
357
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
358
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
359
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
360
+ "dark:hover:bg-accent/50"
361
+ ].join(" "),
362
+ // Link variant - full customization
363
+ link: [
364
+ "bg-[var(--button-link-bg,transparent)]",
365
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
366
+ "border-[length:var(--button-link-border-width,0px)]",
367
+ "border-[color:var(--button-link-border,transparent)]",
368
+ "[box-shadow:var(--button-link-shadow,none)]",
369
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
370
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
371
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
372
+ "underline-offset-4 hover:underline"
373
+ ].join(" ")
374
+ },
375
+ size: {
376
+ default: [
377
+ "h-[var(--button-height-md,2.25rem)]",
378
+ "px-[var(--button-padding-x-md,1rem)]",
379
+ "py-[var(--button-padding-y-md,0.5rem)]",
380
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
381
+ ].join(" "),
382
+ sm: [
383
+ "h-[var(--button-height-sm,2rem)]",
384
+ "px-[var(--button-padding-x-sm,0.75rem)]",
385
+ "py-[var(--button-padding-y-sm,0.25rem)]",
386
+ "gap-1.5",
387
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
388
+ ].join(" "),
389
+ md: [
390
+ "h-[var(--button-height-md,2.25rem)]",
391
+ "px-[var(--button-padding-x-md,1rem)]",
392
+ "py-[var(--button-padding-y-md,0.5rem)]",
393
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
394
+ ].join(" "),
395
+ lg: [
396
+ "h-[var(--button-height-lg,2.5rem)]",
397
+ "px-[var(--button-padding-x-lg,1.5rem)]",
398
+ "py-[var(--button-padding-y-lg,0.5rem)]",
399
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
400
+ ].join(" "),
401
+ icon: "size-[var(--button-height-md,2.25rem)]",
402
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
403
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
404
+ }
405
+ },
406
+ defaultVariants: {
407
+ variant: "default",
408
+ size: "default"
409
+ }
410
+ });
411
+ var Pressable = React__namespace.forwardRef(
412
+ ({
413
+ children,
414
+ className,
415
+ href,
416
+ onClick,
417
+ variant,
418
+ size,
419
+ asButton = false,
420
+ fallbackComponentType = "span",
421
+ componentType,
422
+ "aria-label": ariaLabel,
423
+ "aria-describedby": ariaDescribedby,
424
+ id,
425
+ ...props
426
+ }, ref) => {
427
+ const navigation = useNavigation({ href, onClick });
428
+ const {
429
+ normalizedHref,
430
+ target,
431
+ rel,
432
+ linkType,
433
+ isInternal,
434
+ handleClick
435
+ } = navigation;
436
+ const shouldRenderLink = normalizedHref && linkType !== "none";
437
+ const shouldRenderButton = !shouldRenderLink && onClick;
438
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
439
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
440
+ const shouldApplyButtonStyles = asButton || variant || size;
441
+ const combinedClassName = cn(
442
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
443
+ className
444
+ );
445
+ const dataProps = Object.fromEntries(
446
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
447
+ );
448
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
449
+ "data-slot": "button",
450
+ "data-variant": variant ?? "default",
451
+ "data-size": size ?? "default"
452
+ } : {};
453
+ const commonProps = {
454
+ className: combinedClassName,
455
+ onClick: handleClick,
456
+ "aria-label": ariaLabel,
457
+ "aria-describedby": ariaDescribedby,
458
+ id,
459
+ ...dataProps,
460
+ ...buttonDataAttributes
461
+ };
462
+ if (finalComponentType === "a" && shouldRenderLink) {
463
+ return /* @__PURE__ */ jsxRuntime.jsx(
464
+ "a",
465
+ {
466
+ ref,
467
+ href: normalizedHref,
468
+ target,
469
+ rel,
470
+ ...commonProps,
471
+ ...props,
472
+ children
473
+ }
474
+ );
475
+ }
476
+ if (finalComponentType === "button") {
477
+ return /* @__PURE__ */ jsxRuntime.jsx(
478
+ "button",
479
+ {
480
+ ref,
481
+ type: props.type || "button",
482
+ ...commonProps,
483
+ ...props,
484
+ children
485
+ }
486
+ );
487
+ }
488
+ if (finalComponentType === "div") {
489
+ return /* @__PURE__ */ jsxRuntime.jsx(
490
+ "div",
491
+ {
492
+ ref,
493
+ ...commonProps,
494
+ children
495
+ }
496
+ );
497
+ }
498
+ return /* @__PURE__ */ jsxRuntime.jsx(
499
+ "span",
500
+ {
501
+ ref,
502
+ ...commonProps,
503
+ children
504
+ }
505
+ );
506
+ }
507
+ );
508
+ Pressable.displayName = "Pressable";
105
509
  var maxWidthStyles = {
106
510
  sm: "max-w-screen-sm",
107
511
  md: "max-w-screen-md",
@@ -111,7 +515,7 @@ var maxWidthStyles = {
111
515
  "4xl": "max-w-[1536px]",
112
516
  full: "max-w-full"
113
517
  };
114
- var Container = React__default.default.forwardRef(
518
+ var Container = React__namespace.default.forwardRef(
115
519
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
116
520
  const Component = as;
117
521
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -417,7 +821,7 @@ var spacingStyles = {
417
821
  };
418
822
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
419
823
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
420
- var Section = React__default.default.forwardRef(
824
+ var Section = React__namespace.default.forwardRef(
421
825
  ({
422
826
  id,
423
827
  title,
@@ -541,10 +945,18 @@ function TestimonialsMarquee({
541
945
  const authorName = getAuthorName(testimonial);
542
946
  const avatarSrc = getAvatarSrc(testimonial);
543
947
  return /* @__PURE__ */ jsxRuntime.jsx(
544
- Card,
948
+ Pressable,
545
949
  {
546
- className: cn("w-80 shrink-0", cardClassName),
547
- children: /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "p-6", children: [
950
+ href: testimonial?.linkConfig?.href,
951
+ className: cn(
952
+ "bg-card text-card-foreground",
953
+ "rounded-2xl border shadow-xl",
954
+ "cursor-pointer transition-all duration-500",
955
+ "hover:bg-primary hover:text-primary-foreground",
956
+ "flex flex-col gap-6 w-80 shrink-0",
957
+ cardClassName
958
+ ),
959
+ children: /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "p-6 h-full flex flex-col justify-between gap-12", children: [
548
960
  testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsxs(
549
961
  "p",
550
962
  {
@@ -562,15 +974,15 @@ function TestimonialsMarquee({
562
974
  /* @__PURE__ */ jsxRuntime.jsxs(
563
975
  "div",
564
976
  {
565
- className: cn("flex items-center gap-3", authorClassName),
977
+ className: cn("flex items-center gap-4", authorClassName),
566
978
  children: [
567
- /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-9", children: [
979
+ /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "relative flex shrink-0 overflow-hidden rounded-full size-10 ring-4 ring-primary shadow-lg", children: [
568
980
  /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
569
981
  /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "text-xs", children: getInitials(authorName) })
570
982
  ] }),
571
983
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
572
- testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: testimonial.author }) : testimonial.author),
573
- testimonial.role && (typeof testimonial.role === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs", children: testimonial.role }) : testimonial.role)
984
+ testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-medium", children: testimonial.author }) : testimonial.author),
985
+ testimonial.role && (typeof testimonial.role === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: testimonial.role }) : testimonial.role)
574
986
  ] })
575
987
  ]
576
988
  }
@@ -608,18 +1020,18 @@ function TestimonialsMarquee({
608
1020
  className: cn("overflow-hidden", className),
609
1021
  containerClassName,
610
1022
  children: [
611
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-12", headerClassName), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-2xl text-center", children: [
1023
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-12", headerClassName), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-full md:max-w-2xl text-center space-y-2", children: [
612
1024
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
613
1025
  "h2",
614
1026
  {
615
1027
  className: cn(
616
- "text-3xl font-semibold tracking-tight md:text-4xl",
1028
+ "text-3xl font-semibold tracking-tight md:text-4xl lg:text-6xl text-pretty",
617
1029
  headingClassName
618
1030
  ),
619
1031
  children: heading
620
1032
  }
621
1033
  ) : heading),
622
- description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-4 text-lg", descriptionClassName), children: description }) : description)
1034
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description)
623
1035
  ] }) }),
624
1036
  renderedTestimonials,
625
1037
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `