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