@opensite/ui 2.0.6 → 2.0.8

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