@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
@@ -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,
@@ -499,7 +903,8 @@ function TestimonialsMarquee({
499
903
  quoteClassName,
500
904
  authorClassName,
501
905
  background,
502
- spacing,
906
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
907
+ spacing = "xl",
503
908
  pattern,
504
909
  patternOpacity
505
910
  }) {
@@ -509,81 +914,102 @@ function TestimonialsMarquee({
509
914
  if (typeof testimonial.author === "string") return testimonial.author;
510
915
  return "";
511
916
  }, []);
512
- const getAvatarSrc = React.useCallback((testimonial) => {
513
- return testimonial.avatarSrc || testimonial.avatar?.src;
514
- }, []);
917
+ const getAvatarSrc = React.useCallback(
918
+ (testimonial) => {
919
+ return testimonial.avatarSrc || testimonial.avatar?.src;
920
+ },
921
+ []
922
+ );
515
923
  const getInitials = React.useCallback((name) => {
516
924
  return name.split(" ").map((n) => n[0]).join("");
517
925
  }, []);
518
926
  const renderedTestimonials = React.useMemo(() => {
519
927
  if (testimonialsSlot) return testimonialsSlot;
520
928
  if (!testimonials || testimonials.length === 0) return null;
521
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", marqueeClassName), children: [
522
- /* @__PURE__ */ jsxRuntime.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" }),
523
- /* @__PURE__ */ jsxRuntime.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" }),
524
- /* @__PURE__ */ jsxRuntime.jsx(
525
- "div",
526
- {
527
- className: cn(
528
- "flex gap-4",
529
- pauseOnHover !== false && "[&:hover_.marquee-content]:pause"
530
- ),
531
- children: /* @__PURE__ */ jsxRuntime.jsx(
532
- "div",
533
- {
534
- className: "marquee-content flex shrink-0 animate-marquee gap-4",
535
- style: {
536
- animationDuration: speedMap[effectiveSpeed]
537
- },
538
- children: duplicatedTestimonials.map((testimonial, index) => {
539
- const authorName = getAuthorName(testimonial);
540
- const avatarSrc = getAvatarSrc(testimonial);
541
- return /* @__PURE__ */ jsxRuntime.jsx(
542
- Card,
543
- {
544
- className: cn("w-80 shrink-0", cardClassName),
545
- children: /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "p-6", children: [
546
- testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsxs(
547
- "p",
548
- {
549
- className: cn(
550
- "mb-4 text-sm leading-relaxed",
551
- quoteClassName
552
- ),
553
- children: [
554
- "\u201C",
555
- testimonial.quote,
556
- "\u201D"
557
- ]
558
- }
559
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-4", quoteClassName), children: testimonial.quote })),
560
- /* @__PURE__ */ jsxRuntime.jsxs(
561
- "div",
562
- {
563
- className: cn("flex items-center gap-3", authorClassName),
564
- children: [
565
- /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-9", children: [
566
- /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
567
- /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "text-xs", children: getInitials(authorName) })
568
- ] }),
569
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
570
- testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: testimonial.author }) : testimonial.author),
571
- testimonial.role && (typeof testimonial.role === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: testimonial.role }) : testimonial.role)
572
- ] })
573
- ]
574
- }
575
- )
576
- ] })
577
- },
578
- index
579
- );
580
- })
581
- }
582
- )
583
- }
584
- )
585
- ] });
586
- }, [testimonialsSlot, marqueeClassName, pauseOnHover, effectiveSpeed, duplicatedTestimonials, cardClassName, quoteClassName, authorClassName, testimonials, getAuthorName, getAvatarSrc, getInitials]);
929
+ return /* @__PURE__ */ jsxRuntime.jsx(
930
+ "div",
931
+ {
932
+ className: cn(
933
+ "relative marquee-fade",
934
+ pauseOnHover && "marquee-pause-on-hover",
935
+ marqueeClassName
936
+ ),
937
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-4", children: /* @__PURE__ */ jsxRuntime.jsx(
938
+ "div",
939
+ {
940
+ className: "marquee-content flex shrink-0 animate-marquee gap-4",
941
+ style: {
942
+ animationDuration: speedMap[effectiveSpeed]
943
+ },
944
+ children: duplicatedTestimonials.map((testimonial, index) => {
945
+ const authorName = getAuthorName(testimonial);
946
+ const avatarSrc = getAvatarSrc(testimonial);
947
+ return /* @__PURE__ */ jsxRuntime.jsx(
948
+ Pressable,
949
+ {
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: [
960
+ testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsxs(
961
+ "p",
962
+ {
963
+ className: cn(
964
+ "mb-4 text-sm leading-relaxed",
965
+ quoteClassName
966
+ ),
967
+ children: [
968
+ "\u201C",
969
+ testimonial.quote,
970
+ "\u201D"
971
+ ]
972
+ }
973
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-4", quoteClassName), children: testimonial.quote })),
974
+ /* @__PURE__ */ jsxRuntime.jsxs(
975
+ "div",
976
+ {
977
+ className: cn("flex items-center gap-4", authorClassName),
978
+ children: [
979
+ /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "relative flex shrink-0 overflow-hidden rounded-full size-10 ring-4 ring-primary shadow-lg", children: [
980
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
981
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { className: "text-xs", children: getInitials(authorName) })
982
+ ] }),
983
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
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)
986
+ ] })
987
+ ]
988
+ }
989
+ )
990
+ ] })
991
+ },
992
+ index
993
+ );
994
+ })
995
+ }
996
+ ) })
997
+ }
998
+ );
999
+ }, [
1000
+ testimonialsSlot,
1001
+ marqueeClassName,
1002
+ pauseOnHover,
1003
+ effectiveSpeed,
1004
+ duplicatedTestimonials,
1005
+ cardClassName,
1006
+ quoteClassName,
1007
+ authorClassName,
1008
+ testimonials,
1009
+ getAuthorName,
1010
+ getAvatarSrc,
1011
+ getInitials
1012
+ ]);
587
1013
  return /* @__PURE__ */ jsxRuntime.jsxs(
588
1014
  Section,
589
1015
  {
@@ -592,28 +1018,20 @@ function TestimonialsMarquee({
592
1018
  pattern,
593
1019
  patternOpacity,
594
1020
  className: cn("overflow-hidden", className),
1021
+ containerClassName,
595
1022
  children: [
596
- /* @__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: [
597
1024
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
598
1025
  "h2",
599
1026
  {
600
1027
  className: cn(
601
- "text-3xl font-semibold tracking-tight md:text-4xl",
1028
+ "text-3xl font-semibold tracking-tight md:text-4xl lg:text-6xl text-pretty",
602
1029
  headingClassName
603
1030
  ),
604
1031
  children: heading
605
1032
  }
606
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
607
- description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
608
- "p",
609
- {
610
- className: cn(
611
- "mt-4 text-lg text-muted-foreground",
612
- descriptionClassName
613
- ),
614
- children: description
615
- }
616
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-4", descriptionClassName), children: description }))
1033
+ ) : heading),
1034
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description)
617
1035
  ] }) }),
618
1036
  renderedTestimonials,
619
1037
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
@@ -628,9 +1046,13 @@ function TestimonialsMarquee({
628
1046
  .animate-marquee {
629
1047
  animation: marquee linear infinite;
630
1048
  }
631
- .pause {
1049
+ .marquee-pause-on-hover:hover .marquee-content {
632
1050
  animation-play-state: paused;
633
1051
  }
1052
+ .marquee-fade {
1053
+ -webkit-mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
1054
+ mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
1055
+ }
634
1056
  ` })
635
1057
  ]
636
1058
  }