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