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