@opensite/ui 2.0.5 → 2.0.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 (75) hide show
  1. package/dist/hero-adaptable-product-grid.cjs +11 -8
  2. package/dist/hero-adaptable-product-grid.d.cts +1 -1
  3. package/dist/hero-adaptable-product-grid.d.ts +1 -1
  4. package/dist/hero-adaptable-product-grid.js +11 -8
  5. package/dist/hero-business-operations-mosaic.cjs +542 -22
  6. package/dist/hero-business-operations-mosaic.d.cts +20 -8
  7. package/dist/hero-business-operations-mosaic.d.ts +20 -8
  8. package/dist/hero-business-operations-mosaic.js +542 -19
  9. package/dist/hero-centered-gradient-cta.cjs +3 -3
  10. package/dist/hero-centered-gradient-cta.js +3 -3
  11. package/dist/hero-community-survey-cta.cjs +3 -2
  12. package/dist/hero-community-survey-cta.js +3 -2
  13. package/dist/hero-conversion-video-play.cjs +1 -1
  14. package/dist/hero-conversion-video-play.js +1 -1
  15. package/dist/hero-crm-streamlined.cjs +4 -4
  16. package/dist/hero-crm-streamlined.js +4 -4
  17. package/dist/hero-design-showcase-logos.cjs +4 -1
  18. package/dist/hero-design-showcase-logos.js +4 -1
  19. package/dist/hero-design-system-3d.cjs +1 -1
  20. package/dist/hero-design-system-3d.js +1 -1
  21. package/dist/hero-feature-cards-grid.cjs +2 -2
  22. package/dist/hero-feature-cards-grid.js +2 -2
  23. package/dist/hero-fullscreen-background-image.cjs +4 -3
  24. package/dist/hero-fullscreen-background-image.js +4 -3
  25. package/dist/hero-fullscreen-logo-cta.cjs +7 -5
  26. package/dist/hero-fullscreen-logo-cta.js +7 -5
  27. package/dist/hero-gradient-avatars-rating.cjs +3 -3
  28. package/dist/hero-gradient-avatars-rating.js +3 -3
  29. package/dist/hero-gradient-client-focused.cjs +2 -2
  30. package/dist/hero-gradient-client-focused.js +2 -2
  31. package/dist/hero-grid-pattern-solutions.cjs +2 -2
  32. package/dist/hero-grid-pattern-solutions.d.cts +1 -1
  33. package/dist/hero-grid-pattern-solutions.d.ts +1 -1
  34. package/dist/hero-grid-pattern-solutions.js +2 -2
  35. package/dist/hero-innovation-image-grid.cjs +48 -42
  36. package/dist/hero-innovation-image-grid.js +48 -42
  37. package/dist/hero-mental-health-team.cjs +633 -89
  38. package/dist/hero-mental-health-team.d.cts +26 -6
  39. package/dist/hero-mental-health-team.d.ts +26 -6
  40. package/dist/hero-mental-health-team.js +614 -85
  41. package/dist/hero-minimal-centered-dark.cjs +841 -807
  42. package/dist/hero-minimal-centered-dark.d.cts +1 -1
  43. package/dist/hero-minimal-centered-dark.d.ts +1 -1
  44. package/dist/hero-minimal-centered-dark.js +840 -806
  45. package/dist/hero-presentation-platform-video.cjs +8 -2
  46. package/dist/hero-presentation-platform-video.js +8 -2
  47. package/dist/hero-product-showcase-floating.cjs +715 -612
  48. package/dist/hero-product-showcase-floating.d.cts +5 -1
  49. package/dist/hero-product-showcase-floating.d.ts +5 -1
  50. package/dist/hero-product-showcase-floating.js +712 -609
  51. package/dist/hero-saas-dashboard-preview.cjs +82 -107
  52. package/dist/hero-saas-dashboard-preview.d.cts +1 -1
  53. package/dist/hero-saas-dashboard-preview.d.ts +1 -1
  54. package/dist/hero-saas-dashboard-preview.js +82 -107
  55. package/dist/hero-software-growth-video-dialog.cjs +5 -5
  56. package/dist/hero-software-growth-video-dialog.js +5 -5
  57. package/dist/hero-split-image-newsletter.cjs +41 -32
  58. package/dist/hero-split-image-newsletter.js +41 -32
  59. package/dist/hero-stats-social-proof.cjs +1 -1
  60. package/dist/hero-stats-social-proof.js +1 -1
  61. package/dist/hero-testimonial-image-grid.cjs +2 -2
  62. package/dist/hero-testimonial-image-grid.js +2 -2
  63. package/dist/hero-therapy-testimonial-grid.cjs +682 -638
  64. package/dist/hero-therapy-testimonial-grid.d.cts +5 -1
  65. package/dist/hero-therapy-testimonial-grid.d.ts +5 -1
  66. package/dist/hero-therapy-testimonial-grid.js +671 -627
  67. package/dist/hero-ui-library-showcase.cjs +51 -42
  68. package/dist/hero-ui-library-showcase.js +51 -42
  69. package/dist/hero-video-dialog-gradient.cjs +2 -2
  70. package/dist/hero-video-dialog-gradient.js +2 -2
  71. package/dist/hero-video-overlay-stars.cjs +7 -15
  72. package/dist/hero-video-overlay-stars.js +7 -15
  73. package/dist/registry.cjs +608 -438
  74. package/dist/registry.js +608 -438
  75. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React = require('react');
4
+ var React3 = require('react');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
- var classVarianceAuthority = require('class-variance-authority');
8
7
  var jsxRuntime = require('react/jsx-runtime');
8
+ var classVarianceAuthority = require('class-variance-authority');
9
9
  var reactSlot = require('@radix-ui/react-slot');
10
10
 
