@opensite/ui 2.3.6 → 2.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,253 +1,511 @@
1
1
  "use client";
2
- import * as React from 'react';
3
- import React__default, { useCallback, useMemo } from 'react';
2
+ import * as React3 from 'react';
3
+ import React3__default, { useCallback, useMemo } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { Img } from '@page-speed/img';
7
- import { cva } from 'class-variance-authority';
8
- import { jsx, jsxs } from 'react/jsx-runtime';
9
7
  import { Icon } from '@page-speed/icon';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
9
  import * as TabsPrimitive from '@radix-ui/react-tabs';
11
10
  import { Slot } from '@radix-ui/react-slot';
11
+ import { cva } from 'class-variance-authority';
12
12
 
13
13
  // components/blocks/about/community-initiatives.tsx
14
14
  function cn(...inputs) {
15
15
  return twMerge(clsx(inputs));
16
16
  }
17
- function getNestedCardBg(parentBg, variant = "muted", options) {
18
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
19
- if (isDark) {
20
- switch (variant) {
21
- case "muted":
22
- return "bg-background";
23
- case "card":
24
- return "bg-card";
25
- case "accent":
26
- return "bg-accent";
27
- case "subtle":
28
- return "bg-background/50";
29
- }
30
- } else {
31
- switch (variant) {
32
- case "muted":
33
- return "bg-muted";
34
- case "card":
35
- return "bg-card";
36
- case "accent":
37
- return "bg-accent";
38
- case "subtle":
39
- return "bg-muted/50";
40
- }
41
- }
17
+ var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
18
+ function DynamicIcon({ apiKey, ...props }) {
19
+ return /* @__PURE__ */ jsx(Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
42
20
  }
43
- function getTextColor(parentBg, variant = "default", options) {
44
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
45
- if (isDark) {
46
- switch (variant) {
47
- case "default":
48
- return "text-foreground";
49
- case "muted":
50
- return "text-foreground/80";
51
- case "subtle":
52
- return "text-foreground/60";
53
- case "accent":
54
- return "text-accent-foreground";
55
- }
56
- } else {
57
- switch (variant) {
58
- case "default":
59
- return "text-foreground";
60
- case "muted":
61
- return "text-muted-foreground";
62
- case "subtle":
63
- return "text-muted-foreground/70";
64
- case "accent":
65
- return "text-primary";
21
+ function Tabs({
22
+ className,
23
+ ...props
24
+ }) {
25
+ return /* @__PURE__ */ jsx(
26
+ TabsPrimitive.Root,
27
+ {
28
+ "data-slot": "tabs",
29
+ className: cn("flex flex-col gap-2", className),
30
+ ...props
66
31
  }
67
- }
32
+ );
68
33
  }
69
- function getAccentColor(parentBg, options) {
70
- const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
71
- return isDark ? "text-accent-foreground" : "text-primary";
34
+ function TabsList({
35
+ className,
36
+ ...props
37
+ }) {
38
+ return /* @__PURE__ */ jsx(
39
+ TabsPrimitive.List,
40
+ {
41
+ "data-slot": "tabs-list",
42
+ className: cn(
43
+ "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
44
+ className
45
+ ),
46
+ ...props
47
+ }
48
+ );
72
49
  }
73
- function normalizePhoneNumber(input) {
74
- const trimmed = input.trim();
75
- if (trimmed.toLowerCase().startsWith("tel:")) {
76
- return trimmed;
77
- }
78
- const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
79
- if (match) {
80
- const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
81
- const extension = match[3];
82
- const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
83
- const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
84
- return `tel:${withExtension}`;
85
- }
86
- const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
87
- return `tel:${cleaned}`;
50
+ function TabsTrigger({
51
+ className,
52
+ ...props
53
+ }) {
54
+ return /* @__PURE__ */ jsx(
55
+ TabsPrimitive.Trigger,
56
+ {
57
+ "data-slot": "tabs-trigger",
58
+ className: cn(
59
+ "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
60
+ className
61
+ ),
62
+ ...props
63
+ }
64
+ );
88
65
  }
89
- function normalizeEmail(input) {
90
- const trimmed = input.trim();
91
- if (trimmed.toLowerCase().startsWith("mailto:")) {
92
- return trimmed;
93
- }
94
- return `mailto:${trimmed}`;
66
+ function TabsContent({
67
+ className,
68
+ ...props
69
+ }) {
70
+ return /* @__PURE__ */ jsx(
71
+ TabsPrimitive.Content,
72
+ {
73
+ "data-slot": "tabs-content",
74
+ className: cn("flex-1 outline-none", className),
75
+ ...props
76
+ }
77
+ );
95
78
  }
96
- function isEmail(input) {
97
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
98
- return emailRegex.test(input.trim());
79
+ function Card({ className, ...props }) {
80
+ return /* @__PURE__ */ jsx(
81
+ "div",
82
+ {
83
+ "data-slot": "card",
84
+ className: cn(
85
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
86
+ className
87
+ ),
88
+ ...props
89
+ }
90
+ );
99
91
  }
100
- function isPhoneNumber(input) {
101
- const trimmed = input.trim();
102
- if (trimmed.toLowerCase().startsWith("tel:")) {
103
- return true;
104
- }
105
- const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
106
- return phoneRegex.test(trimmed);
92
+ function CardContent({ className, ...props }) {
93
+ return /* @__PURE__ */ jsx(
94
+ "div",
95
+ {
96
+ "data-slot": "card-content",
97
+ className: cn("px-6", className),
98
+ ...props
99
+ }
100
+ );
107
101
  }
108
- function isInternalUrl(href) {
109
- if (typeof window === "undefined") {
110
- return href.startsWith("/") && !href.startsWith("//");
111
- }
112
- const trimmed = href.trim();
113
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
114
- return true;
115
- }
116
- try {
117
- const url = new URL(trimmed, window.location.href);
118
- const currentOrigin = window.location.origin;
119
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
120
- return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
121
- } catch {
122
- return false;
102
+ var badgeVariants = cva(
103
+ "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",
104
+ {
105
+ variants: {
106
+ variant: {
107
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
108
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
109
+ 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",
110
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
111
+ }
112
+ },
113
+ defaultVariants: {
114
+ variant: "default"
115
+ }
123
116
  }
117
+ );
118
+ function Badge({
119
+ className,
120
+ variant,
121
+ asChild = false,
122
+ ...props
123
+ }) {
124
+ const Comp = asChild ? Slot : "span";
125
+ return /* @__PURE__ */ jsx(
126
+ Comp,
127
+ {
128
+ "data-slot": "badge",
129
+ className: cn(badgeVariants({ variant }), className),
130
+ ...props
131
+ }
132
+ );
124
133
  }
125
- function toRelativePath(href) {
126
- if (typeof window === "undefined") {
127
- return href;
134
+ var maxWidthStyles = {
135
+ sm: "max-w-screen-sm",
136
+ md: "max-w-screen-md",
137
+ lg: "max-w-screen-lg",
138
+ xl: "max-w-7xl",
139
+ "2xl": "max-w-screen-2xl",
140
+ "4xl": "max-w-[1536px]",
141
+ full: "max-w-full"
142
+ };
143
+ var Container = React3__default.forwardRef(
144
+ ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
145
+ const Component = as;
146
+ return /* @__PURE__ */ jsx(
147
+ Component,
148
+ {
149
+ ref,
150
+ className: cn(
151
+ "mx-auto w-full px-2 sm:px-4 lg:px-8",
152
+ maxWidthStyles[maxWidth],
153
+ className
154
+ ),
155
+ ...props,
156
+ children
157
+ }
158
+ );
128
159
  }
129
- const trimmed = href.trim();
130
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
131
- return trimmed;
160
+ );
161
+ Container.displayName = "Container";
162
+
163
+ // lib/patternSvgs.ts
164
+ var patternSvgs = {
165
+ squareAltGrid: "https://cdn.ing/assets/files/record/286187/4gpn0yq2ptra8iwlvmwwv860ggwv",
166
+ grid1: "https://cdn.ing/assets/files/record/286186/nbdflpgp4ostrno079hygibsflp3",
167
+ noise: "https://cdn.ing/assets/i/r/286188/zrqcp9hynh3j7p2laihwzfbujgrl/noise.png",
168
+ dots: "https://cdn.ing/assets/files/record/286198/yfsjx9thvtxzhl2qtshxyhkrm524",
169
+ dotPattern: "https://cdn.ing/assets/files/record/286192/7ig0cku8aqbboiza8nuk6hw0nnsr",
170
+ dotPattern2: "https://cdn.ing/assets/files/record/286189/arez6gd2s7isn9i1o6c7sexdq7bl",
171
+ circles: "https://cdn.ing/assets/files/record/286190/gtmia3sncjtzetdshc20zf1d3c17",
172
+ waves: "https://cdn.ing/assets/files/record/286191/mqlb33fzxz9cdth1bx7if0wmpkp1",
173
+ crossPattern: "https://cdn.ing/assets/files/record/286193/9yfqwdbnqaipbp7fsb3wbzzmq472",
174
+ architect: "https://cdn.ing/assets/files/record/286194/vgs88ugpvyhxu13wqgy0acvae6re",
175
+ tinyCheckers: "https://cdn.ing/assets/files/record/286195/65efaknsw8kcpf9o3c2gybytsl5b",
176
+ p6: "https://cdn.ing/assets/i/r/286196/6kl0rqnd6mjk8j7e525fo8fo0vkc/p6.webp"
177
+ };
178
+ var maskTop = "radial-gradient(ellipse 70% 60% at 50% 0%, #000 60%, transparent 100%)";
179
+ var maskBottom = "radial-gradient(ellipse 100% 80% at 50% 100%, #000 50%, transparent 90%)";
180
+ var maskCenter = "radial-gradient(ellipse 60% 60% at 50% 50%, #000 30%, transparent 70%)";
181
+ var maskTopLeft = "radial-gradient(ellipse 80% 80% at 0% 0%, #000 50%, transparent 90%)";
182
+ var maskTopRight = "radial-gradient(ellipse 80% 80% at 100% 0%, #000 50%, transparent 90%)";
183
+ var maskBottomLeft = "radial-gradient(ellipse 80% 80% at 0% 100%, #000 50%, transparent 90%)";
184
+ var maskBottomRight = "radial-gradient(ellipse 80% 80% at 100% 100%, #000 50%, transparent 90%)";
185
+ var circuitBoardPattern = (id, mask) => /* @__PURE__ */ jsxs(
186
+ "svg",
187
+ {
188
+ className: "h-full w-full",
189
+ xmlns: "http://www.w3.org/2000/svg",
190
+ style: mask ? {
191
+ maskImage: mask,
192
+ WebkitMaskImage: mask
193
+ } : void 0,
194
+ children: [
195
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
196
+ "pattern",
197
+ {
198
+ id,
199
+ x: "0",
200
+ y: "0",
201
+ width: "100",
202
+ height: "100",
203
+ patternUnits: "userSpaceOnUse",
204
+ children: [
205
+ /* @__PURE__ */ jsx(
206
+ "path",
207
+ {
208
+ d: "M0 50h40M60 50h40M50 0v40M50 60v40",
209
+ stroke: "hsl(var(--muted))",
210
+ strokeWidth: "1",
211
+ fill: "none"
212
+ }
213
+ ),
214
+ /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r: "3", fill: "hsl(var(--muted))" }),
215
+ /* @__PURE__ */ jsx("circle", { cx: "0", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
216
+ /* @__PURE__ */ jsx("circle", { cx: "100", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
217
+ /* @__PURE__ */ jsx("circle", { cx: "50", cy: "0", r: "2", fill: "hsl(var(--muted))" }),
218
+ /* @__PURE__ */ jsx("circle", { cx: "50", cy: "100", r: "2", fill: "hsl(var(--muted))" })
219
+ ]
220
+ }
221
+ ) }),
222
+ /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
223
+ ]
132
224
  }
133
- try {
134
- const url = new URL(trimmed, window.location.href);
135
- const currentOrigin = window.location.origin;
136
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
137
- if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
138
- return url.pathname + url.search + url.hash;
139
- }
140
- } catch {
225
+ );
226
+ var gridDotsPattern = (id, mask) => /* @__PURE__ */ jsxs(
227
+ "svg",
228
+ {
229
+ className: "h-full w-full",
230
+ xmlns: "http://www.w3.org/2000/svg",
231
+ style: mask ? {
232
+ maskImage: mask,
233
+ WebkitMaskImage: mask
234
+ } : void 0,
235
+ children: [
236
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
237
+ "pattern",
238
+ {
239
+ id,
240
+ x: "0",
241
+ y: "0",
242
+ width: "40",
243
+ height: "40",
244
+ patternUnits: "userSpaceOnUse",
245
+ children: [
246
+ /* @__PURE__ */ jsx(
247
+ "path",
248
+ {
249
+ d: "M0 20h40M20 0v40",
250
+ stroke: "hsl(var(--muted))",
251
+ strokeWidth: "0.5",
252
+ fill: "none"
253
+ }
254
+ ),
255
+ /* @__PURE__ */ jsx("circle", { cx: "20", cy: "20", r: "2", fill: "hsl(var(--muted))" })
256
+ ]
257
+ }
258
+ ) }),
259
+ /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
260
+ ]
141
261
  }
142
- return trimmed;
143
- }
144
- function useNavigation({
145
- href,
146
- onClick
147
- } = {}) {
148
- const linkType = React.useMemo(() => {
149
- if (!href || href.trim() === "") {
150
- return onClick ? "none" : "none";
151
- }
152
- const trimmed = href.trim();
153
- if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
154
- return "mailto";
155
- }
156
- if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
157
- return "tel";
158
- }
159
- if (isInternalUrl(trimmed)) {
160
- return "internal";
161
- }
162
- try {
163
- new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
164
- return "external";
165
- } catch {
166
- return "internal";
262
+ );
263
+ var gridPattern = (size, mask) => /* @__PURE__ */ jsx(
264
+ "div",
265
+ {
266
+ 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)]",
267
+ style: {
268
+ backgroundSize: `${size}px ${size}px`,
269
+ ...mask ? {
270
+ maskImage: mask,
271
+ WebkitMaskImage: mask
272
+ } : {}
167
273
  }
168
- }, [href, onClick]);
169
- const normalizedHref = React.useMemo(() => {
170
- if (!href || href.trim() === "") {
171
- return void 0;
274
+ }
275
+ );
276
+ var diagonalCrossPattern = (mask) => /* @__PURE__ */ jsx(
277
+ "div",
278
+ {
279
+ className: "h-full w-full",
280
+ style: {
281
+ 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)",
282
+ ...mask ? {
283
+ maskImage: mask,
284
+ WebkitMaskImage: mask
285
+ } : {}
172
286
  }
173
- const trimmed = href.trim();
174
- switch (linkType) {
175
- case "tel":
176
- return normalizePhoneNumber(trimmed);
177
- case "mailto":
178
- return normalizeEmail(trimmed);
179
- case "internal":
180
- return toRelativePath(trimmed);
181
- case "external":
182
- return trimmed;
183
- default:
184
- return trimmed;
287
+ }
288
+ );
289
+ 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)";
290
+ var dashedGridPattern = (fadeMask) => {
291
+ const mask = fadeMask ? `${dashedGridMaskBase}, ${fadeMask}` : dashedGridMaskBase;
292
+ return /* @__PURE__ */ jsx(
293
+ "div",
294
+ {
295
+ className: "h-full w-full",
296
+ style: {
297
+ backgroundImage: "linear-gradient(to right, hsl(var(--muted)) 1px, transparent 1px), linear-gradient(to bottom, hsl(var(--muted)) 1px, transparent 1px)",
298
+ backgroundSize: "20px 20px",
299
+ backgroundPosition: "0 0, 0 0",
300
+ maskImage: mask,
301
+ WebkitMaskImage: mask,
302
+ maskComposite: "intersect",
303
+ WebkitMaskComposite: "source-in"
304
+ }
185
305
  }
186
- }, [href, linkType]);
187
- const target = React.useMemo(() => {
188
- switch (linkType) {
189
- case "external":
190
- return "_blank";
191
- case "internal":
192
- return "_self";
193
- case "mailto":
194
- case "tel":
195
- return void 0;
196
- default:
197
- return void 0;
306
+ );
307
+ };
308
+ var gradientGlow = (position) => /* @__PURE__ */ jsx(
309
+ "div",
310
+ {
311
+ className: cn(
312
+ "pointer-events-none absolute left-1/2 z-0 aspect-square w-3/4 -translate-x-1/2 rounded-full opacity-50 blur-3xl",
313
+ position === "top" ? "-top-1/4" : "-bottom-1/4"
314
+ ),
315
+ style: {
316
+ background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
198
317
  }
199
- }, [linkType]);
200
- const rel = React.useMemo(() => {
201
- if (linkType === "external") {
202
- return "noopener noreferrer";
318
+ }
319
+ );
320
+ var spotlight = (position) => /* @__PURE__ */ jsx(
321
+ "div",
322
+ {
323
+ className: cn(
324
+ "pointer-events-none absolute top-1/2 z-0 aspect-square w-3/4 -translate-y-1/2 rounded-full opacity-40 blur-3xl",
325
+ position === "left" ? "-left-1/4" : "-right-1/4"
326
+ ),
327
+ style: {
328
+ background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
203
329
  }
204
- return void 0;
205
- }, [linkType]);
206
- const isExternal = linkType === "external";
207
- const isInternal = linkType === "internal";
208
- const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
209
- const handleClick = React.useCallback(
210
- (event) => {
211
- if (onClick) {
212
- try {
213
- onClick(event);
214
- } catch (error) {
215
- console.error("Error in user onClick handler:", error);
216
- }
330
+ }
331
+ );
332
+ var patternOverlays = {
333
+ circuitBoardBasic: () => circuitBoardPattern("circuit-board-basic"),
334
+ circuitBoardFadeTop: () => circuitBoardPattern("circuit-board-fade-top", maskTop),
335
+ circuitBoardFadeBottom: () => circuitBoardPattern("circuit-board-fade-bottom", maskBottom),
336
+ circuitBoardFadeCenter: () => circuitBoardPattern("circuit-board-fade-center", maskCenter),
337
+ circuitBoardFadeTopLeft: () => circuitBoardPattern("circuit-board-fade-top-left", maskTopLeft),
338
+ circuitBoardFadeTopRight: () => circuitBoardPattern("circuit-board-fade-top-right", maskTopRight),
339
+ circuitBoardFadeBottomLeft: () => circuitBoardPattern("circuit-board-fade-bottom-left", maskBottomLeft),
340
+ circuitBoardFadeBottomRight: () => circuitBoardPattern("circuit-board-fade-bottom-right", maskBottomRight),
341
+ dashedGridBasic: () => dashedGridPattern(),
342
+ dashedGridFadeTop: () => dashedGridPattern(maskTop),
343
+ dashedGridFadeBottom: () => dashedGridPattern(maskBottom),
344
+ dashedGridFadeCenter: () => dashedGridPattern(maskCenter),
345
+ dashedGridFadeTopLeft: () => dashedGridPattern(maskTopLeft),
346
+ dashedGridFadeTopRight: () => dashedGridPattern(maskTopRight),
347
+ dashedGridFadeBottomLeft: () => dashedGridPattern(maskBottomLeft),
348
+ dashedGridFadeBottomRight: () => dashedGridPattern(maskBottomRight),
349
+ diagonalCrossBasic: () => diagonalCrossPattern(),
350
+ diagonalCrossFadeTop: () => diagonalCrossPattern(maskTop),
351
+ diagonalCrossFadeBottom: () => diagonalCrossPattern(maskBottom),
352
+ diagonalCrossFadeCenter: () => diagonalCrossPattern(maskCenter),
353
+ diagonalCrossFadeTopLeft: () => diagonalCrossPattern(maskTopLeft),
354
+ diagonalCrossFadeTopRight: () => diagonalCrossPattern(maskTopRight),
355
+ diagonalCrossFadeBottomLeft: () => diagonalCrossPattern(maskBottomLeft),
356
+ diagonalCrossFadeBottomRight: () => diagonalCrossPattern(maskBottomRight),
357
+ gridBasic: () => gridPattern(40),
358
+ gridFadeTop: () => gridPattern(32, maskTop),
359
+ gridFadeBottom: () => gridPattern(32, maskBottom),
360
+ gridFadeCenter: () => gridPattern(40, maskCenter),
361
+ gridFadeTopLeft: () => gridPattern(32, maskTopLeft),
362
+ gridFadeTopRight: () => gridPattern(32, maskTopRight),
363
+ gridFadeBottomLeft: () => gridPattern(32, maskBottomLeft),
364
+ gridFadeBottomRight: () => gridPattern(32, maskBottomRight),
365
+ gridDotsBasic: () => gridDotsPattern("grid-dots-basic"),
366
+ gridDotsFadeCenter: () => gridDotsPattern("grid-dots-fade-center", maskCenter),
367
+ gradientGlowTop: () => gradientGlow("top"),
368
+ gradientGlowBottom: () => gradientGlow("bottom"),
369
+ spotlightLeft: () => spotlight("left"),
370
+ spotlightRight: () => spotlight("right")
371
+ };
372
+ var inlinePatternStyles = {
373
+ radialGradientTop: {
374
+ background: "radial-gradient(125% 125% at 50% 10%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
375
+ },
376
+ radialGradientBottom: {
377
+ background: "radial-gradient(125% 125% at 50% 90%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
378
+ }
379
+ };
380
+ function PatternBackground({
381
+ pattern,
382
+ opacity = 0.08,
383
+ className,
384
+ style
385
+ }) {
386
+ if (!pattern) {
387
+ return null;
388
+ }
389
+ if (pattern in inlinePatternStyles) {
390
+ const inlineStyle = inlinePatternStyles[pattern];
391
+ return /* @__PURE__ */ jsx(
392
+ "div",
393
+ {
394
+ className: cn("pointer-events-none absolute inset-0 z-0", className),
395
+ style: { ...inlineStyle, opacity, ...style },
396
+ "aria-hidden": "true"
217
397
  }
218
- if (event.defaultPrevented) {
219
- return;
398
+ );
399
+ }
400
+ if (pattern in patternOverlays) {
401
+ const Overlay = patternOverlays[pattern];
402
+ return /* @__PURE__ */ jsx(
403
+ "div",
404
+ {
405
+ className: cn("pointer-events-none absolute inset-0 z-0", className),
406
+ style: { opacity, ...style },
407
+ "aria-hidden": "true",
408
+ children: Overlay()
220
409
  }
221
- if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
222
- !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
223
- if (typeof window !== "undefined") {
224
- const handler = window.__opensiteNavigationHandler;
225
- if (typeof handler === "function") {
226
- try {
227
- const handled = handler(normalizedHref, event.nativeEvent || event);
228
- if (handled !== false) {
229
- event.preventDefault();
230
- }
231
- } catch (error) {
232
- console.error("Error in navigation handler:", error);
233
- }
234
- }
235
- }
236
- }
237
- },
238
- [onClick, shouldUseRouter, normalizedHref]
410
+ );
411
+ }
412
+ const patternUrl = pattern in patternSvgs ? patternSvgs[pattern] : pattern;
413
+ return /* @__PURE__ */ jsx(
414
+ "div",
415
+ {
416
+ className: cn("pointer-events-none absolute inset-0 z-0", className),
417
+ style: {
418
+ backgroundImage: `url(${patternUrl})`,
419
+ backgroundRepeat: "repeat",
420
+ backgroundSize: "auto",
421
+ opacity,
422
+ ...style
423
+ },
424
+ "aria-hidden": "true"
425
+ }
239
426
  );
240
- return {
241
- linkType,
242
- normalizedHref,
243
- target,
244
- rel,
245
- isExternal,
246
- isInternal,
247
- shouldUseRouter,
248
- handleClick
249
- };
250
427
  }
428
+ var backgroundStyles = {
429
+ default: "bg-background text-foreground",
430
+ white: "bg-white text-dark",
431
+ gray: "bg-muted/30 text-foreground",
432
+ dark: "bg-foreground text-background",
433
+ transparent: "bg-transparent text-foreground",
434
+ gradient: "bg-linear-to-br from-primary via-primary/90 to-foreground text-primary-foreground",
435
+ primary: "bg-primary text-primary-foreground",
436
+ secondary: "bg-secondary text-secondary-foreground",
437
+ muted: "bg-muted text-muted-foreground"
438
+ };
439
+ var spacingStyles = {
440
+ none: "py-0 md:py-0",
441
+ sm: "py-12 md:py-16",
442
+ md: "py-16 md:py-24",
443
+ lg: "py-20 md:py-32",
444
+ xl: "py-24 md:py-40"
445
+ };
446
+ var predefinedSpacings = ["none", "sm", "md", "lg", "xl"];
447
+ var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
448
+ var Section = React3__default.forwardRef(
449
+ ({
450
+ id,
451
+ title,
452
+ subtitle,
453
+ children,
454
+ className,
455
+ style,
456
+ background = "default",
457
+ spacing = "lg",
458
+ pattern,
459
+ patternOpacity,
460
+ patternClassName,
461
+ containerClassName,
462
+ containerMaxWidth = "xl",
463
+ ...props
464
+ }, ref) => {
465
+ const effectivePatternOpacity = patternOpacity !== void 0 ? patternOpacity : pattern ? 1 : 0;
466
+ return /* @__PURE__ */ jsxs(
467
+ "section",
468
+ {
469
+ ref,
470
+ id,
471
+ className: cn(
472
+ "relative",
473
+ pattern ? "overflow-hidden" : null,
474
+ backgroundStyles[background],
475
+ isPredefinedSpacing(spacing) ? spacingStyles[spacing] : spacing,
476
+ className
477
+ ),
478
+ style,
479
+ ...props,
480
+ children: [
481
+ /* @__PURE__ */ jsx(
482
+ PatternBackground,
483
+ {
484
+ pattern,
485
+ opacity: effectivePatternOpacity,
486
+ className: patternClassName
487
+ }
488
+ ),
489
+ /* @__PURE__ */ jsxs(
490
+ Container,
491
+ {
492
+ maxWidth: containerMaxWidth,
493
+ className: cn("relative z-10", containerClassName),
494
+ children: [
495
+ (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "mb-6 text-center md:mb-16", children: [
496
+ subtitle && /* @__PURE__ */ jsx("p", { className: "mb-2 text-sm font-semibold uppercase tracking-wider", children: subtitle }),
497
+ title && /* @__PURE__ */ jsx("h2", { className: "text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl", children: title })
498
+ ] }),
499
+ children
500
+ ]
501
+ }
502
+ )
503
+ ]
504
+ }
505
+ );
506
+ }
507
+ );
508
+ Section.displayName = "Section";
251
509
  var baseStyles = [
252
510
  // Layout
253
511
  "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
@@ -390,596 +648,346 @@ var buttonVariants = cva(baseStyles, {
390
648
  size: "default"
391
649
  }
392
650
  });
393
- var Pressable = React.forwardRef(
394
- ({
395
- children,
396
- className,
397
- href,
398
- onClick,
399
- variant,
400
- size,
401
- asButton = false,
402
- fallbackComponentType = "span",
403
- componentType,
404
- "aria-label": ariaLabel,
405
- "aria-describedby": ariaDescribedby,
406
- id,
407
- ...props
408
- }, ref) => {
409
- const navigation = useNavigation({ href, onClick });
410
- const {
411
- normalizedHref,
412
- target,
413
- rel,
414
- linkType,
415
- isInternal,
416
- handleClick
417
- } = navigation;
418
- const shouldRenderLink = normalizedHref && linkType !== "none";
419
- const shouldRenderButton = !shouldRenderLink && onClick;
420
- const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
421
- const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
422
- const shouldApplyButtonStyles = asButton || variant || size;
423
- const combinedClassName = cn(
424
- shouldApplyButtonStyles && buttonVariants({ variant, size }),
425
- className
426
- );
427
- const dataProps = Object.fromEntries(
428
- Object.entries(props).filter(([key]) => key.startsWith("data-"))
429
- );
430
- const buttonDataAttributes = shouldApplyButtonStyles ? {
431
- "data-slot": "button",
432
- "data-variant": variant ?? "default",
433
- "data-size": size ?? "default"
434
- } : {};
435
- const commonProps = {
436
- className: combinedClassName,
437
- onClick: handleClick,
438
- "aria-label": ariaLabel,
439
- "aria-describedby": ariaDescribedby,
440
- id,
441
- ...dataProps,
442
- ...buttonDataAttributes
443
- };
444
- if (finalComponentType === "a" && shouldRenderLink) {
445
- return /* @__PURE__ */ jsx(
446
- "a",
447
- {
448
- ref,
449
- href: normalizedHref,
450
- target,
451
- rel,
452
- ...commonProps,
453
- ...props,
454
- children
455
- }
456
- );
457
- }
458
- if (finalComponentType === "button") {
459
- return /* @__PURE__ */ jsx(
460
- "button",
461
- {
462
- ref,
463
- type: props.type || "button",
464
- ...commonProps,
465
- ...props,
466
- children
467
- }
468
- );
469
- }
470
- if (finalComponentType === "div") {
471
- return /* @__PURE__ */ jsx(
472
- "div",
473
- {
474
- ref,
475
- ...commonProps,
476
- children
477
- }
478
- );
479
- }
480
- return /* @__PURE__ */ jsx(
481
- "span",
482
- {
483
- ref,
484
- ...commonProps,
485
- children
486
- }
487
- );
651
+ function normalizePhoneNumber(input) {
652
+ const trimmed = input.trim();
653
+ if (trimmed.toLowerCase().startsWith("tel:")) {
654
+ return trimmed;
488
655
  }
489
- );
490
- Pressable.displayName = "Pressable";
491
- var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
492
- function DynamicIcon({ apiKey, ...props }) {
493
- return /* @__PURE__ */ jsx(Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
656
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
657
+ if (match) {
658
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
659
+ const extension = match[3];
660
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
661
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
662
+ return `tel:${withExtension}`;
663
+ }
664
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
665
+ return `tel:${cleaned}`;
494
666
  }
495
- function Tabs({
496
- className,
497
- ...props
498
- }) {
499
- return /* @__PURE__ */ jsx(
500
- TabsPrimitive.Root,
501
- {
502
- "data-slot": "tabs",
503
- className: cn("flex flex-col gap-2", className),
504
- ...props
505
- }
506
- );
667
+ function normalizeEmail(input) {
668
+ const trimmed = input.trim();
669
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
670
+ return trimmed;
671
+ }
672
+ return `mailto:${trimmed}`;
507
673
  }
508
- function TabsList({
509
- className,
510
- ...props
511
- }) {
512
- return /* @__PURE__ */ jsx(
513
- TabsPrimitive.List,
514
- {
515
- "data-slot": "tabs-list",
516
- className: cn(
517
- "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
518
- className
519
- ),
520
- ...props
521
- }
522
- );
674
+ function isEmail(input) {
675
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
676
+ return emailRegex.test(input.trim());
523
677
  }
524
- function TabsTrigger({
525
- className,
526
- ...props
527
- }) {
528
- return /* @__PURE__ */ jsx(
529
- TabsPrimitive.Trigger,
530
- {
531
- "data-slot": "tabs-trigger",
532
- className: cn(
533
- "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
534
- className
535
- ),
536
- ...props
537
- }
538
- );
678
+ function isPhoneNumber(input) {
679
+ const trimmed = input.trim();
680
+ if (trimmed.toLowerCase().startsWith("tel:")) {
681
+ return true;
682
+ }
683
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
684
+ return phoneRegex.test(trimmed);
539
685
  }
540
- function TabsContent({
541
- className,
542
- ...props
543
- }) {
544
- return /* @__PURE__ */ jsx(
545
- TabsPrimitive.Content,
546
- {
547
- "data-slot": "tabs-content",
548
- className: cn("flex-1 outline-none", className),
549
- ...props
550
- }
551
- );
686
+ function isInternalUrl(href) {
687
+ if (typeof window === "undefined") {
688
+ return href.startsWith("/") && !href.startsWith("//");
689
+ }
690
+ const trimmed = href.trim();
691
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
692
+ return true;
693
+ }
694
+ try {
695
+ const url = new URL(trimmed, window.location.href);
696
+ const currentOrigin = window.location.origin;
697
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
698
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
699
+ } catch {
700
+ return false;
701
+ }
552
702
  }
553
- function Card({ className, ...props }) {
554
- return /* @__PURE__ */ jsx(
555
- "div",
556
- {
557
- "data-slot": "card",
558
- className: cn(
559
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
560
- className
561
- ),
562
- ...props
703
+ function toRelativePath(href) {
704
+ if (typeof window === "undefined") {
705
+ return href;
706
+ }
707
+ const trimmed = href.trim();
708
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
709
+ return trimmed;
710
+ }
711
+ try {
712
+ const url = new URL(trimmed, window.location.href);
713
+ const currentOrigin = window.location.origin;
714
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
715
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
716
+ return url.pathname + url.search + url.hash;
563
717
  }
564
- );
718
+ } catch {
719
+ }
720
+ return trimmed;
565
721
  }
566
- function CardContent({ className, ...props }) {
567
- return /* @__PURE__ */ jsx(
568
- "div",
569
- {
570
- "data-slot": "card-content",
571
- className: cn("px-6", className),
572
- ...props
722
+ function useNavigation({
723
+ href,
724
+ onClick
725
+ } = {}) {
726
+ const linkType = React3.useMemo(() => {
727
+ if (!href || href.trim() === "") {
728
+ return onClick ? "none" : "none";
573
729
  }
574
- );
575
- }
576
- var badgeVariants = cva(
577
- "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",
578
- {
579
- variants: {
580
- variant: {
581
- default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
582
- secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
583
- 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",
584
- outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
585
- }
586
- },
587
- defaultVariants: {
588
- variant: "default"
730
+ const trimmed = href.trim();
731
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
732
+ return "mailto";
589
733
  }
590
- }
591
- );
592
- function Badge({
593
- className,
594
- variant,
595
- asChild = false,
596
- ...props
597
- }) {
598
- const Comp = asChild ? Slot : "span";
599
- return /* @__PURE__ */ jsx(
600
- Comp,
601
- {
602
- "data-slot": "badge",
603
- className: cn(badgeVariants({ variant }), className),
604
- ...props
734
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
735
+ return "tel";
605
736
  }
606
- );
607
- }
608
- var maxWidthStyles = {
609
- sm: "max-w-screen-sm",
610
- md: "max-w-screen-md",
611
- lg: "max-w-screen-lg",
612
- xl: "max-w-7xl",
613
- "2xl": "max-w-screen-2xl",
614
- "4xl": "max-w-[1536px]",
615
- full: "max-w-full"
616
- };
617
- var Container = React__default.forwardRef(
618
- ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
619
- const Component = as;
620
- return /* @__PURE__ */ jsx(
621
- Component,
622
- {
623
- ref,
624
- className: cn(
625
- "mx-auto w-full px-2 sm:px-4 lg:px-8",
626
- maxWidthStyles[maxWidth],
627
- className
628
- ),
629
- ...props,
630
- children
631
- }
632
- );
633
- }
634
- );
635
- Container.displayName = "Container";
636
-
637
- // lib/patternSvgs.ts
638
- var patternSvgs = {
639
- squareAltGrid: "https://cdn.ing/assets/files/record/286187/4gpn0yq2ptra8iwlvmwwv860ggwv",
640
- grid1: "https://cdn.ing/assets/files/record/286186/nbdflpgp4ostrno079hygibsflp3",
641
- noise: "https://cdn.ing/assets/i/r/286188/zrqcp9hynh3j7p2laihwzfbujgrl/noise.png",
642
- dots: "https://cdn.ing/assets/files/record/286198/yfsjx9thvtxzhl2qtshxyhkrm524",
643
- dotPattern: "https://cdn.ing/assets/files/record/286192/7ig0cku8aqbboiza8nuk6hw0nnsr",
644
- dotPattern2: "https://cdn.ing/assets/files/record/286189/arez6gd2s7isn9i1o6c7sexdq7bl",
645
- circles: "https://cdn.ing/assets/files/record/286190/gtmia3sncjtzetdshc20zf1d3c17",
646
- waves: "https://cdn.ing/assets/files/record/286191/mqlb33fzxz9cdth1bx7if0wmpkp1",
647
- crossPattern: "https://cdn.ing/assets/files/record/286193/9yfqwdbnqaipbp7fsb3wbzzmq472",
648
- architect: "https://cdn.ing/assets/files/record/286194/vgs88ugpvyhxu13wqgy0acvae6re",
649
- tinyCheckers: "https://cdn.ing/assets/files/record/286195/65efaknsw8kcpf9o3c2gybytsl5b",
650
- p6: "https://cdn.ing/assets/i/r/286196/6kl0rqnd6mjk8j7e525fo8fo0vkc/p6.webp"
651
- };
652
- var maskTop = "radial-gradient(ellipse 70% 60% at 50% 0%, #000 60%, transparent 100%)";
653
- var maskBottom = "radial-gradient(ellipse 100% 80% at 50% 100%, #000 50%, transparent 90%)";
654
- var maskCenter = "radial-gradient(ellipse 60% 60% at 50% 50%, #000 30%, transparent 70%)";
655
- var maskTopLeft = "radial-gradient(ellipse 80% 80% at 0% 0%, #000 50%, transparent 90%)";
656
- var maskTopRight = "radial-gradient(ellipse 80% 80% at 100% 0%, #000 50%, transparent 90%)";
657
- var maskBottomLeft = "radial-gradient(ellipse 80% 80% at 0% 100%, #000 50%, transparent 90%)";
658
- var maskBottomRight = "radial-gradient(ellipse 80% 80% at 100% 100%, #000 50%, transparent 90%)";
659
- var circuitBoardPattern = (id, mask) => /* @__PURE__ */ jsxs(
660
- "svg",
661
- {
662
- className: "h-full w-full",
663
- xmlns: "http://www.w3.org/2000/svg",
664
- style: mask ? {
665
- maskImage: mask,
666
- WebkitMaskImage: mask
667
- } : void 0,
668
- children: [
669
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
670
- "pattern",
671
- {
672
- id,
673
- x: "0",
674
- y: "0",
675
- width: "100",
676
- height: "100",
677
- patternUnits: "userSpaceOnUse",
678
- children: [
679
- /* @__PURE__ */ jsx(
680
- "path",
681
- {
682
- d: "M0 50h40M60 50h40M50 0v40M50 60v40",
683
- stroke: "hsl(var(--muted))",
684
- strokeWidth: "1",
685
- fill: "none"
686
- }
687
- ),
688
- /* @__PURE__ */ jsx("circle", { cx: "50", cy: "50", r: "3", fill: "hsl(var(--muted))" }),
689
- /* @__PURE__ */ jsx("circle", { cx: "0", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
690
- /* @__PURE__ */ jsx("circle", { cx: "100", cy: "50", r: "2", fill: "hsl(var(--muted))" }),
691
- /* @__PURE__ */ jsx("circle", { cx: "50", cy: "0", r: "2", fill: "hsl(var(--muted))" }),
692
- /* @__PURE__ */ jsx("circle", { cx: "50", cy: "100", r: "2", fill: "hsl(var(--muted))" })
693
- ]
737
+ if (isInternalUrl(trimmed)) {
738
+ return "internal";
739
+ }
740
+ try {
741
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
742
+ return "external";
743
+ } catch {
744
+ return "internal";
745
+ }
746
+ }, [href, onClick]);
747
+ const normalizedHref = React3.useMemo(() => {
748
+ if (!href || href.trim() === "") {
749
+ return void 0;
750
+ }
751
+ const trimmed = href.trim();
752
+ switch (linkType) {
753
+ case "tel":
754
+ return normalizePhoneNumber(trimmed);
755
+ case "mailto":
756
+ return normalizeEmail(trimmed);
757
+ case "internal":
758
+ return toRelativePath(trimmed);
759
+ case "external":
760
+ return trimmed;
761
+ default:
762
+ return trimmed;
763
+ }
764
+ }, [href, linkType]);
765
+ const target = React3.useMemo(() => {
766
+ switch (linkType) {
767
+ case "external":
768
+ return "_blank";
769
+ case "internal":
770
+ return "_self";
771
+ case "mailto":
772
+ case "tel":
773
+ return void 0;
774
+ default:
775
+ return void 0;
776
+ }
777
+ }, [linkType]);
778
+ const rel = React3.useMemo(() => {
779
+ if (linkType === "external") {
780
+ return "noopener noreferrer";
781
+ }
782
+ return void 0;
783
+ }, [linkType]);
784
+ const isExternal = linkType === "external";
785
+ const isInternal = linkType === "internal";
786
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
787
+ const handleClick = React3.useCallback(
788
+ (event) => {
789
+ if (onClick) {
790
+ try {
791
+ onClick(event);
792
+ } catch (error) {
793
+ console.error("Error in user onClick handler:", error);
694
794
  }
695
- ) }),
696
- /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
697
- ]
698
- }
699
- );
700
- var gridDotsPattern = (id, mask) => /* @__PURE__ */ jsxs(
701
- "svg",
702
- {
703
- className: "h-full w-full",
704
- xmlns: "http://www.w3.org/2000/svg",
705
- style: mask ? {
706
- maskImage: mask,
707
- WebkitMaskImage: mask
708
- } : void 0,
709
- children: [
710
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
711
- "pattern",
712
- {
713
- id,
714
- x: "0",
715
- y: "0",
716
- width: "40",
717
- height: "40",
718
- patternUnits: "userSpaceOnUse",
719
- children: [
720
- /* @__PURE__ */ jsx(
721
- "path",
722
- {
723
- d: "M0 20h40M20 0v40",
724
- stroke: "hsl(var(--muted))",
725
- strokeWidth: "0.5",
726
- fill: "none"
795
+ }
796
+ if (event.defaultPrevented) {
797
+ return;
798
+ }
799
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
800
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
801
+ if (typeof window !== "undefined") {
802
+ const handler = window.__opensiteNavigationHandler;
803
+ if (typeof handler === "function") {
804
+ try {
805
+ const handled = handler(normalizedHref, event.nativeEvent || event);
806
+ if (handled !== false) {
807
+ event.preventDefault();
727
808
  }
728
- ),
729
- /* @__PURE__ */ jsx("circle", { cx: "20", cy: "20", r: "2", fill: "hsl(var(--muted))" })
730
- ]
809
+ } catch (error) {
810
+ console.error("Error in navigation handler:", error);
811
+ }
812
+ }
731
813
  }
732
- ) }),
733
- /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` })
734
- ]
735
- }
736
- );
737
- var gridPattern = (size, mask) => /* @__PURE__ */ jsx(
738
- "div",
739
- {
740
- 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)]",
741
- style: {
742
- backgroundSize: `${size}px ${size}px`,
743
- ...mask ? {
744
- maskImage: mask,
745
- WebkitMaskImage: mask
746
- } : {}
747
- }
748
- }
749
- );
750
- var diagonalCrossPattern = (mask) => /* @__PURE__ */ jsx(
751
- "div",
752
- {
753
- className: "h-full w-full",
754
- style: {
755
- 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)",
756
- ...mask ? {
757
- maskImage: mask,
758
- WebkitMaskImage: mask
759
- } : {}
760
- }
761
- }
762
- );
763
- 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)";
764
- var dashedGridPattern = (fadeMask) => {
765
- const mask = fadeMask ? `${dashedGridMaskBase}, ${fadeMask}` : dashedGridMaskBase;
766
- return /* @__PURE__ */ jsx(
767
- "div",
768
- {
769
- className: "h-full w-full",
770
- style: {
771
- backgroundImage: "linear-gradient(to right, hsl(var(--muted)) 1px, transparent 1px), linear-gradient(to bottom, hsl(var(--muted)) 1px, transparent 1px)",
772
- backgroundSize: "20px 20px",
773
- backgroundPosition: "0 0, 0 0",
774
- maskImage: mask,
775
- WebkitMaskImage: mask,
776
- maskComposite: "intersect",
777
- WebkitMaskComposite: "source-in"
778
814
  }
815
+ },
816
+ [onClick, shouldUseRouter, normalizedHref]
817
+ );
818
+ return {
819
+ linkType,
820
+ normalizedHref,
821
+ target,
822
+ rel,
823
+ isExternal,
824
+ isInternal,
825
+ shouldUseRouter,
826
+ handleClick
827
+ };
828
+ }
829
+ var Pressable = React3.forwardRef(
830
+ ({
831
+ children,
832
+ className,
833
+ href,
834
+ onClick,
835
+ variant,
836
+ size,
837
+ asButton = false,
838
+ fallbackComponentType = "span",
839
+ componentType,
840
+ "aria-label": ariaLabel,
841
+ "aria-describedby": ariaDescribedby,
842
+ id,
843
+ ...props
844
+ }, ref) => {
845
+ const navigation = useNavigation({ href, onClick });
846
+ const {
847
+ normalizedHref,
848
+ target,
849
+ rel,
850
+ linkType,
851
+ isInternal,
852
+ handleClick
853
+ } = navigation;
854
+ const shouldRenderLink = normalizedHref && linkType !== "none";
855
+ const shouldRenderButton = !shouldRenderLink && onClick;
856
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
857
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
858
+ const shouldApplyButtonStyles = asButton || variant || size;
859
+ const combinedClassName = cn(
860
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
861
+ className
862
+ );
863
+ const dataProps = Object.fromEntries(
864
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
865
+ );
866
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
867
+ "data-slot": "button",
868
+ "data-variant": variant ?? "default",
869
+ "data-size": size ?? "default"
870
+ } : {};
871
+ const commonProps = {
872
+ className: combinedClassName,
873
+ onClick: handleClick,
874
+ "aria-label": ariaLabel,
875
+ "aria-describedby": ariaDescribedby,
876
+ id,
877
+ ...dataProps,
878
+ ...buttonDataAttributes
879
+ };
880
+ if (finalComponentType === "a" && shouldRenderLink) {
881
+ return /* @__PURE__ */ jsx(
882
+ "a",
883
+ {
884
+ ref,
885
+ href: normalizedHref,
886
+ target,
887
+ rel,
888
+ ...commonProps,
889
+ ...props,
890
+ children
891
+ }
892
+ );
779
893
  }
780
- );
781
- };
782
- var gradientGlow = (position) => /* @__PURE__ */ jsx(
783
- "div",
784
- {
785
- className: cn(
786
- "pointer-events-none absolute left-1/2 z-0 aspect-square w-3/4 -translate-x-1/2 rounded-full opacity-50 blur-3xl",
787
- position === "top" ? "-top-1/4" : "-bottom-1/4"
788
- ),
789
- style: {
790
- background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
894
+ if (finalComponentType === "button") {
895
+ return /* @__PURE__ */ jsx(
896
+ "button",
897
+ {
898
+ ref,
899
+ type: props.type || "button",
900
+ ...commonProps,
901
+ ...props,
902
+ children
903
+ }
904
+ );
791
905
  }
792
- }
793
- );
794
- var spotlight = (position) => /* @__PURE__ */ jsx(
795
- "div",
796
- {
797
- className: cn(
798
- "pointer-events-none absolute top-1/2 z-0 aspect-square w-3/4 -translate-y-1/2 rounded-full opacity-40 blur-3xl",
799
- position === "left" ? "-left-1/4" : "-right-1/4"
800
- ),
801
- style: {
802
- background: "radial-gradient(circle, hsl(var(--primary)) 0%, transparent 70%)"
906
+ if (finalComponentType === "div") {
907
+ return /* @__PURE__ */ jsx(
908
+ "div",
909
+ {
910
+ ref,
911
+ ...commonProps,
912
+ children
913
+ }
914
+ );
803
915
  }
804
- }
805
- );
806
- var patternOverlays = {
807
- circuitBoardBasic: () => circuitBoardPattern("circuit-board-basic"),
808
- circuitBoardFadeTop: () => circuitBoardPattern("circuit-board-fade-top", maskTop),
809
- circuitBoardFadeBottom: () => circuitBoardPattern("circuit-board-fade-bottom", maskBottom),
810
- circuitBoardFadeCenter: () => circuitBoardPattern("circuit-board-fade-center", maskCenter),
811
- circuitBoardFadeTopLeft: () => circuitBoardPattern("circuit-board-fade-top-left", maskTopLeft),
812
- circuitBoardFadeTopRight: () => circuitBoardPattern("circuit-board-fade-top-right", maskTopRight),
813
- circuitBoardFadeBottomLeft: () => circuitBoardPattern("circuit-board-fade-bottom-left", maskBottomLeft),
814
- circuitBoardFadeBottomRight: () => circuitBoardPattern("circuit-board-fade-bottom-right", maskBottomRight),
815
- dashedGridBasic: () => dashedGridPattern(),
816
- dashedGridFadeTop: () => dashedGridPattern(maskTop),
817
- dashedGridFadeBottom: () => dashedGridPattern(maskBottom),
818
- dashedGridFadeCenter: () => dashedGridPattern(maskCenter),
819
- dashedGridFadeTopLeft: () => dashedGridPattern(maskTopLeft),
820
- dashedGridFadeTopRight: () => dashedGridPattern(maskTopRight),
821
- dashedGridFadeBottomLeft: () => dashedGridPattern(maskBottomLeft),
822
- dashedGridFadeBottomRight: () => dashedGridPattern(maskBottomRight),
823
- diagonalCrossBasic: () => diagonalCrossPattern(),
824
- diagonalCrossFadeTop: () => diagonalCrossPattern(maskTop),
825
- diagonalCrossFadeBottom: () => diagonalCrossPattern(maskBottom),
826
- diagonalCrossFadeCenter: () => diagonalCrossPattern(maskCenter),
827
- diagonalCrossFadeTopLeft: () => diagonalCrossPattern(maskTopLeft),
828
- diagonalCrossFadeTopRight: () => diagonalCrossPattern(maskTopRight),
829
- diagonalCrossFadeBottomLeft: () => diagonalCrossPattern(maskBottomLeft),
830
- diagonalCrossFadeBottomRight: () => diagonalCrossPattern(maskBottomRight),
831
- gridBasic: () => gridPattern(40),
832
- gridFadeTop: () => gridPattern(32, maskTop),
833
- gridFadeBottom: () => gridPattern(32, maskBottom),
834
- gridFadeCenter: () => gridPattern(40, maskCenter),
835
- gridFadeTopLeft: () => gridPattern(32, maskTopLeft),
836
- gridFadeTopRight: () => gridPattern(32, maskTopRight),
837
- gridFadeBottomLeft: () => gridPattern(32, maskBottomLeft),
838
- gridFadeBottomRight: () => gridPattern(32, maskBottomRight),
839
- gridDotsBasic: () => gridDotsPattern("grid-dots-basic"),
840
- gridDotsFadeCenter: () => gridDotsPattern("grid-dots-fade-center", maskCenter),
841
- gradientGlowTop: () => gradientGlow("top"),
842
- gradientGlowBottom: () => gradientGlow("bottom"),
843
- spotlightLeft: () => spotlight("left"),
844
- spotlightRight: () => spotlight("right")
845
- };
846
- var inlinePatternStyles = {
847
- radialGradientTop: {
848
- background: "radial-gradient(125% 125% at 50% 10%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
849
- },
850
- radialGradientBottom: {
851
- background: "radial-gradient(125% 125% at 50% 90%, hsl(var(--background)) 40%, hsl(var(--primary)) 100%)"
852
- }
853
- };
854
- function PatternBackground({
855
- pattern,
856
- opacity = 0.08,
857
- className,
858
- style
859
- }) {
860
- if (!pattern) {
861
- return null;
862
- }
863
- if (pattern in inlinePatternStyles) {
864
- const inlineStyle = inlinePatternStyles[pattern];
865
916
  return /* @__PURE__ */ jsx(
866
- "div",
917
+ "span",
867
918
  {
868
- className: cn("pointer-events-none absolute inset-0 z-0", className),
869
- style: { ...inlineStyle, opacity, ...style },
870
- "aria-hidden": "true"
919
+ ref,
920
+ ...commonProps,
921
+ children
871
922
  }
872
923
  );
873
924
  }
874
- if (pattern in patternOverlays) {
875
- const Overlay = patternOverlays[pattern];
925
+ );
926
+ Pressable.displayName = "Pressable";
927
+ var MOBILE_CLASSES = {
928
+ "fit-left": "items-start md:items-center",
929
+ "fit-center": "items-center",
930
+ "fit-right": "items-end md:items-center",
931
+ "full-left": "items-stretch md:items-center",
932
+ "full-center": "items-stretch md:items-center",
933
+ "full-right": "items-stretch md:items-center"
934
+ };
935
+ function BlockActions({
936
+ mobileConfig,
937
+ actionsClassName,
938
+ verticalSpacing = "mt-4 md:mt-8",
939
+ actions,
940
+ actionsSlot
941
+ }) {
942
+ const width = mobileConfig?.width ?? "full";
943
+ const position = mobileConfig?.position ?? "center";
944
+ const mobileLayoutClass = MOBILE_CLASSES[`${width}-${position}`];
945
+ if (actionsSlot) {
946
+ return /* @__PURE__ */ jsx("div", { children: actionsSlot });
947
+ } else if (actions && actions?.length > 0) {
876
948
  return /* @__PURE__ */ jsx(
877
949
  "div",
878
950
  {
879
- className: cn("pointer-events-none absolute inset-0 z-0", className),
880
- style: { opacity, ...style },
881
- "aria-hidden": "true",
882
- children: Overlay()
951
+ className: cn(
952
+ "flex flex-col md:flex-row flex-wrap gap-4",
953
+ mobileLayoutClass,
954
+ actionsClassName,
955
+ verticalSpacing
956
+ ),
957
+ children: actions.map((action, index) => /* @__PURE__ */ jsx(ActionComponent, { action }, index))
883
958
  }
884
959
  );
960
+ } else {
961
+ return null;
885
962
  }
886
- const patternUrl = pattern in patternSvgs ? patternSvgs[pattern] : pattern;
963
+ }
964
+ function ActionComponent({ action }) {
965
+ const {
966
+ label,
967
+ icon,
968
+ iconAfter,
969
+ children,
970
+ href,
971
+ onClick,
972
+ className: actionClassName,
973
+ ...pressableProps
974
+ } = action;
887
975
  return /* @__PURE__ */ jsx(
888
- "div",
976
+ Pressable,
889
977
  {
890
- className: cn("pointer-events-none absolute inset-0 z-0", className),
891
- style: {
892
- backgroundImage: `url(${patternUrl})`,
893
- backgroundRepeat: "repeat",
894
- backgroundSize: "auto",
895
- opacity,
896
- ...style
897
- },
898
- "aria-hidden": "true"
978
+ href,
979
+ onClick,
980
+ asButton: action.asButton ?? true,
981
+ className: actionClassName,
982
+ ...pressableProps,
983
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
984
+ icon,
985
+ label,
986
+ iconAfter
987
+ ] })
899
988
  }
900
989
  );
901
990
  }
902
- var backgroundStyles = {
903
- default: "bg-background text-foreground",
904
- white: "bg-white text-dark",
905
- gray: "bg-muted/30 text-foreground",
906
- dark: "bg-foreground text-background",
907
- transparent: "bg-transparent text-foreground",
908
- gradient: "bg-linear-to-br from-primary via-primary/90 to-foreground text-primary-foreground",
909
- primary: "bg-primary text-primary-foreground",
910
- secondary: "bg-secondary text-secondary-foreground",
911
- muted: "bg-muted text-muted-foreground"
912
- };
913
- var spacingStyles = {
914
- none: "py-0 md:py-0",
915
- sm: "py-12 md:py-16",
916
- md: "py-16 md:py-24",
917
- lg: "py-20 md:py-32",
918
- xl: "py-24 md:py-40"
919
- };
920
- var predefinedSpacings = ["none", "sm", "md", "lg", "xl"];
921
- var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
922
- var Section = React__default.forwardRef(
923
- ({
924
- id,
925
- title,
926
- subtitle,
927
- children,
928
- className,
929
- style,
930
- background = "default",
931
- spacing = "lg",
932
- pattern,
933
- patternOpacity,
934
- patternClassName,
935
- containerClassName,
936
- containerMaxWidth = "xl",
937
- ...props
938
- }, ref) => {
939
- const effectivePatternOpacity = patternOpacity !== void 0 ? patternOpacity : pattern ? 1 : 0;
940
- return /* @__PURE__ */ jsxs(
941
- "section",
942
- {
943
- ref,
944
- id,
945
- className: cn(
946
- "relative",
947
- pattern ? "overflow-hidden" : null,
948
- backgroundStyles[background],
949
- isPredefinedSpacing(spacing) ? spacingStyles[spacing] : spacing,
950
- className
951
- ),
952
- style,
953
- ...props,
954
- children: [
955
- /* @__PURE__ */ jsx(
956
- PatternBackground,
957
- {
958
- pattern,
959
- opacity: effectivePatternOpacity,
960
- className: patternClassName
961
- }
962
- ),
963
- /* @__PURE__ */ jsxs(
964
- Container,
965
- {
966
- maxWidth: containerMaxWidth,
967
- className: cn("relative z-10", containerClassName),
968
- children: [
969
- (title || subtitle) && /* @__PURE__ */ jsxs("div", { className: "mb-6 text-center md:mb-16", children: [
970
- subtitle && /* @__PURE__ */ jsx("p", { className: "mb-2 text-sm font-semibold uppercase tracking-wider", children: subtitle }),
971
- title && /* @__PURE__ */ jsx("h2", { className: "text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl", children: title })
972
- ] }),
973
- children
974
- ]
975
- }
976
- )
977
- ]
978
- }
979
- );
980
- }
981
- );
982
- Section.displayName = "Section";
983
991
  function CommunityInitiatives({
984
992
  badgeText,
985
993
  heading,
@@ -1008,7 +1016,7 @@ function CommunityInitiatives({
1008
1016
  pattern,
1009
1017
  patternOpacity
1010
1018
  }) {
1011
- const [activeCategory, setActiveCategory] = React.useState(
1019
+ const [activeCategory, setActiveCategory] = React3.useState(
1012
1020
  categories?.[0]?.id || ""
1013
1021
  );
1014
1022
  const currentCategory = categories?.find((category) => category.id === activeCategory) || categories?.[0];
@@ -1018,28 +1026,6 @@ function CommunityInitiatives({
1018
1026
  },
1019
1027
  []
1020
1028
  );
1021
- const actionsContent = useMemo(() => {
1022
- if (actionsSlot) return actionsSlot;
1023
- if (!actions || actions.length === 0) return null;
1024
- return /* @__PURE__ */ jsx(
1025
- "div",
1026
- {
1027
- className: cn("flex flex-wrap justify-center gap-4", actionsClassName),
1028
- children: actions.map((action, idx) => /* @__PURE__ */ jsx(
1029
- Pressable,
1030
- {
1031
- href: action.href,
1032
- onClick: action.onClick,
1033
- variant: action.variant || "default",
1034
- size: action.size || "lg",
1035
- asButton: true,
1036
- children: action.label
1037
- },
1038
- idx
1039
- ))
1040
- }
1041
- );
1042
- }, [actionsSlot, actions, actionsClassName]);
1043
1029
  const categoriesContent = useMemo(() => {
1044
1030
  if (categoriesSlot) return categoriesSlot;
1045
1031
  if (!categories || categories.length === 0) return null;
@@ -1071,7 +1057,7 @@ function CommunityInitiatives({
1071
1057
  category.id
1072
1058
  )) })
1073
1059
  ] }),
1074
- /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-2xl text-left md:text-center", children: /* @__PURE__ */ jsx("p", { className: cn(getTextColor(background, "muted")), children: currentCategory?.description }) }),
1060
+ /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-2xl text-left md:text-center", children: /* @__PURE__ */ jsx("p", { className: "relative", children: currentCategory?.description }) }),
1075
1061
  categories.map((category) => /* @__PURE__ */ jsx(
1076
1062
  TabsContent,
1077
1063
  {
@@ -1093,47 +1079,13 @@ function CommunityInitiatives({
1093
1079
  ),
1094
1080
  children: [
1095
1081
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1096
- /* @__PURE__ */ jsx(
1097
- "div",
1098
- {
1099
- className: cn(
1100
- "rounded-md p-2",
1101
- getNestedCardBg(background, "muted")
1102
- ),
1103
- children: /* @__PURE__ */ jsx(
1104
- DynamicIcon,
1105
- {
1106
- name: initiative.icon,
1107
- size: 24,
1108
- className: cn(getAccentColor(background))
1109
- }
1110
- )
1111
- }
1112
- ),
1082
+ /* @__PURE__ */ jsx("div", { className: cn("rounded-md p-2"), children: /* @__PURE__ */ jsx(DynamicIcon, { name: initiative.icon, size: 24 }) }),
1113
1083
  /* @__PURE__ */ jsx("h3", { className: "text-2xl font-bold", children: initiative.title })
1114
1084
  ] }),
1115
- /* @__PURE__ */ jsx("p", { className: cn(getTextColor(background, "muted")), children: initiative.description }),
1085
+ /* @__PURE__ */ jsx("p", { className: "relative", children: initiative.description }),
1116
1086
  initiative.metrics && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-4 pt-2", children: initiative.metrics.map((metric, i) => /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1117
- /* @__PURE__ */ jsx(
1118
- "div",
1119
- {
1120
- className: cn(
1121
- "text-2xl font-bold",
1122
- getAccentColor(background)
1123
- ),
1124
- children: metric.value
1125
- }
1126
- ),
1127
- /* @__PURE__ */ jsx(
1128
- "div",
1129
- {
1130
- className: cn(
1131
- "mt-1 text-xs",
1132
- getTextColor(background, "muted")
1133
- ),
1134
- children: metric.label
1135
- }
1136
- )
1087
+ /* @__PURE__ */ jsx("div", { className: cn("text-2xl font-bold"), children: metric.value }),
1088
+ /* @__PURE__ */ jsx("div", { className: cn("mt-1 text-xs"), children: metric.label })
1137
1089
  ] }, i)) })
1138
1090
  ]
1139
1091
  }
@@ -1166,8 +1118,7 @@ function CommunityInitiatives({
1166
1118
  Card,
1167
1119
  {
1168
1120
  className: cn(
1169
- "flex h-full min-h-[280px] w-full items-center justify-center",
1170
- getNestedCardBg(background, "subtle")
1121
+ "flex h-full min-h-[280px] w-full items-center justify-center"
1171
1122
  ),
1172
1123
  children: /* @__PURE__ */ jsxs(CardContent, { className: "p-6 text-center", children: [
1173
1124
  /* @__PURE__ */ jsx(
@@ -1175,11 +1126,7 @@ function CommunityInitiatives({
1175
1126
  {
1176
1127
  name: initiative.icon,
1177
1128
  size: 64,
1178
- className: cn(
1179
- "mx-auto mb-4",
1180
- getTextColor(background, "muted"),
1181
- "opacity-50"
1182
- )
1129
+ className: cn("mx-auto mb-4", "opacity-50")
1183
1130
  }
1184
1131
  ),
1185
1132
  /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "mx-auto", children: [
@@ -1248,30 +1195,45 @@ function CommunityInitiatives({
1248
1195
  }
1249
1196
  ),
1250
1197
  categoriesContent,
1251
- /* @__PURE__ */ jsxs("div", { className: cn("mt-20 text-center", ctaClassName), children: [
1252
- ctaBadgeText && /* @__PURE__ */ jsx(
1253
- "div",
1254
- {
1255
- className: cn(
1256
- "mb-8 inline-flex items-center justify-center rounded-full p-1"
1257
- ),
1258
- children: /* @__PURE__ */ jsx(Badge, { className: "rounded-full bg-primary px-4 py-1 text-primary-foreground", children: ctaBadgeText })
1259
- }
1260
- ),
1261
- ctaHeading && (typeof ctaHeading === "string" ? /* @__PURE__ */ jsx("h3", { className: cn("mb-4 text-2xl font-bold", ctaHeadingClassName), children: ctaHeading }) : ctaHeading),
1262
- ctaDescription && (typeof ctaDescription === "string" ? /* @__PURE__ */ jsx(
1263
- "p",
1264
- {
1265
- className: cn(
1266
- "mx-auto mb-8 max-w-2xl",
1267
- getTextColor(background, "muted"),
1268
- ctaDescriptionClassName
1198
+ /* @__PURE__ */ jsxs(
1199
+ "div",
1200
+ {
1201
+ className: cn(
1202
+ "mt-10 md:mt-24 p-6 md:p-16",
1203
+ "text-center flex flex-col items-center",
1204
+ "bg-muted text-muted-foreground",
1205
+ "rounded-2xl shadow-lg",
1206
+ ctaClassName
1207
+ ),
1208
+ children: [
1209
+ ctaBadgeText && /* @__PURE__ */ jsx(
1210
+ "div",
1211
+ {
1212
+ className: cn(
1213
+ "mb-8 inline-flex items-center justify-center rounded-full p-1"
1214
+ ),
1215
+ children: /* @__PURE__ */ jsx(Badge, { className: "rounded-full bg-primary px-4 py-1 text-primary-foreground", children: ctaBadgeText })
1216
+ }
1269
1217
  ),
1270
- children: ctaDescription
1271
- }
1272
- ) : ctaDescription),
1273
- actionsContent
1274
- ] })
1218
+ ctaHeading && (typeof ctaHeading === "string" ? /* @__PURE__ */ jsx("h3", { className: cn("mb-4 text-2xl font-bold", ctaHeadingClassName), children: ctaHeading }) : ctaHeading),
1219
+ ctaDescription && (typeof ctaDescription === "string" ? /* @__PURE__ */ jsx(
1220
+ "p",
1221
+ {
1222
+ className: cn("mx-auto mb-8 max-w-2xl", ctaDescriptionClassName),
1223
+ children: ctaDescription
1224
+ }
1225
+ ) : ctaDescription),
1226
+ /* @__PURE__ */ jsx(
1227
+ BlockActions,
1228
+ {
1229
+ actions,
1230
+ actionsSlot,
1231
+ actionsClassName
1232
+ }
1233
+ )
1234
+ ]
1235
+ }
1236
+ )
1275
1237
  ]
1276
1238
  }
1277
1239
  );