@opensite/ui 2.7.1 → 2.7.2

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