11
11
  function _interopNamespace(e) {
@@ -26,834 +26,898 @@ function _interopNamespace(e) {
26
26
  return Object.freeze(n);
27
27
  }
28
28
 
29
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
29
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
30
30
 
31
31
  // components/blocks/hero/hero-minimal-centered-dark.tsx
32
32
  function cn(...inputs) {
33
33
  return tailwindMerge.twMerge(clsx.clsx(inputs));
34
34
  }
35
- function normalizePhoneNumber(input) {
36
- const trimmed = input.trim();
37
- if (trimmed.toLowerCase().startsWith("tel:")) {
38
- return trimmed;
39
- }
40
- const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
41
- if (match) {
42
- const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
43
- const extension = match[3];
44
- const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
45
- const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
46
- return `tel:${withExtension}`;
47
- }
48
- const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
49
- return `tel:${cleaned}`;
50
- }
51
- function normalizeEmail(input) {
52
- const trimmed = input.trim();
53
- if (trimmed.toLowerCase().startsWith("mailto:")) {
54
- return trimmed;
55
- }
56
- return `mailto:${trimmed}`;
57
- }
58
- function isEmail(input) {
59
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
60
- return emailRegex.test(input.trim());
61
- }
62
- function isPhoneNumber(input) {
63
- const trimmed = input.trim();
64
- if (trimmed.toLowerCase().startsWith("tel:")) {
65
- return true;
66
- }
67
- const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
68
- return phoneRegex.test(trimmed);
69
- }
70
- function isInternalUrl(href) {
71
- if (typeof window === "undefined") {
72
- return href.startsWith("/") && !href.startsWith("//");
73
- }
74
- const trimmed = href.trim();
75
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
76
- return true;
77
- }
78
- try {
79
- const url = new URL(trimmed, window.location.href);
80
- const currentOrigin = window.location.origin;
81
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
82
- return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
83
- } catch {
84
- return false;
35
+ var maxWidthStyles = {
36
+ sm: "max-w-screen-sm",
37
+ md: "max-w-screen-md",
38
+ lg: "max-w-screen-lg",
39
+ xl: "max-w-7xl",
40
+ "2xl": "max-w-screen-2xl",
41
+ "4xl": "max-w-[1536px]",
42
+ full: "max-w-full"
43
+ };
44
+ var Container = React3__namespace.default.forwardRef(
45
+ ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
46
+ const Component = as;
47
+ return /* @__PURE__ */ jsxRuntime.jsx(
48
+ Component,
49
+ {
50
+ ref,
51
+ className: cn(
52
+ "mx-auto w-full px-2 sm:px-4 lg:px-8",
53
+ maxWidthStyles[maxWidth],
54
+ className
55
+ ),
56
+ ...props,
57
+ children
58
+ }
59
+ );
85
60
  }
86
- }
87
- function toRelativePath(href) {
88
- if (typeof window === "undefined") {
89
- return href;
61
+ );
62
+ Container.displayName = "Container";
63
+
64
+ // lib/patternSvgs.ts
65
+ var patternSvgs = {
66
+ squareAltGrid: "https://cdn.ing/assets/files/record/286187/4gpn0yq2ptra8iwlvmwwv860ggwv",
67
+ grid1: "https://cdn.ing/assets/files/record/286186/nbdflpgp4ostrno079hygibsflp3",
68
+ noise: "https://cdn.ing/assets/i/r/286188/zrqcp9hynh3j7p2laihwzfbujgrl/noise.png",
69
+ dots: "https://cdn.ing/assets/files/record/286198/yfsjx9thvtxzhl2qtshxyhkrm524",
70
+ dotPattern: "https://cdn.ing/assets/files/record/286192/7ig0cku8aqbboiza8nuk6hw0nnsr",
71
+ dotPattern2: "https://cdn.ing/assets/files/record/286189/arez6gd2s7isn9i1o6c7sexdq7bl",
72
+ circles: "https://cdn.ing/assets/files/record/286190/gtmia3sncjtzetdshc20zf1d3c17",
73
+ waves: "https://cdn.ing/assets/files/record/286191/mqlb33fzxz9cdth1bx7if0wmpkp1",
74
+ crossPattern: "https://cdn.ing/assets/files/record/286193/9yfqwdbnqaipbp7fsb3wbzzmq472",
75
+ architect: "https://cdn.ing/assets/files/record/286194/vgs88ugpvyhxu13wqgy0acvae6re",
76
+ tinyCheckers: "https://cdn.ing/assets/files/record/286195/65efaknsw8kcpf9o3c2gybytsl5b",
77
+ p6: "https://cdn.ing/assets/i/r/286196/6kl0rqnd6mjk8j7e525fo8fo0vkc/p6.webp"
78
+ };
79
+ var maskTop = "radial-gradient(ellipse 70% 60% at 50% 0%, #000 60%, transparent 100%)";
80
+ var maskBottom = "radial-gradient(ellipse 100% 80% at 50% 100%, #000 50%, transparent 90%)";
81
+ var maskCenter = "radial-gradient(ellipse 60% 60% at 50% 50%, #000 30%, transparent 70%)";
82
+ var maskTopLeft = "radial-gradient(ellipse 80% 80% at 0% 0%, #000 50%, transparent 90%)";
83
+ var maskTopRight = "radial-gradient(ellipse 80% 80% at 100% 0%, #000 50%, transparent 90%)";
84
+ var maskBottomLeft = "radial-gradient(ellipse 80% 80% at 0% 100%, #000 50%, transparent 90%)";
85
+ var maskBottomRight = "radial-gradient(ellipse 80% 80% at 100% 100%, #000 50%, transparent 90%)";
86
+ var circuitBoardPattern = (id, mask) => /* @__PURE__ */ jsxRuntime.jsxs(
87
+ "svg",
88
+ {
89
+ className: "h-full w-full",
90
+ xmlns: "http://www.w3.org/2000/svg",
91
+ style: mask ? {
92
+ maskImage: mask,
93
+ WebkitMaskImage: mask
94
+ } : void 0,
95
+ children: [
96
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
97
+ "pattern",
98
+ {
99
+ id,
100
+ x: "0",
101
+ y: "0",
102
+ width: "100",
103
+ height: "100",
104
+ patternUnits: "userSpaceOnUse",
105
+ children: [
106
+ /* @__PURE__ */ jsxRuntime.jsx(
107
+ "path",
108
+ {
109
+ d: "M0 50h40M60 50h40M50 0v40M50 60v40",
110
+ stroke: "hsl(var(--muted))",
111
+ strokeWidth: "1",
112
+ fill: "none"
113
+ }
114
+ ),
115
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "50", r: "3", fill: "hsl(var(--muted))" }),
116
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "0", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
117
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "100", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
118
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "0", r: "2", fill: "hsl(var(--muted))" }),
119
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "100", r: "2", fill: "hsl(var(--muted))" })
120
+ ]
121
+ }
122
+ ) }),
123
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
124
+ ]
90
125
  }
91
- const trimmed = href.trim();
92
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
93
- return trimmed;
126
+ );
127
+ var gridDotsPattern = (id, mask) => /* @__PURE__ */ jsxRuntime.jsxs(
128
+ "svg",
129
+ {
130
+ className: "h-full w-full",
131
+ xmlns: "http://www.w3.org/2000/svg",
132
+ style: mask ? {
133
+ maskImage: mask,
134
+ WebkitMaskImage: mask
135
+ } : void 0,
136
+ children: [
137
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
138
+ "pattern",
139
+ {
140
+ id,
141
+ x: "0",
142
+ y: "0",
143
+ width: "40",
144
+ height: "40",
145
+ patternUnits: "userSpaceOnUse",
146
+ children: [
147
+ /* @__PURE__ */ jsxRuntime.jsx(
148
+ "path",
149
+ {
150
+ d: "M0 20h40M20 0v40",
151
+ stroke: "hsl(var(--muted))",
152
+ strokeWidth: "0.5",
153
+ fill: "none"
154
+ }
155
+ ),
156
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "20", cy: "20", r: "2", fill: "hsl(var(--muted))" })
157
+ ]
158
+ }
159
+ ) }),
160
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
161
+ ]
94
162
  }
