@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,12 +1,13 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React = require('react');
4
+ var React2 = require('react');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var icon = require('@page-speed/icon');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
  var AvatarPrimitive = require('@radix-ui/react-avatar');
10
+ var classVarianceAuthority = require('class-variance-authority');
10
11
  var img = require('@page-speed/img');
11
12
 
12
13
  function _interopNamespace(e) {
@@ -27,7 +28,7 @@ function _interopNamespace(e) {
27
28
  return Object.freeze(n);
28
29
  }
29
30
 
30
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
31
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
31
32
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
32
33
 
33
34
  // components/blocks/testimonials/testimonials-split-image.tsx
@@ -35,7 +36,7 @@ function cn(...inputs) {
35
36
  return tailwindMerge.twMerge(clsx.clsx(inputs));
36
37
  }
37
38
  var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
38
- var DynamicIcon = React__namespace.memo(function DynamicIcon2({
39
+ var DynamicIcon = React2__namespace.memo(function DynamicIcon2({
39
40
  apiKey,
40
41
  ...props
41
42
  }) {
@@ -87,6 +88,424 @@ function AvatarFallback({
87
88
  }
88
89
  );
89
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 = React2__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 = React2__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 = React2__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 = React2__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 = React2__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 = React2__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";
90
509
  var maxWidthStyles = {
91
510
  sm: "max-w-screen-sm",
92
511
  md: "max-w-screen-md",
@@ -96,7 +515,7 @@ var maxWidthStyles = {
96
515
  "4xl": "max-w-[1536px]",
97
516
  full: "max-w-full"
98
517
  };
99
- var Container = React__namespace.default.forwardRef(
518
+ var Container = React2__namespace.default.forwardRef(
100
519
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
101
520
  const Component = as;
102
521
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -402,7 +821,7 @@ var spacingStyles = {
402
821
  };
403
822
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
404
823
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
405
- var Section = React__namespace.default.forwardRef(
824
+ var Section = React2__namespace.default.forwardRef(
406
825
  ({
407
826
  id,
408
827
  title,
@@ -484,17 +903,17 @@ function TestimonialsSplitImage({
484
903
  optixFlowConfig
485
904
  }) {
486
905
  const effectiveImagePosition = imagePosition || "left";
487
- const getAuthorName = React.useCallback(() => {
906
+ const getAuthorName = React2.useCallback(() => {
488
907
  if (typeof testimonial?.author === "string") return testimonial.author;
489
908
  return "";
490
909
  }, [testimonial?.author]);
491
- const getAvatarSrc = React.useCallback(() => {
910
+ const getAvatarSrc = React2.useCallback(() => {
492
911
  return testimonial?.avatarSrc || testimonial?.avatar?.src;
493
912
  }, [testimonial?.avatarSrc, testimonial?.avatar?.src]);
494
- const getInitials = React.useCallback((name) => {
913
+ const getInitials = React2.useCallback((name) => {
495
914
  return name.split(" ").map((n) => n[0]).join("");
496
915
  }, []);
497
- const renderedTestimonial = React.useMemo(() => {
916
+ const renderedTestimonial = React2.useMemo(() => {
498
917
  if (testimonialSlot) return testimonialSlot;
499
918
  if (!testimonial) return null;
500
919
  const authorName = getAuthorName();
@@ -511,32 +930,44 @@ function TestimonialsSplitImage({
511
930
  /* @__PURE__ */ jsxRuntime.jsx(
512
931
  DynamicIcon,
513
932
  {
514
- name: "lucide/quote",
933
+ name: "mdi/comment-quote-outline",
515
934
  size: 48,
516
- className: cn("text-primary/20", quoteIconClassName)
935
+ className: quoteIconClassName
517
936
  }
518
937
  ),
519
938
  testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
520
939
  "blockquote",
521
940
  {
522
941
  className: cn(
523
- "text-xl font-medium leading-relaxed md:text-2xl",
942
+ "text-lg font-light leading-relaxed md:text-2xl lg:text-3xl",
524
943
  quoteClassName
525
944
  ),
526
945
  children: testimonial.quote
527
946
  }
528
947
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: quoteClassName, children: testimonial.quote })),
529
948
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-4 pt-4", authorClassName), children: [
530
- /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "size-12", children: [
949
+ /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: "relative flex shrink-0 overflow-hidden shadow-xl rounded-2xl size-18", children: [
531
950
  /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatarSrc, alt: authorName }),
532
951
  /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: getInitials(authorName) })
533
952
  ] }),
534
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
953
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0", children: [
535
954
  testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold", children: testimonial.author }) : testimonial.author),
536
955
  (testimonial.role || testimonial.company) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm ", children: [
537
956
  testimonial.role && (typeof testimonial.role === "string" ? testimonial.role : testimonial.role),
538
957
  testimonial.company && (typeof testimonial.company === "string" ? ` at ${testimonial.company}` : testimonial.company)
539
- ] })
958
+ ] }),
959
+ testimonial.linkConfig?.href && /* @__PURE__ */ jsxRuntime.jsx(
960
+ Pressable,
961
+ {
962
+ href: testimonial.linkConfig.href,
963
+ className: cn(
964
+ testimonial.linkConfig.className,
965
+ "text-sm font-bold tracking-wide uppercase",
966
+ "hover:underline hover:underline-offset-2"
967
+ ),
968
+ children: testimonial.linkConfig.label
969
+ }
970
+ )
540
971
  ] })
541
972
  ] })
542
973
  ]
@@ -566,13 +997,17 @@ function TestimonialsSplitImage({
566
997
  children: /* @__PURE__ */ jsxRuntime.jsxs(
567
998
  "div",
568
999
  {
569
- className: cn("grid items-center gap-12 lg:grid-cols-2", gridClassName),
1000
+ className: cn(
1001
+ "grid items-center gap-10 md:gap-12 grid-cols-1 lg:grid-cols-2",
1002
+ gridClassName
1003
+ ),
570
1004
  children: [
571
1005
  imageSrc && /* @__PURE__ */ jsxRuntime.jsx(
572
1006
  "div",
573
1007
  {
574
1008
  className: cn(
575
- "relative aspect-4/3 overflow-hidden rounded-2xl lg:aspect-square",
1009
+ "shadow-xl rounded-2xl",
1010
+ "relative aspect-4/3 overflow-hidden lg:aspect-square",
576
1011
  effectiveImagePosition === "right" && "lg:order-2",
577
1012
  imageClassName
578
1013
  ),