@opensite/ui 2.0.2 → 2.0.4

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