95
- try {
96
- const url = new URL(trimmed, window.location.href);
97
- const currentOrigin = window.location.origin;
98
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
99
- if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
100
- return url.pathname + url.search + url.hash;
163
+ );
164
+ var gridPattern = (size, mask) => /* @__PURE__ */ jsxRuntime.jsx(
165
+ "div",
166
+ {
167
+ className: "h-full w-full bg-[linear-gradient(to_right,_hsl(var(--muted))_1px,_transparent_1px),linear-gradient(to_bottom,_hsl(var(--muted))_1px,_transparent_1px)]",
168
+ style: {
169
+ backgroundSize: `${size}px ${size}px`,
170
+ ...mask ? {
171
+ maskImage: mask,
172
+ WebkitMaskImage: mask
173
+ } : {}
101
174
  }
102
- } catch {
103
175
  }
104
- return trimmed;
105
- }
106
- function useNavigation({
107
- href,
108
- onClick
109
- } = {}) {
110
- const linkType = React__namespace.useMemo(() => {
111
- if (!href || href.trim() === "") {
112
- return onClick ? "none" : "none";
176
+ );
177
+ var diagonalCrossPattern = (mask) => /* @__PURE__ */ jsxRuntime.jsx(
178
+ "div",
179
+ {
180
+ className: "h-full w-full",
181
+ style: {
182
+ backgroundImage: "repeating-linear-gradient(45deg, transparent, transparent 32px, hsl(var(--muted)) 32px, hsl(var(--muted)) 33px), repeating-linear-gradient(135deg, transparent, transparent 32px, hsl(var(--muted)) 32px, hsl(var(--muted)) 33px)",
183
+ ...mask ? {
184
+ maskImage: mask,
185
+ WebkitMaskImage: mask
186
+ } : {}
113
187
  }
114
- const trimmed = href.trim();
115
- if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
116
- return "mailto";
188
+ }
189
+ );
190
+ var dashedGridMaskBase = "repeating-linear-gradient(to right, black 0px, black 3px, transparent 3px, transparent 8px), repeating-linear-gradient(to bottom, black 0px, black 3px, transparent 3px, transparent 8px)";
191
+ var dashedGridPattern = (fadeMask) => {
192
+ const mask = fadeMask ? `${dashedGridMaskBase}, ${fadeMask}` : dashedGridMaskBase;
193
+ return /* @__PURE__ */ jsxRuntime.jsx(
194
+ "div",
195
+ {
196
+ className: "h-full w-full",
197
+ style: {
198
+ backgroundImage: "linear-gradient(to right, hsl(var(--muted)) 1px, transparent 1px), linear-gradient(to bottom, hsl(var(--muted)) 1px, transparent 1px)",
199
+ backgroundSize: "20px 20px",
200
+ backgroundPosition: "0 0, 0 0",
201
+ maskImage: mask,
202
+ WebkitMaskImage: mask,
203
+ maskComposite: "intersect",
204
+ WebkitMaskComposite: "source-in"
205
+ }
117
206
  }
118
- if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
119
- return "tel";
207
+ );
208
+ };
209
+ var gradientGlow = (position) => /* @__PURE__ */ jsxRuntime.jsx(
210
+ "div",
211
+ {
212
+ className: cn(
213
+ "pointer-events-none absolute left-1/2 z-0 aspect-square w-3/4 -translate-x-1/2 rounded-full opacity-50 blur-3xl",
214
+ position === "top" ? "-top-1/4" : "-bottom-1/4"
215
+ ),
216
+ style: {
217
+ background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
120
218
  }
121
- if (isInternalUrl(trimmed)) {
122
- return "internal";
123
- }
124
- try {
125
- new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
126
- return "external";
127
- } catch {
128
- return "internal";
129
- }
130
- }, [href, onClick]);
131
- const normalizedHref = React__namespace.useMemo(() => {
132
- if (!href || href.trim() === "") {
133
- return void 0;
134
- }
135
- const trimmed = href.trim();
136
- switch (linkType) {
137
- case "tel":
138
- return normalizePhoneNumber(trimmed);
139
- case "mailto":
140
- return normalizeEmail(trimmed);
141
- case "internal":
142
- return toRelativePath(trimmed);
143
- case "external":
144
- return trimmed;
145
- default:
146
- return trimmed;
147
- }
148
- }, [href, linkType]);
149
- const target = React__namespace.useMemo(() => {
150
- switch (linkType) {
151
- case "external":
152
- return "_blank";
153
- case "internal":
154
- return "_self";
155
- case "mailto":
156
- case "tel":
157
- return void 0;
158
- default:
159
- return void 0;
160
- }
161
- }, [linkType]);
162
- const rel = React__namespace.useMemo(() => {
163
- if (linkType === "external") {
164
- return "noopener noreferrer";
165
- }
166
- return void 0;
167
- }, [linkType]);
168
- const isExternal = linkType === "external";
169
- const isInternal = linkType === "internal";
170
- const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
171
- const handleClick = React__namespace.useCallback(
172
- (event) => {
173
- if (onClick) {
174
- try {
175
- onClick(event);
176
- } catch (error) {
177
- console.error("Error in user onClick handler:", error);
178
- }
179
- }
180
- if (event.defaultPrevented) {
181
- return;
182
- }
183
- if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
184
- !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
185
- if (typeof window !== "undefined") {
186
- const handler = window.__opensiteNavigationHandler;
187
- if (typeof handler === "function") {
188
- try {
189
- const handled = handler(normalizedHref, event.nativeEvent || event);
190
- if (handled !== false) {
191
- event.preventDefault();
192
- }
193
- } catch (error) {
194
- console.error("Error in navigation handler:", error);
195
- }
196
- }
197
- }
198
- }
199
- },
200
- [onClick, shouldUseRouter, normalizedHref]
201
- );
202
- return {
203
- linkType,
204
- normalizedHref,
205
- target,
206
- rel,
207
- isExternal,
208
- isInternal,
209
- shouldUseRouter,
210
- handleClick
211
- };
212
- }
213
- var baseStyles = [
214
- // Layout
215
- "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
216
- // Typography - using CSS variables with sensible defaults
217
- "font-[var(--button-font-family,inherit)]",
218
- "font-[var(--button-font-weight,500)]",
219
- "tracking-[var(--button-letter-spacing,0)]",
220
- "leading-[var(--button-line-height,1.25)]",
221
- "[text-transform:var(--button-text-transform,none)]",
222
- "text-sm",
223
- // Border radius
224
- "rounded-[var(--button-radius,var(--radius,0.375rem))]",
225
- // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
226
- "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
227
- // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
228
- "[box-shadow:var(--button-shadow,none)]",
229
- "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
230
- // Disabled state
231
- "disabled:pointer-events-none disabled:opacity-50",
232
- // SVG handling
233
- "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
234
- // Focus styles
235
- "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
236
- // Invalid state
237
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
238
- ].join(" ");
239
- var buttonVariants = classVarianceAuthority.cva(baseStyles, {
240
- variants: {
241
- variant: {
242
- // Default (Primary) variant - full customization
243
- default: [
244
- "bg-[var(--button-default-bg,hsl(var(--primary)))]",
245
- "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
246
- "border-[length:var(--button-default-border-width,0px)]",
247
- "border-[color:var(--button-default-border,transparent)]",
248
- "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
249
- "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
250
- "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
251
- "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
252
- "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
253
- ].join(" "),
254
- // Destructive variant - full customization
255
- destructive: [
256
- "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
257
- "text-[var(--button-destructive-fg,white)]",
258
- "border-[length:var(--button-destructive-border-width,0px)]",
259
- "border-[color:var(--button-destructive-border,transparent)]",
260
- "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
261
- "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
262
- "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
263
- "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
264
- "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
265
- "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
266
- "dark:bg-destructive/60"
267
- ].join(" "),
268
- // Outline variant - full customization with proper border handling
269
- outline: [
270
- "bg-[var(--button-outline-bg,hsl(var(--background)))]",
271
- "text-[var(--button-outline-fg,inherit)]",
272
- "border-[length:var(--button-outline-border-width,1px)]",
273
- "border-[color:var(--button-outline-border,hsl(var(--border)))]",
274
- "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
275
- "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
276
- "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
277
- "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
278
- "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
279
- "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
280
- ].join(" "),
281
- // Secondary variant - full customization
282
- secondary: [
283
- "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
284
- "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
285
- "border-[length:var(--button-secondary-border-width,0px)]",
286
- "border-[color:var(--button-secondary-border,transparent)]",
287
- "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
288
- "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
289
- "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
290
- "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
291
- "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
292
- ].join(" "),
293
- // Ghost variant - full customization
294
- ghost: [
295
- "bg-[var(--button-ghost-bg,transparent)]",
296
- "text-[var(--button-ghost-fg,inherit)]",
297
- "border-[length:var(--button-ghost-border-width,0px)]",
298
- "border-[color:var(--button-ghost-border,transparent)]",
299
- "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
300
- "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
301
- "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
302
- "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
303
- "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
304
- "dark:hover:bg-accent/50"
305
- ].join(" "),
306
- // Link variant - full customization
307
- link: [
308
- "bg-[var(--button-link-bg,transparent)]",
309
- "text-[var(--button-link-fg,hsl(var(--primary)))]",
310
- "border-[length:var(--button-link-border-width,0px)]",
311
- "border-[color:var(--button-link-border,transparent)]",
312
- "[box-shadow:var(--button-link-shadow,none)]",
313
- "hover:bg-[var(--button-link-hover-bg,transparent)]",
314
- "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
315
- "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
316
- "underline-offset-4 hover:underline"
317
- ].join(" ")
318
- },
319
- size: {
320
- default: [
321
- "h-[var(--button-height-md,2.25rem)]",
322
- "px-[var(--button-padding-x-md,1rem)]",
323
- "py-[var(--button-padding-y-md,0.5rem)]",
324
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
325
- ].join(" "),
326
- sm: [
327
- "h-[var(--button-height-sm,2rem)]",
328
- "px-[var(--button-padding-x-sm,0.75rem)]",
329
- "py-[var(--button-padding-y-sm,0.25rem)]",
330
- "gap-1.5",
331
- "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
332
- ].join(" "),
333
- md: [
334
- "h-[var(--button-height-md,2.25rem)]",
335
- "px-[var(--button-padding-x-md,1rem)]",
336
- "py-[var(--button-padding-y-md,0.5rem)]",
337
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
338
- ].join(" "),
339
- lg: [
340
- "h-[var(--button-height-lg,2.5rem)]",
341
- "px-[var(--button-padding-x-lg,1.5rem)]",
342
- "py-[var(--button-padding-y-lg,0.5rem)]",
343
- "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
344
- ].join(" "),
345
- icon: "size-[var(--button-height-md,2.25rem)]",
346
- "icon-sm": "size-[var(--button-height-sm,2rem)]",
347
- "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
219
+ }
220
+ );
221
+ var spotlight = (position) => /* @__PURE__ */ jsxRuntime.jsx(
222
+ "div",
223
+ {
224
+ className: cn(
225
+ "pointer-events-none absolute top-1/2 z-0 aspect-square w-3/4 -translate-y-1/2 rounded-full opacity-40 blur-3xl",
226
+ position === "left" ? "-left-1/4" : "-right-1/4"
227
+ ),
228
+ style: {
229
+ background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
348
230
  }
231
+ }
232
+ );
233
+ var patternOverlays = {
234
+ circuitBoardBasic: () => circuitBoardPattern("circuit-board-basic"),
235
+ circuitBoardFadeTop: () => circuitBoardPattern("circuit-board-fade-top", maskTop),
236
+ circuitBoardFadeBottom: () => circuitBoardPattern("circuit-board-fade-bottom", maskBottom),
237
+ circuitBoardFadeCenter: () => circuitBoardPattern("circuit-board-fade-center", maskCenter),
238
+ circuitBoardFadeTopLeft: () => circuitBoardPattern("circuit-board-fade-top-left", maskTopLeft),
239
+ circuitBoardFadeTopRight: () => circuitBoardPattern("circuit-board-fade-top-right", maskTopRight),
240
+ circuitBoardFadeBottomLeft: () => circuitBoardPattern("circuit-board-fade-bottom-left", maskBottomLeft),
241
+ circuitBoardFadeBottomRight: () => circuitBoardPattern("circuit-board-fade-bottom-right", maskBottomRight),
242
+ dashedGridBasic: () => dashedGridPattern(),
243
+ dashedGridFadeTop: () => dashedGridPattern(maskTop),
244
+ dashedGridFadeBottom: () => dashedGridPattern(maskBottom),
245
+ dashedGridFadeCenter: () => dashedGridPattern(maskCenter),
246
+ dashedGridFadeTopLeft: () => dashedGridPattern(maskTopLeft),
247
+ dashedGridFadeTopRight: () => dashedGridPattern(maskTopRight),
248
+ dashedGridFadeBottomLeft: () => dashedGridPattern(maskBottomLeft),
249
+ dashedGridFadeBottomRight: () => dashedGridPattern(maskBottomRight),
250
+ diagonalCrossBasic: () => diagonalCrossPattern(),
251
+ diagonalCrossFadeTop: () => diagonalCrossPattern(maskTop),
252
+ diagonalCrossFadeBottom: () => diagonalCrossPattern(maskBottom),
253
+ diagonalCrossFadeCenter: () => diagonalCrossPattern(maskCenter),
254
+ diagonalCrossFadeTopLeft: () => diagonalCrossPattern(maskTopLeft),
255
+ diagonalCrossFadeTopRight: () => diagonalCrossPattern(maskTopRight),
256
+ diagonalCrossFadeBottomLeft: () => diagonalCrossPattern(maskBottomLeft),
257
+ diagonalCrossFadeBottomRight: () => diagonalCrossPattern(maskBottomRight),
258
+ gridBasic: () => gridPattern(40),
259
+ gridFadeTop: () => gridPattern(32, maskTop),
260
+ gridFadeBottom: () => gridPattern(32, maskBottom),
261
+ gridFadeCenter: () => gridPattern(40, maskCenter),
262
+ gridFadeTopLeft: () => gridPattern(32, maskTopLeft),
263
+ gridFadeTopRight: () => gridPattern(32, maskTopRight),
264
+ gridFadeBottomLeft: () => gridPattern(32, maskBottomLeft),
265
+ gridFadeBottomRight: () => gridPattern(32, maskBottomRight),
266
+ gridDotsBasic: () => gridDotsPattern("grid-dots-basic"),
267
+ gridDotsFadeCenter: () => gridDotsPattern("grid-dots-fade-center", maskCenter),
268
+ gradientGlowTop: () => gradientGlow("top"),
269
+ gradientGlowBottom: () => gradientGlow("bottom"),
270
+ spotlightLeft: () => spotlight("left"),
271
+ spotlightRight: () => spotlight("right")
272
+ };
273
+ var inlinePatternStyles = {
274
+ radialGradientTop: {
275
+ background: "radial-gradient(125% 125% at 50% 10%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
349
276
  },
350
- defaultVariants: {
351
- variant: "default",
352
- size: "default"
277
+ radialGradientBottom: {
278
+ background: "radial-gradient(125% 125% at 50% 90%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
353
279
  }
354
- });
355
- var Pressable = React__namespace.forwardRef(
356
- ({
357
- children,
358
- className,
359
- href,
360
- onClick,
361
- variant,
362
- size,
363
- asButton = false,
364
- fallbackComponentType = "span",
365
- componentType,
366
- "aria-label": ariaLabel,
367
- "aria-describedby": ariaDescribedby,
368
- id,
369
- ...props
370
- }, ref) => {
371
- const navigation = useNavigation({ href, onClick });
372
- const {
373
- normalizedHref,
374
- target,
375
- rel,
376
- linkType,
377
- isInternal,
378
- handleClick
379
- } = navigation;
380
- const shouldRenderLink = normalizedHref && linkType !== "none";
381
- const shouldRenderButton = !shouldRenderLink && onClick;
382
- const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
383
- const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
384
- const shouldApplyButtonStyles = asButton || variant || size;
385
- const combinedClassName = cn(
386
- shouldApplyButtonStyles && buttonVariants({ variant, size }),
387
- className
388
- );
389
- const dataProps = Object.fromEntries(
390
- Object.entries(props).filter(([key]) => key.startsWith("data-"))
391
- );
392
- const buttonDataAttributes = shouldApplyButtonStyles ? {
393
- "data-slot": "button",
394
- "data-variant": variant ?? "default",
395
- "data-size": size ?? "default"
396
- } : {};
397
- const commonProps = {
398
- className: combinedClassName,
399
- onClick: handleClick,
400
- "aria-label": ariaLabel,
401
- "aria-describedby": ariaDescribedby,
402
- id,
403
- ...dataProps,
404
- ...buttonDataAttributes
405
- };
406
- if (finalComponentType === "a" && shouldRenderLink) {
407
- return /* @__PURE__ */ jsxRuntime.jsx(
408
- "a",
409
- {
410
- ref,
411
- href: normalizedHref,
412
- target,
413
- rel,
414
- ...commonProps,
415
- ...props,
416
- children
417
- }
418
- );
419
- }
420
- if (finalComponentType === "button") {
421
- return /* @__PURE__ */ jsxRuntime.jsx(
422
- "button",
423
- {
424
- ref,
425
- type: props.type || "button",
426
- ...commonProps,
427
- ...props,
428
- children
429
- }
430
- );
431
- }
432
- if (finalComponentType === "div") {
433
- return /* @__PURE__ */ jsxRuntime.jsx(
434
- "div",
435
- {
436
- ref,
437
- ...commonProps,
438
- children
439
- }
440
- );
441
- }
280
+ };
281
+ function PatternBackground({
282
+ pattern,
283
+ opacity = 0.08,
284
+ className,
285
+ style
286
+ }) {
287
+ if (!pattern) {
288
+ return null;
289
+ }
290
+ if (pattern in inlinePatternStyles) {
291
+ const inlineStyle = inlinePatternStyles[pattern];
442
292
  return /* @__PURE__ */ jsxRuntime.jsx(
443
- "span",
293
+ "div",
444
294
  {
445
- ref,
446
- ...commonProps,
447
- children
295
+ className: cn("pointer-events-none absolute inset-0 z-0", className),
296
+ style: { ...inlineStyle, opacity, ...style },
297
+ "aria-hidden": "true"
448
298
  }
449
299
  );
450
300
  }
451
- );
452
- Pressable.displayName = "Pressable";
453
- var maxWidthStyles = {
454
- sm: "max-w-screen-sm",
455
- md: "max-w-screen-md",
456
- lg: "max-w-screen-lg",
457
- xl: "max-w-7xl",
458
- "2xl": "max-w-screen-2xl",
459
- "4xl": "max-w-[1536px]",
460
- full: "max-w-full"
461
- };
462
- var Container = React__namespace.default.forwardRef(
463
- ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
464
- const Component = as;
301
+ if (pattern in patternOverlays) {
302
+ const Overlay = patternOverlays[pattern];
465
303
  return /* @__PURE__ */ jsxRuntime.jsx(
466
- Component,
304
+ "div",
467
305
  {
468
- ref,
469
- className: cn(
470
- "mx-auto w-full px-2 sm:px-4 lg:px-8",
471
- maxWidthStyles[maxWidth],
472
- className
473
- ),
474
- ...props,
475
- children
306
+ className: cn("pointer-events-none absolute inset-0 z-0", className),
307
+ style: { opacity, ...style },
308
+ "aria-hidden": "true",
309
+ children: Overlay()
476
310
  }
477
311
  );
478
312
  }
479
- );
480
- Container.displayName = "Container";
481
-
482
- // lib/patternSvgs.ts
483
- var patternSvgs = {
484
- squareAltGrid: "https://cdn.ing/assets/files/record/286187/4gpn0yq2ptra8iwlvmwwv860ggwv",
485
- grid1: "https://cdn.ing/assets/files/record/286186/nbdflpgp4ostrno079hygibsflp3",
486
- noise: "https://cdn.ing/assets/i/r/286188/zrqcp9hynh3j7p2laihwzfbujgrl/noise.png",
487
- dots: "https://cdn.ing/assets/files/record/286198/yfsjx9thvtxzhl2qtshxyhkrm524",
488
- dotPattern: "https://cdn.ing/assets/files/record/286192/7ig0cku8aqbboiza8nuk6hw0nnsr",
489
- dotPattern2: "https://cdn.ing/assets/files/record/286189/arez6gd2s7isn9i1o6c7sexdq7bl",
490
- circles: "https://cdn.ing/assets/files/record/286190/gtmia3sncjtzetdshc20zf1d3c17",
491
- waves: "https://cdn.ing/assets/files/record/286191/mqlb33fzxz9cdth1bx7if0wmpkp1",
492
- crossPattern: "https://cdn.ing/assets/files/record/286193/9yfqwdbnqaipbp7fsb3wbzzmq472",
493
- architect: "https://cdn.ing/assets/files/record/286194/vgs88ugpvyhxu13wqgy0acvae6re",
494
- tinyCheckers: "https://cdn.ing/assets/files/record/286195/65efaknsw8kcpf9o3c2gybytsl5b",
495
- p6: "https://cdn.ing/assets/i/r/286196/6kl0rqnd6mjk8j7e525fo8fo0vkc/p6.webp"
496
- };
497
- var maskTop = "radial-gradient(ellipse 70% 60% at 50% 0%, #000 60%, transparent 100%)";
498
- var maskBottom = "radial-gradient(ellipse 100% 80% at 50% 100%, #000 50%, transparent 90%)";
499
- var maskCenter = "radial-gradient(ellipse 60% 60% at 50% 50%, #000 30%, transparent 70%)";
500
- var maskTopLeft = "radial-gradient(ellipse 80% 80% at 0% 0%, #000 50%, transparent 90%)";
501
- var maskTopRight = "radial-gradient(ellipse 80% 80% at 100% 0%, #000 50%, transparent 90%)";
502
- var maskBottomLeft = "radial-gradient(ellipse 80% 80% at 0% 100%, #000 50%, transparent 90%)";
503
- var maskBottomRight = "radial-gradient(ellipse 80% 80% at 100% 100%, #000 50%, transparent 90%)";
504
- var circuitBoardPattern = (id, mask) => /* @__PURE__ */ jsxRuntime.jsxs(
505
- "svg",
506
- {
507
- className: "h-full w-full",
508
- xmlns: "http://www.w3.org/2000/svg",
509
- style: mask ? {
510
- maskImage: mask,
511
- WebkitMaskImage: mask
512
- } : void 0,
513
- children: [
514
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
515
- "pattern",
516
- {
517
- id,
518
- x: "0",
519
- y: "0",
520
- width: "100",
521
- height: "100",
522
- patternUnits: "userSpaceOnUse",
523
- children: [
524
- /* @__PURE__ */ jsxRuntime.jsx(
525
- "path",
526
- {
527
- d: "M0 50h40M60 50h40M50 0v40M50 60v40",
528
- stroke: "hsl(var(--muted))",
529
- strokeWidth: "1",
530
- fill: "none"
531
- }
532
- ),
533
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "50", r: "3", fill: "hsl(var(--muted))" }),
534
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "0", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
535
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "100", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
536
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "0", r: "2", fill: "hsl(var(--muted))" }),
537
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "50", cy: "100", r: "2", fill: "hsl(var(--muted))" })
538
- ]
539
- }
540
- ) }),
541
- /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
542
- ]
543
- }
544
- );
545
- var gridDotsPattern = (id, mask) => /* @__PURE__ */ jsxRuntime.jsxs(
546
- "svg",
547
- {
548
- className: "h-full w-full",
549
- xmlns: "http://www.w3.org/2000/svg",
550
- style: mask ? {
551
- maskImage: mask,
552
- WebkitMaskImage: mask
553
- } : void 0,
554
- children: [
555
- /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
556
- "pattern",
557
- {
558
- id,
559
- x: "0",
560
- y: "0",
561
- width: "40",
562
- height: "40",
563
- patternUnits: "userSpaceOnUse",
564
- children: [
565
- /* @__PURE__ */ jsxRuntime.jsx(
566
- "path",
567
- {
568
- d: "M0 20h40M20 0v40",
569
- stroke: "hsl(var(--muted))",
570
- strokeWidth: "0.5",
571
- fill: "none"
572
- }
573
- ),
574
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "20", cy: "20", r: "2", fill: "hsl(var(--muted))" })
575
- ]
576
- }
577
- ) }),
578
- /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
579
- ]
313
+ const patternUrl = pattern in patternSvgs ? patternSvgs[pattern] : pattern;
314
+ return /* @__PURE__ */ jsxRuntime.jsx(
315
+ "div",
316
+ {
317
+ className: cn("pointer-events-none absolute inset-0 z-0", className),
318
+ style: {
319
+ backgroundImage: `url(${patternUrl})`,
320
+ backgroundRepeat: "repeat",
321
+ backgroundSize: "auto",
322
+ opacity,
323
+ ...style
324
+ },
325
+ "aria-hidden": "true"
326
+ }
327
+ );
328
+ }
329
+ var backgroundStyles = {
330
+ default: "bg-background text-foreground",
331
+ white: "bg-white text-dark",
332
+ gray: "bg-muted/30 text-foreground",
333
+ dark: "bg-foreground text-background",
334
+ transparent: "bg-transparent text-foreground",
335
+ gradient: "bg-linear-to-br from-primary via-primary/90 to-foreground text-primary-foreground",
336
+ primary: "bg-primary text-primary-foreground",
337
+ secondary: "bg-secondary text-secondary-foreground",
338
+ muted: "bg-muted text-muted-foreground"
339
+ };
340
+ var spacingStyles = {
341
+ none: "py-0 md:py-0",
342
+ sm: "py-12 md:py-16",
343
+ md: "py-16 md:py-24",
344
+ lg: "py-20 md:py-32",
345
+ xl: "py-24 md:py-40"
346
+ };
347
+ var predefinedSpacings = ["none", "sm", "md", "lg", "xl"];
348
+ var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
349
+ var Section = React3__namespace.default.forwardRef(
350
+ ({
351
+ id,
352
+ title,
353
+ subtitle,
354
+ children,
355
+ className,
356
+ style,
357
+ background = "default",
358
+ spacing = "lg",
359
+ pattern,
360
+ patternOpacity,
361
+ patternClassName,
362
+ containerClassName,
363
+ containerMaxWidth = "xl",
364
+ ...props
365
+ }, ref) => {
366
+ const effectivePatternOpacity = patternOpacity !== void 0 ? patternOpacity : pattern ? 1 : 0;
367
+ return /* @__PURE__ */ jsxRuntime.jsxs(
368
+ "section",
369
+ {
370
+ ref,
371
+ id,
372
+ className: cn(
373
+ "relative",
374
+ pattern ? "overflow-hidden" : null,
375
+ backgroundStyles[background],
376
+ isPredefinedSpacing(spacing) ? spacingStyles[spacing] : spacing,
377
+ className
378
+ ),
379
+ style,
380
+ ...props,
381
+ children: [
382
+ /* @__PURE__ */ jsxRuntime.jsx(
383
+ PatternBackground,
384
+ {
385
+ pattern,
386
+ opacity: effectivePatternOpacity,
387
+ className: patternClassName
388
+ }
389
+ ),
390
+ /* @__PURE__ */ jsxRuntime.jsxs(
391
+ Container,
392
+ {
393
+ maxWidth: containerMaxWidth,
394
+ className: cn("relative z-10", containerClassName),
395
+ children: [
396
+ (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 text-center md:mb-16", children: [
397
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-sm font-semibold uppercase tracking-wider", children: subtitle }),
398
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl", children: title })
399
+ ] }),
400
+ children
401
+ ]
402
+ }
403
+ )
404
+ ]
405
+ }
406
+ );
580
407
  }
