@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,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,
@@ -474,7 +881,8 @@ function TestimonialsMarquee({
474
881
  quoteClassName,
475
882
  authorClassName,
476
883
  background,
477
- spacing,
884
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
885
+ spacing = "xl",
478
886
  pattern,
479
887
  patternOpacity
480
888
  }) {
@@ -484,81 +892,102 @@ function TestimonialsMarquee({
484
892
  if (typeof testimonial.author === "string") return testimonial.author;
485
893
  return "";
486
894
  }, []);
487
- const getAvatarSrc = useCallback((testimonial) => {
488
- return testimonial.avatarSrc || testimonial.avatar?.src;
489
- }, []);
895
+ const getAvatarSrc = useCallback(
896
+ (testimonial) => {
897
+ return testimonial.avatarSrc || testimonial.avatar?.src;
898
+ },
899
+ []
900
+ );
490
901
  const getInitials = useCallback((name) => {
491
902
  return name.split(" ").map((n) => n[0]).join("");
492
903
  }, []);
493
904
  const renderedTestimonials = useMemo(() => {
494
905
  if (testimonialsSlot) return testimonialsSlot;
495
906
  if (!testimonials || testimonials.length === 0) return null;
496
- return /* @__PURE__ */ jsxs("div", { className: cn("relative", marqueeClassName), children: [
497
- /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute left-0 top-0 z-10 h-full w-24 bg-gradient-to-r from-background to-transparent" }),
498
- /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute right-0 top-0 z-10 h-full w-24 bg-gradient-to-l from-background to-transparent" }),
499
- /* @__PURE__ */ jsx(
500
- "div",
501
- {
502
- className: cn(
503
- "flex gap-4",
504
- pauseOnHover !== false && "[&:hover_.marquee-content]:pause"
505
- ),
506
- children: /* @__PURE__ */ jsx(
507
- "div",
508
- {
509
- className: "marquee-content flex shrink-0 animate-marquee gap-4",
510
- style: {
511
- animationDuration: speedMap[effectiveSpeed]
512
- },
513
- children: duplicatedTestimonials.map((testimonial, index) => {
514
- const authorName = getAuthorName(testimonial);
515
- const avatarSrc = getAvatarSrc(testimonial);
516
- return /* @__PURE__ */ jsx(
517
- Card,
518
- {
519
- className: cn("w-80 shrink-0", cardClassName),
520
- children: /* @__PURE__ */ jsxs(CardContent, { className: "p-6", children: [
521
- testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxs(
522
- "p",
523
- {
524
- className: cn(
525
- "mb-4 text-sm leading-relaxed",
526
- quoteClassName
527
- ),
528
- children: [
529
- "\u201C",
530
- testimonial.quote,
531
- "\u201D"
532
- ]
533
- }
534
- ) : /* @__PURE__ */ jsx("div", { className: cn("mb-4", quoteClassName), children: testimonial.quote })),
535
- /* @__PURE__ */ jsxs(
536
- "div",
537
- {
538
- className: cn("flex items-center gap-3", authorClassName),
539
- children: [
540
- /* @__PURE__ */ jsxs(Avatar, { className: "size-9", children: [
541
- /* @__PURE__ */ jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
542
- /* @__PURE__ */ jsx(AvatarFallback, { className: "text-xs", children: getInitials(authorName) })
543
- ] }),
544
- /* @__PURE__ */ jsxs("div", { children: [
545
- testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: testimonial.author }) : testimonial.author),
546
- testimonial.role && (typeof testimonial.role === "string" ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: testimonial.role }) : testimonial.role)
547
- ] })
548
- ]
549
- }
550
- )
551
- ] })
552
- },
553
- index
554
- );
555
- })
556
- }
557
- )
558
- }
559
- )
560
- ] });
561
- }, [testimonialsSlot, marqueeClassName, pauseOnHover, effectiveSpeed, duplicatedTestimonials, cardClassName, quoteClassName, authorClassName, testimonials, getAuthorName, getAvatarSrc, getInitials]);
907
+ return /* @__PURE__ */ jsx(
908
+ "div",
909
+ {
910
+ className: cn(
911
+ "relative marquee-fade",
912
+ pauseOnHover && "marquee-pause-on-hover",
913
+ marqueeClassName
914
+ ),
915
+ children: /* @__PURE__ */ jsx("div", { className: "flex gap-4", children: /* @__PURE__ */ jsx(
916
+ "div",
917
+ {
918
+ className: "marquee-content flex shrink-0 animate-marquee gap-4",
919
+ style: {
920
+ animationDuration: speedMap[effectiveSpeed]
921
+ },
922
+ children: duplicatedTestimonials.map((testimonial, index) => {
923
+ const authorName = getAuthorName(testimonial);
924
+ const avatarSrc = getAvatarSrc(testimonial);
925
+ return /* @__PURE__ */ jsx(
926
+ Pressable,
927
+ {
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: [
938
+ testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxs(
939
+ "p",
940
+ {
941
+ className: cn(
942
+ "mb-4 text-sm leading-relaxed",
943
+ quoteClassName
944
+ ),
945
+ children: [
946
+ "\u201C",
947
+ testimonial.quote,
948
+ "\u201D"
949
+ ]
950
+ }
951
+ ) : /* @__PURE__ */ jsx("div", { className: cn("mb-4", quoteClassName), children: testimonial.quote })),
952
+ /* @__PURE__ */ jsxs(
953
+ "div",
954
+ {
955
+ className: cn("flex items-center gap-4", authorClassName),
956
+ children: [
957
+ /* @__PURE__ */ jsxs(Avatar, { className: "relative flex shrink-0 overflow-hidden rounded-full size-10 ring-4 ring-primary shadow-lg", children: [
958
+ /* @__PURE__ */ jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
959
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-xs", children: getInitials(authorName) })
960
+ ] }),
961
+ /* @__PURE__ */ jsxs("div", { children: [
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)
964
+ ] })
965
+ ]
966
+ }
967
+ )
968
+ ] })
969
+ },
970
+ index
971
+ );
972
+ })
973
+ }
974
+ ) })
975
+ }
976
+ );
977
+ }, [
978
+ testimonialsSlot,
979
+ marqueeClassName,
980
+ pauseOnHover,
981
+ effectiveSpeed,
982
+ duplicatedTestimonials,
983
+ cardClassName,
984
+ quoteClassName,
985
+ authorClassName,
986
+ testimonials,
987
+ getAuthorName,
988
+ getAvatarSrc,
989
+ getInitials
990
+ ]);
562
991
  return /* @__PURE__ */ jsxs(
563
992
  Section,
564
993
  {
@@ -567,28 +996,20 @@ function TestimonialsMarquee({
567
996
  pattern,
568
997
  patternOpacity,
569
998
  className: cn("overflow-hidden", className),
999
+ containerClassName,
570
1000
  children: [
571
- /* @__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: [
572
1002
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
573
1003
  "h2",
574
1004
  {
575
1005
  className: cn(
576
- "text-3xl font-semibold tracking-tight md:text-4xl",
1006
+ "text-3xl font-semibold tracking-tight md:text-4xl lg:text-6xl text-pretty",
577
1007
  headingClassName
578
1008
  ),
579
1009
  children: heading
580
1010
  }
581
- ) : /* @__PURE__ */ jsx("div", { className: headingClassName, children: heading })),
582
- description && (typeof description === "string" ? /* @__PURE__ */ jsx(
583
- "p",
584
- {
585
- className: cn(
586
- "mt-4 text-lg text-muted-foreground",
587
- descriptionClassName
588
- ),
589
- children: description
590
- }
591
- ) : /* @__PURE__ */ jsx("div", { className: cn("mt-4", descriptionClassName), children: description }))
1011
+ ) : heading),
1012
+ description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description)
592
1013
  ] }) }),
593
1014
  renderedTestimonials,
594
1015
  /* @__PURE__ */ jsx("style", { children: `
@@ -603,9 +1024,13 @@ function TestimonialsMarquee({
603
1024
  .animate-marquee {
604
1025
  animation: marquee linear infinite;
605
1026
  }
606
- .pause {
1027
+ .marquee-pause-on-hover:hover .marquee-content {
607
1028
  animation-play-state: paused;
608
1029
  }
1030
+ .marquee-fade {
1031
+ -webkit-mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
1032
+ mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
1033
+ }
609
1034
  ` })
610
1035
  ]
611
1036
  }