@opensite/ui 2.0.6 → 2.0.8

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