581
408
  );
582
- var gridPattern = (size, mask) => /* @__PURE__ */ jsxRuntime.jsx(
583
- "div",
584
- {
585
- className: "h-full w-full bg-[linear-gradient(to_right,_hsl(var(--muted))_1px,_transparent_1px),linear-gradient(to_bottom,_hsl(var(--muted))_1px,_transparent_1px)]",
586
- style: {
587
- backgroundSize: `${size}px ${size}px`,
588
- ...mask ? {
589
- maskImage: mask,
590
- WebkitMaskImage: mask
591
- } : {}
409
+ Section.displayName = "Section";
410
+ var baseStyles = [
411
+ // Layout
412
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
413
+ // Typography - using CSS variables with sensible defaults
414
+ "font-[var(--button-font-family,inherit)]",
415
+ "font-[var(--button-font-weight,500)]",
416
+ "tracking-[var(--button-letter-spacing,0)]",
417
+ "leading-[var(--button-line-height,1.25)]",
418
+ "[text-transform:var(--button-text-transform,none)]",
419
+ "text-sm",
420
+ // Border radius
421
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
422
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
423
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
424
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
425
+ "[box-shadow:var(--button-shadow,none)]",
426
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
427
+ // Disabled state
428
+ "disabled:pointer-events-none disabled:opacity-50",
429
+ // SVG handling
430
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
431
+ // Focus styles
432
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
433
+ // Invalid state
434
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
435
+ ].join(" ");
436
+ var buttonVariants = classVarianceAuthority.cva(baseStyles, {
437
+ variants: {
438
+ variant: {
439
+ // Default (Primary) variant - full customization
440
+ default: [
441
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
442
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
443
+ "border-[length:var(--button-default-border-width,0px)]",
444
+ "border-[color:var(--button-default-border,transparent)]",
445
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
446
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
447
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
448
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
449
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
450
+ ].join(" "),
451
+ // Destructive variant - full customization
452
+ destructive: [
453
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
454
+ "text-[var(--button-destructive-fg,white)]",
455
+ "border-[length:var(--button-destructive-border-width,0px)]",
456
+ "border-[color:var(--button-destructive-border,transparent)]",
457
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
458
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
459
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
460
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
461
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
462
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
463
+ "dark:bg-destructive/60"
464
+ ].join(" "),
465
+ // Outline variant - full customization with proper border handling
466
+ outline: [
467
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
468
+ "text-[var(--button-outline-fg,inherit)]",
469
+ "border-[length:var(--button-outline-border-width,1px)]",
470
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
471
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
472
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
473
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
474
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
475
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
476
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
477
+ ].join(" "),
478
+ // Secondary variant - full customization
479
+ secondary: [
480
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
481
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
482
+ "border-[length:var(--button-secondary-border-width,0px)]",
483
+ "border-[color:var(--button-secondary-border,transparent)]",
484
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
485
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
486
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
487
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
488
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
489
+ ].join(" "),
490
+ // Ghost variant - full customization
491
+ ghost: [
492
+ "bg-[var(--button-ghost-bg,transparent)]",
493
+ "text-[var(--button-ghost-fg,inherit)]",
494
+ "border-[length:var(--button-ghost-border-width,0px)]",
495
+ "border-[color:var(--button-ghost-border,transparent)]",
496
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
497
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
498
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
499
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
500
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
501
+ "dark:hover:bg-accent/50"
502
+ ].join(" "),
503
+ // Link variant - full customization
504
+ link: [
505
+ "bg-[var(--button-link-bg,transparent)]",
506
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
507
+ "border-[length:var(--button-link-border-width,0px)]",
508
+ "border-[color:var(--button-link-border,transparent)]",
509
+ "[box-shadow:var(--button-link-shadow,none)]",
510
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
511
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
512
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
513
+ "underline-offset-4 hover:underline"
514
+ ].join(" ")
515
+ },
516
+ size: {
517
+ default: [
518
+ "h-[var(--button-height-md,2.25rem)]",
519
+ "px-[var(--button-padding-x-md,1rem)]",
520
+ "py-[var(--button-padding-y-md,0.5rem)]",
521
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
522
+ ].join(" "),
523
+ sm: [
524
+ "h-[var(--button-height-sm,2rem)]",
525
+ "px-[var(--button-padding-x-sm,0.75rem)]",
526
+ "py-[var(--button-padding-y-sm,0.25rem)]",
527
+ "gap-1.5",
528
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
529
+ ].join(" "),
530
+ md: [
531
+ "h-[var(--button-height-md,2.25rem)]",
532
+ "px-[var(--button-padding-x-md,1rem)]",
533
+ "py-[var(--button-padding-y-md,0.5rem)]",
534
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
535
+ ].join(" "),
536
+ lg: [
537
+ "h-[var(--button-height-lg,2.5rem)]",
538
+ "px-[var(--button-padding-x-lg,1.5rem)]",
539
+ "py-[var(--button-padding-y-lg,0.5rem)]",
540
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
541
+ ].join(" "),
542
+ icon: "size-[var(--button-height-md,2.25rem)]",
543
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
544
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
592
545
  }
546
+ },
547
+ defaultVariants: {
548
+ variant: "default",
549
+ size: "default"
593
550
  }
594
- );
595
- var diagonalCrossPattern = (mask) => /* @__PURE__ */ jsxRuntime.jsx(
596
- "div",
551
+ });
552
+ var badgeVariants = classVarianceAuthority.cva(
553
+ "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
597
554
  {
598
- className: "h-full w-full",
599
- style: {
600
- backgroundImage: "repeating-linear-gradient(45deg, transparent, transparent 32px, hsl(var(--muted)) 32px, hsl(var(--muted)) 33px), repeating-linear-gradient(135deg, transparent, transparent 32px, hsl(var(--muted)) 32px, hsl(var(--muted)) 33px)",
601
- ...mask ? {
602
- maskImage: mask,
603
- WebkitMaskImage: mask
604
- } : {}
555
+ variants: {
556
+ variant: {
557
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
558
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
559
+ destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
560
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
561
+ }
562
+ },
563
+ defaultVariants: {
564
+ variant: "default"
605
565
  }
606
566
  }
607
567
  );
608
- var dashedGridMaskBase = "repeating-linear-gradient(to right, black 0px, black 3px, transparent 3px, transparent 8px), repeating-linear-gradient(to bottom, black 0px, black 3px, transparent 3px, transparent 8px)";
609
- var dashedGridPattern = (fadeMask) => {
610
- const mask = fadeMask ? `${dashedGridMaskBase}, ${fadeMask}` : dashedGridMaskBase;
568
+ function Badge({
569
+ className,
570
+ variant,
571
+ asChild = false,
572
+ ...props
573
+ }) {
574
+ const Comp = asChild ? reactSlot.Slot : "span";
611
575
  return /* @__PURE__ */ jsxRuntime.jsx(
612
- "div",
576
+ Comp,
613
577
  {
614
- className: "h-full w-full",
615
- style: {
616
- backgroundImage: "linear-gradient(to right, hsl(var(--muted)) 1px, transparent 1px), linear-gradient(to bottom, hsl(var(--muted)) 1px, transparent 1px)",
617
- backgroundSize: "20px 20px",
618
- backgroundPosition: "0 0, 0 0",
619
- maskImage: mask,
620
- WebkitMaskImage: mask,
621
- maskComposite: "intersect",
622
- WebkitMaskComposite: "source-in"
623
- }
578
+ "data-slot": "badge",
579
+ className: cn(badgeVariants({ variant }), className),
580
+ ...props
624
581
  }
625
582
  );
626
- };
627
- var gradientGlow = (position) => /* @__PURE__ */ jsxRuntime.jsx(
628
- "div",
629
- {
630
- className: cn(
631
- "pointer-events-none absolute left-1/2 z-0 aspect-square w-3/4 -translate-x-1/2 rounded-full opacity-50 blur-3xl",
632
- position === "top" ? "-top-1/4" : "-bottom-1/4"
633
- ),
634
- style: {
635
- background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
636
- }
583
+ }
584
+ function normalizePhoneNumber(input) {
585
+ const trimmed = input.trim();
586
+ if (trimmed.toLowerCase().startsWith("tel:")) {
587
+ return trimmed;
637
588
  }
638
- );
639
- var spotlight = (position) => /* @__PURE__ */ jsxRuntime.jsx(
640
- "div",
641
- {
642
- className: cn(
643
- "pointer-events-none absolute top-1/2 z-0 aspect-square w-3/4 -translate-y-1/2 rounded-full opacity-40 blur-3xl",
644
- position === "left" ? "-left-1/4" : "-right-1/4"
645
- ),
646
- style: {
647
- background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
648
- }
589
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
590
+ if (match) {
591
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
592
+ const extension = match[3];
593
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
594
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
595
+ return `tel:${withExtension}`;
649
596
  }
650
- );
651
- var patternOverlays = {
652
- circuitBoardBasic: () => circuitBoardPattern("circuit-board-basic"),
653
- circuitBoardFadeTop: () => circuitBoardPattern("circuit-board-fade-top", maskTop),
654
- circuitBoardFadeBottom: () => circuitBoardPattern("circuit-board-fade-bottom", maskBottom),
655
- circuitBoardFadeCenter: () => circuitBoardPattern("circuit-board-fade-center", maskCenter),
656
- circuitBoardFadeTopLeft: () => circuitBoardPattern("circuit-board-fade-top-left", maskTopLeft),
657
- circuitBoardFadeTopRight: () => circuitBoardPattern("circuit-board-fade-top-right", maskTopRight),
658
- circuitBoardFadeBottomLeft: () => circuitBoardPattern("circuit-board-fade-bottom-left", maskBottomLeft),
659
- circuitBoardFadeBottomRight: () => circuitBoardPattern("circuit-board-fade-bottom-right", maskBottomRight),
660
- dashedGridBasic: () => dashedGridPattern(),
661
- dashedGridFadeTop: () => dashedGridPattern(maskTop),
662
- dashedGridFadeBottom: () => dashedGridPattern(maskBottom),
663
- dashedGridFadeCenter: () => dashedGridPattern(maskCenter),
664
- dashedGridFadeTopLeft: () => dashedGridPattern(maskTopLeft),
665
- dashedGridFadeTopRight: () => dashedGridPattern(maskTopRight),
666
- dashedGridFadeBottomLeft: () => dashedGridPattern(maskBottomLeft),
667
- dashedGridFadeBottomRight: () => dashedGridPattern(maskBottomRight),
668
- diagonalCrossBasic: () => diagonalCrossPattern(),
669
- diagonalCrossFadeTop: () => diagonalCrossPattern(maskTop),
670
- diagonalCrossFadeBottom: () => diagonalCrossPattern(maskBottom),
671
- diagonalCrossFadeCenter: () => diagonalCrossPattern(maskCenter),
672
- diagonalCrossFadeTopLeft: () => diagonalCrossPattern(maskTopLeft),
673
- diagonalCrossFadeTopRight: () => diagonalCrossPattern(maskTopRight),
674
- diagonalCrossFadeBottomLeft: () => diagonalCrossPattern(maskBottomLeft),
675
- diagonalCrossFadeBottomRight: () => diagonalCrossPattern(maskBottomRight),
676
- gridBasic: () => gridPattern(40),
677
- gridFadeTop: () => gridPattern(32, maskTop),
678
- gridFadeBottom: () => gridPattern(32, maskBottom),
679
- gridFadeCenter: () => gridPattern(40, maskCenter),
680
- gridFadeTopLeft: () => gridPattern(32, maskTopLeft),
681
- gridFadeTopRight: () => gridPattern(32, maskTopRight),
682
- gridFadeBottomLeft: () => gridPattern(32, maskBottomLeft),
683
- gridFadeBottomRight: () => gridPattern(32, maskBottomRight),
684
- gridDotsBasic: () => gridDotsPattern("grid-dots-basic"),
685
- gridDotsFadeCenter: () => gridDotsPattern("grid-dots-fade-center", maskCenter),
686
- gradientGlowTop: () => gradientGlow("top"),
687
- gradientGlowBottom: () => gradientGlow("bottom"),
688
- spotlightLeft: () => spotlight("left"),
689
- spotlightRight: () => spotlight("right")
690
- };
691
- var inlinePatternStyles = {
692
- radialGradientTop: {
693
- background: "radial-gradient(125% 125% at 50% 10%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
694
- },
695
- radialGradientBottom: {
696
- background: "radial-gradient(125% 125% at 50% 90%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
597
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
598
+ return `tel:${cleaned}`;
599
+ }
600
+ function normalizeEmail(input) {
601
+ const trimmed = input.trim();
602
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
603
+ return trimmed;
697
604
  }
698
- };
699
- function PatternBackground({
700
- pattern,
701
- opacity = 0.08,
702
- className,
703
- style
704
- }) {
705
- if (!pattern) {
706
- return null;
605
+ return `mailto:${trimmed}`;
606
+ }
607
+ function isEmail(input) {
608
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
609
+ return emailRegex.test(input.trim());
610
+ }
611
+ function isPhoneNumber(input) {
612
+ const trimmed = input.trim();
613
+ if (trimmed.toLowerCase().startsWith("tel:")) {
614
+ return true;
707
615
  }
708
- if (pattern in inlinePatternStyles) {
709
- const inlineStyle = inlinePatternStyles[pattern];
710
- return /* @__PURE__ */ jsxRuntime.jsx(
711
- "div",
712
- {
713
- className: cn("pointer-events-none absolute inset-0 z-0", className),
714
- style: { ...inlineStyle, opacity, ...style },
715
- "aria-hidden": "true"
716
- }
717
- );
616
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
617
+ return phoneRegex.test(trimmed);
618
+ }
619
+ function isInternalUrl(href) {
620
+ if (typeof window === "undefined") {
621
+ return href.startsWith("/") && !href.startsWith("//");
718
622
  }
719
- if (pattern in patternOverlays) {
720
- const Overlay = patternOverlays[pattern];
721
- return /* @__PURE__ */ jsxRuntime.jsx(
722
- "div",
723
- {
724
- className: cn("pointer-events-none absolute inset-0 z-0", className),
725
- style: { opacity, ...style },
726
- "aria-hidden": "true",
727
- children: Overlay()
728
- }
729
- );
623
+ const trimmed = href.trim();
624
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
625
+ return true;
730
626
  }
731
- const patternUrl = pattern in patternSvgs ? patternSvgs[pattern] : pattern;
732
- return /* @__PURE__ */ jsxRuntime.jsx(
733
- "div",
734
- {
735
- className: cn("pointer-events-none absolute inset-0 z-0", className),
736
- style: {
737
- backgroundImage: `url(${patternUrl})`,
738
- backgroundRepeat: "repeat",
739
- backgroundSize: "auto",
740
- opacity,
741
- ...style
742
- },
743
- "aria-hidden": "true"
627
+ try {
628
+ const url = new URL(trimmed, window.location.href);
629
+ const currentOrigin = window.location.origin;
630
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
631
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
632
+ } catch {
633
+ return false;
634
+ }
635
+ }
636
+ function toRelativePath(href) {
637
+ if (typeof window === "undefined") {
638
+ return href;
639
+ }
640
+ const trimmed = href.trim();
641
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
642
+ return trimmed;
643
+ }
644
+ try {
645
+ const url = new URL(trimmed, window.location.href);
646
+ const currentOrigin = window.location.origin;
647
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
648
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
649
+ return url.pathname + url.search + url.hash;
650
+ }
651
+ } catch {
652
+ }
653
+ return trimmed;
654
+ }
655
+ function useNavigation({
656
+ href,
657
+ onClick
658
+ } = {}) {
659
+ const linkType = React3__namespace.useMemo(() => {
660
+ if (!href || href.trim() === "") {
661
+ return onClick ? "none" : "none";
662
+ }
663
+ const trimmed = href.trim();
664
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
665
+ return "mailto";
666
+ }
667
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
668
+ return "tel";
669
+ }
670
+ if (isInternalUrl(trimmed)) {
671
+ return "internal";
672
+ }
673
+ try {
674
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
675
+ return "external";
676
+ } catch {
677
+ return "internal";
678
+ }
679
+ }, [href, onClick]);
680
+ const normalizedHref = React3__namespace.useMemo(() => {
681
+ if (!href || href.trim() === "") {
682
+ return void 0;
683
+ }
684
+ const trimmed = href.trim();
685
+ switch (linkType) {
686
+ case "tel":
687
+ return normalizePhoneNumber(trimmed);
688
+ case "mailto":
689
+ return normalizeEmail(trimmed);
690
+ case "internal":
691
+ return toRelativePath(trimmed);
692
+ case "external":
693
+ return trimmed;
694
+ default:
695
+ return trimmed;
696
+ }
697
+ }, [href, linkType]);
698
+ const target = React3__namespace.useMemo(() => {
699
+ switch (linkType) {
700
+ case "external":
701
+ return "_blank";
702
+ case "internal":
703
+ return "_self";
704
+ case "mailto":
705
+ case "tel":
706
+ return void 0;
707
+ default:
708
+ return void 0;
709
+ }
710
+ }, [linkType]);
711
+ const rel = React3__namespace.useMemo(() => {
712
+ if (linkType === "external") {
713
+ return "noopener noreferrer";
744
714
  }
715
+ return void 0;
716
+ }, [linkType]);
717
+ const isExternal = linkType === "external";
718
+ const isInternal = linkType === "internal";
719
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
720
+ const handleClick = React3__namespace.useCallback(
721
+ (event) => {
722
+ if (onClick) {
723
+ try {
724
+ onClick(event);
725
+ } catch (error) {
726
+ console.error("Error in user onClick handler:", error);
727
+ }
728
+ }
729
+ if (event.defaultPrevented) {
730
+ return;
731
+ }
732
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
733
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
734
+ if (typeof window !== "undefined") {
735
+ const handler = window.__opensiteNavigationHandler;
736
+ if (typeof handler === "function") {
737
+ try {
738
+ const handled = handler(normalizedHref, event.nativeEvent || event);
739
+ if (handled !== false) {
740
+ event.preventDefault();
741
+ }
742
+ } catch (error) {
743
+ console.error("Error in navigation handler:", error);
744
+ }
745
+ }
746
+ }
747
+ }
748
+ },
749
+ [onClick, shouldUseRouter, normalizedHref]
745
750
  );
751
+ return {
752
+ linkType,
753
+ normalizedHref,
754
+ target,
755
+ rel,
756
+ isExternal,
757
+ isInternal,
758
+ shouldUseRouter,
759
+ handleClick
760
+ };
746
761
  }
747
- var backgroundStyles = {
748
- default: "bg-background text-foreground",
749
- white: "bg-white text-dark",
750
- gray: "bg-muted/30 text-foreground",
751
- dark: "bg-foreground text-background",
752
- transparent: "bg-transparent text-foreground",
753
- gradient: "bg-linear-to-br from-primary via-primary/90 to-foreground text-primary-foreground",
754
- primary: "bg-primary text-primary-foreground",
755
- secondary: "bg-secondary text-secondary-foreground",
756
- muted: "bg-muted text-muted-foreground"
757
- };
758
- var spacingStyles = {
759
- none: "py-0 md:py-0",
760
- sm: "py-12 md:py-16",
761
- md: "py-16 md:py-24",
762
- lg: "py-20 md:py-32",
763
- xl: "py-24 md:py-40"
764
- };
765
- var predefinedSpacings = ["none", "sm", "md", "lg", "xl"];
766
- var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
767
- var Section = React__namespace.default.forwardRef(
762
+ var Pressable = React3__namespace.forwardRef(
768
763
  ({
769
- id,
770
- title,
771
- subtitle,
772
764
  children,
773
765
  className,
774
- style,
775
- background = "default",
776
- spacing = "lg",
777
- pattern,
778
- patternOpacity,
779
- patternClassName,
780
- containerClassName,
781
- containerMaxWidth = "xl",
766
+ href,
767
+ onClick,
768
+ variant,
769
+ size,
770
+ asButton = false,
771
+ fallbackComponentType = "span",
772
+ componentType,
773
+ "aria-label": ariaLabel,
774
+ "aria-describedby": ariaDescribedby,
775
+ id,
782
776
  ...props
783
777
  }, ref) => {
784
- const effectivePatternOpacity = patternOpacity !== void 0 ? patternOpacity : pattern ? 1 : 0;
785
- return /* @__PURE__ */ jsxRuntime.jsxs(
786
- "section",
778
+ const navigation = useNavigation({ href, onClick });
779
+ const {
780
+ normalizedHref,
781
+ target,
782
+ rel,
783
+ linkType,
784
+ isInternal,
785
+ handleClick
786
+ } = navigation;
787
+ const shouldRenderLink = normalizedHref && linkType !== "none";
788
+ const shouldRenderButton = !shouldRenderLink && onClick;
789
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
790
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
791
+ const shouldApplyButtonStyles = asButton || variant || size;
792
+ const combinedClassName = cn(
793
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
794
+ className
795
+ );
796
+ const dataProps = Object.fromEntries(
797
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
798
+ );
799
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
800
+ "data-slot": "button",
801
+ "data-variant": variant ?? "default",
802
+ "data-size": size ?? "default"
803
+ } : {};
804
+ const commonProps = {
805
+ className: combinedClassName,
806
+ onClick: handleClick,
807
+ "aria-label": ariaLabel,
808
+ "aria-describedby": ariaDescribedby,
809
+ id,
810
+ ...dataProps,
811
+ ...buttonDataAttributes
812
+ };
813
+ if (finalComponentType === "a" && shouldRenderLink) {
814
+ return /* @__PURE__ */ jsxRuntime.jsx(
815
+ "a",
816
+ {
817
+ ref,
818
+ href: normalizedHref,
819
+ target,
820
+ rel,
821
+ ...commonProps,
822
+ ...props,
823
+ children
824
+ }
825
+ );
826
+ }
827
+ if (finalComponentType === "button") {
828
+ return /* @__PURE__ */ jsxRuntime.jsx(
829
+ "button",
830
+ {
831
+ ref,
832
+ type: props.type || "button",
833
+ ...commonProps,
834
+ ...props,
835
+ children
836
+ }
837
+ );
838
+ }
839
+ if (finalComponentType === "div") {
840
+ return /* @__PURE__ */ jsxRuntime.jsx(
841
+ "div",
842
+ {
843
+ ref,
844
+ ...commonProps,
845
+ children
846
+ }
847
+ );
848
+ }
849
+ return /* @__PURE__ */ jsxRuntime.jsx(
850
+ "span",
787
851
  {
788
852
  ref,
789
- id,
790
- className: cn(
791
- "relative",
792
- pattern ? "overflow-hidden" : null,
793
- backgroundStyles[background],
794
- isPredefinedSpacing(spacing) ? spacingStyles[spacing] : spacing,
795
- className
796
- ),
797
- style,
798
- ...props,
799
- children: [
800
- /* @__PURE__ */ jsxRuntime.jsx(
801
- PatternBackground,
802
- {
803
- pattern,
804
- opacity: effectivePatternOpacity,
805
- className: patternClassName
806
- }
807
- ),
808
- /* @__PURE__ */ jsxRuntime.jsxs(
809
- Container,
810
- {
811
- maxWidth: containerMaxWidth,
812
- className: cn("relative z-10", containerClassName),
813
- children: [
814
- (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 text-center md:mb-16", children: [
815
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-sm font-semibold uppercase tracking-wider", children: subtitle }),
816
- title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl", children: title })
817
- ] }),
818
- children
819
- ]
820
- }
821
- )
822
- ]
853
+ ...commonProps,
854
+ children
823
855
  }
824
856
  );
825
857
  }
826
858
  );
827
- Section.displayName = "Section";
828
- var badgeVariants = classVarianceAuthority.cva(
829
- "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
830
- {
831
- variants: {
832
- variant: {
833
- default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
834
- secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
835
- destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
836
- outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
859
+ Pressable.displayName = "Pressable";
860
+ var MOBILE_CLASSES = {
861
+ "fit-left": "items-start md:items-center",
862
+ "fit-center": "items-center",
863
+ "fit-right": "items-end md:items-center",
864
+ "full-left": "items-stretch md:items-center",
865
+ "full-center": "items-stretch md:items-center",
866
+ "full-right": "items-stretch md:items-center"
867
+ };
868
+ function BlockActions({
869
+ mobileConfig,
870
+ actionsClassName,
871
+ verticalSpacing = "mt-4 md:mt-8",
872
+ actions,
873
+ actionsSlot
874
+ }) {
875
+ const width = mobileConfig?.width ?? "full";
876
+ const position = mobileConfig?.position ?? "center";
877
+ const mobileLayoutClass = MOBILE_CLASSES[`${width}-${position}`];
878
+ if (actionsSlot) {
879
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: actionsSlot });
880
+ } else if (actions && actions?.length > 0) {
881
+ return /* @__PURE__ */ jsxRuntime.jsx(
882
+ "div",
883
+ {
884
+ className: cn(
885
+ "flex flex-col md:flex-row flex-wrap gap-4",
886
+ mobileLayoutClass,
887
+ actionsClassName,
888
+ verticalSpacing
889
+ ),
890
+ children: actions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsx(ActionComponent, { action }, index))
837
891
  }
838
- },
839
- defaultVariants: {
840
- variant: "default"
841
- }
892
+ );
893
+ } else {
894
+ return null;
842
895
  }
843
- );
844
- function Badge({
845
- className,
846
- variant,
847
- asChild = false,
848
- ...props
849
- }) {
850
- const Comp = asChild ? reactSlot.Slot : "span";
896
+ }
897
+ function ActionComponent({ action }) {
898
+ const {
899
+ label,
900
+ icon,
901
+ iconAfter,
902
+ children,
903
+ href,
904
+ onClick,
905
+ className: actionClassName,
906
+ ...pressableProps
907
+ } = action;
851
908
  return /* @__PURE__ */ jsxRuntime.jsx(
852
- Comp,
909
+ Pressable,
853
910
  {
854
- "data-slot": "badge",
855
- className: cn(badgeVariants({ variant }), className),
856
- ...props
911
+ href,
912
+ onClick,
913
+ asButton: action.asButton ?? true,
914
+ className: actionClassName,
915
+ ...pressableProps,
916
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
917
+ icon,
918
+ label,
919
+ iconAfter
920
+ ] })
857
921
  }
858
922
  );
859
923
  }
@@ -867,46 +931,18 @@ function HeroMinimalCenteredDark({
867
931
  stats,
868
932
  statsSlot,
869
933
  background,
870
- spacing = "pt-32 pb-8 md:pt-32 md:pb-32",
934
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
935
+ spacing = "lg",
871
936
  pattern,
872
937
  patternOpacity,
873
938
  className,
874
- containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
875
939
  badgeClassName,
876
940
  headingClassName,
877
941
  descriptionClassName,
878
942
  actionsClassName,
879
943
  statsClassName
880
944
  }) {
881
- const renderActions = React.useMemo(() => {
882
- if (actionsSlot) return actionsSlot;
883
- if (!actions || actions.length === 0) return null;
884
- return actions.map((action, index) => {
885
- const {
886
- label,
887
- icon,
888
- iconAfter,
889
- children,
890
- className: actionClassName,
891
- ...pressableProps
892
- } = action;
893
- return /* @__PURE__ */ jsxRuntime.jsx(
894
- Pressable,
895
- {
896
- asButton: true,
897
- className: actionClassName,
898
- ...pressableProps,
899
- children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
900
- icon,
901
- label,
902
- iconAfter
903
- ] })
904
- },
905
- index
906
- );
907
- });
908
- }, [actionsSlot, actions]);
909
- const renderStats = React.useMemo(() => {
945
+ const renderStats = React3.useMemo(() => {
910
946
  if (statsSlot) return statsSlot;
911
947
  if (!stats || stats.length === 0) return null;
912
948
  return stats.map((stat, index) => /* @__PURE__ */ jsxRuntime.jsxs(
@@ -931,7 +967,7 @@ function HeroMinimalCenteredDark({
931
967
  className,
932
968
  containerClassName,
933
969
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
934
- badge && /* @__PURE__ */ jsxRuntime.jsx(Badge, { className: cn("px-3 py-2", badgeClassName), children: typeof badge === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: badge }) : badge }),
970
+ badge && /* @__PURE__ */ jsxRuntime.jsx(Badge, { className: cn("px-4 py-1", badgeClassName), children: typeof badge === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: badge }) : badge }),
935
971
  (heading || headingHighlight) && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
936
972
  "h1",
937
973
  {
@@ -961,14 +997,12 @@ function HeroMinimalCenteredDark({
961
997
  children: description
962
998
  }
963
999
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description })),
964
- (actionsSlot || actions && actions.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(
965
- "div",
1000
+ /* @__PURE__ */ jsxRuntime.jsx(
1001
+ BlockActions,
966
1002
  {
967
- className: cn(
968
- "mt-6 md:mt-10 flex flex-col gap-4 md:flex-row",
969
- actionsClassName
970
- ),
971
- children: renderActions
1003
+ actions,
1004
+ actionsSlot,
1005
+ actionsClassName
972
1006
  }
973
1007
  ),
974
1008
  (statsSlot || stats && stats.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(