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