@opensite/ui 2.3.7 → 2.3.9

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