@opensite/ui 2.0.2 → 2.0.4

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