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