@opensite/ui 2.1.9 → 2.2.2

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.
@@ -2,13 +2,13 @@
2
2
  'use strict';
3
3
 
4
4
  var React = require('react');
5
- var forms = require('@page-speed/forms');
5
+ var framerMotion = require('framer-motion');
6
6
  var integration = require('@page-speed/forms/integration');
7
7
  var clsx = require('clsx');
8
8
  var tailwindMerge = require('tailwind-merge');
9
- var classVarianceAuthority = require('class-variance-authority');
10
- var jsxRuntime = require('react/jsx-runtime');
11
9
  var img = require('@page-speed/img');
10
+ var icon = require('@page-speed/icon');
11
+ var jsxRuntime = require('react/jsx-runtime');
12
12
 
13
13
  function _interopNamespace(e) {
14
14
  if (e && e.__esModule) return e;
@@ -34,446 +34,9 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
34
  function cn(...inputs) {
35
35
  return tailwindMerge.twMerge(clsx.clsx(inputs));
36
36
  }
37
- function normalizePhoneNumber(input) {
38
- const trimmed = input.trim();
39
- if (trimmed.toLowerCase().startsWith("tel:")) {
40
- return trimmed;
41
- }
42
- const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
43
- if (match) {
44
- const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
45
- const extension = match[3];
46
- const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
47
- const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
48
- return `tel:${withExtension}`;
49
- }
50
- const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
51
- return `tel:${cleaned}`;
52
- }
53
- function normalizeEmail(input) {
54
- const trimmed = input.trim();
55
- if (trimmed.toLowerCase().startsWith("mailto:")) {
56
- return trimmed;
57
- }
58
- return `mailto:${trimmed}`;
59
- }
60
- function isEmail(input) {
61
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
62
- return emailRegex.test(input.trim());
63
- }
64
- function isPhoneNumber(input) {
65
- const trimmed = input.trim();
66
- if (trimmed.toLowerCase().startsWith("tel:")) {
67
- return true;
68
- }
69
- const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
70
- return phoneRegex.test(trimmed);
71
- }
72
- function isInternalUrl(href) {
73
- if (typeof window === "undefined") {
74
- return href.startsWith("/") && !href.startsWith("//");
75
- }
76
- const trimmed = href.trim();
77
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
78
- return true;
79
- }
80
- try {
81
- const url = new URL(trimmed, window.location.href);
82
- const currentOrigin = window.location.origin;
83
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
84
- return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
85
- } catch {
86
- return false;
87
- }
88
- }
89
- function toRelativePath(href) {
90
- if (typeof window === "undefined") {
91
- return href;
92
- }
93
- const trimmed = href.trim();
94
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
95
- return trimmed;
96
- }
97
- try {
98
- const url = new URL(trimmed, window.location.href);
99
- const currentOrigin = window.location.origin;
100
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
101
- if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
102
- return url.pathname + url.search + url.hash;
103
- }
104
- } catch {
105
- }
106
- return trimmed;
107
- }
108
- function useNavigation({
109
- href,
110
- onClick
111
- } = {}) {
112
- const linkType = React__namespace.useMemo(() => {
113
- if (!href || href.trim() === "") {
114
- return onClick ? "none" : "none";
115
- }
116
- const trimmed = href.trim();
117
- if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
118
- return "mailto";
119
- }
120
- if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
121
- return "tel";
122
- }
123
- if (isInternalUrl(trimmed)) {
124
- return "internal";
125
- }
126
- try {
127
- new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
128
- return "external";
129
- } catch {
130
- return "internal";
131
- }
132
- }, [href, onClick]);
133
- const normalizedHref = React__namespace.useMemo(() => {
134
- if (!href || href.trim() === "") {
135
- return void 0;
136
- }
137
- const trimmed = href.trim();
138
- switch (linkType) {
139
- case "tel":
140
- return normalizePhoneNumber(trimmed);
141
- case "mailto":
142
- return normalizeEmail(trimmed);
143
- case "internal":
144
- return toRelativePath(trimmed);
145
- case "external":
146
- return trimmed;
147
- default:
148
- return trimmed;
149
- }
150
- }, [href, linkType]);
151
- const target = React__namespace.useMemo(() => {
152
- switch (linkType) {
153
- case "external":
154
- return "_blank";
155
- case "internal":
156
- return "_self";
157
- case "mailto":
158
- case "tel":
159
- return void 0;
160
- default:
161
- return void 0;
162
- }
163
- }, [linkType]);
164
- const rel = React__namespace.useMemo(() => {
165
- if (linkType === "external") {
166
- return "noopener noreferrer";
167
- }
168
- return void 0;
169
- }, [linkType]);
170
- const isExternal = linkType === "external";
171
- const isInternal = linkType === "internal";
172
- const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
173
- const handleClick = React__namespace.useCallback(
174
- (event) => {
175
- if (onClick) {
176
- try {
177
- onClick(event);
178
- } catch (error) {
179
- console.error("Error in user onClick handler:", error);
180
- }
181
- }
182
- if (event.defaultPrevented) {
183
- return;
184
- }
185
- if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
186
- !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
187
- if (typeof window !== "undefined") {
188
- const handler = window.__opensiteNavigationHandler;
189
- if (typeof handler === "function") {
190
- try {
191
- const handled = handler(normalizedHref, event.nativeEvent || event);
192
- if (handled !== false) {
193
- event.preventDefault();
194
- }
195
- } catch (error) {
196
- console.error("Error in navigation handler:", error);
197
- }
198
- }
199
- }
200
- }
201
- },
202
- [onClick, shouldUseRouter, normalizedHref]
203
- );
204
- return {
205
- linkType,
206
- normalizedHref,
207
- target,
208
- rel,
209
- isExternal,
210
- isInternal,
211
- shouldUseRouter,
212
- handleClick
213
- };
214
- }
215
- var baseStyles = [
216
- // Layout
217
- "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
218
- // Typography - using CSS variables with sensible defaults
219
- "font-[var(--button-font-family,inherit)]",
220
- "font-[var(--button-font-weight,500)]",
221
- "tracking-[var(--button-letter-spacing,0)]",
222
- "leading-[var(--button-line-height,1.25)]",
223
- "[text-transform:var(--button-text-transform,none)]",
224
- "text-sm",
225
- // Border radius
226
- "rounded-[var(--button-radius,var(--radius,0.375rem))]",
227
- // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
228
- "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
229
- // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
230
- "[box-shadow:var(--button-shadow,none)]",
231
- "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
232
- // Disabled state
233
- "disabled:pointer-events-none disabled:opacity-50",
234
- // SVG handling
235
- "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
236
- // Focus styles
237
- "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
238
- // Invalid state
239
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
240
- ].join(" ");
241
- var buttonVariants = classVarianceAuthority.cva(baseStyles, {
242
- variants: {
243
- variant: {
244
- // Default (Primary) variant - full customization
245
- default: [
246
- "bg-[var(--button-default-bg,hsl(var(--primary)))]",
247
- "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
248
- "border-[length:var(--button-default-border-width,0px)]",
249
- "border-[color:var(--button-default-border,transparent)]",
250
- "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
251
- "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
252
- "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
253
- "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
254
- "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
255
- ].join(" "),
256
- // Destructive variant - full customization
257
- destructive: [
258
- "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
259
- "text-[var(--button-destructive-fg,white)]",
260
- "border-[length:var(--button-destructive-border-width,0px)]",
261
- "border-[color:var(--button-destructive-border,transparent)]",
262
- "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
263
- "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
264
- "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
265
- "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
266
- "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
267
- "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
268
- "dark:bg-destructive/60"
269
- ].join(" "),
270
- // Outline variant - full customization with proper border handling
271
- outline: [
272
- "bg-[var(--button-outline-bg,hsl(var(--background)))]",
273
- "text-[var(--button-outline-fg,inherit)]",
274
- "border-[length:var(--button-outline-border-width,1px)]",
275
- "border-[color:var(--button-outline-border,hsl(var(--border)))]",
276
- "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
277
- "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
278
- "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
279
- "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
280
- "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
281
- "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
282
- ].join(" "),
283
- // Secondary variant - full customization
284
- secondary: [
285
- "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
286
- "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
287
- "border-[length:var(--button-secondary-border-width,0px)]",
288
- "border-[color:var(--button-secondary-border,transparent)]",
289
- "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
290
- "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
291
- "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
292
- "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
293
- "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
294
- ].join(" "),
295
- // Ghost variant - full customization
296
- ghost: [
297
- "bg-[var(--button-ghost-bg,transparent)]",
298
- "text-[var(--button-ghost-fg,inherit)]",
299
- "border-[length:var(--button-ghost-border-width,0px)]",
300
- "border-[color:var(--button-ghost-border,transparent)]",
301
- "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
302
- "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
303
- "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
304
- "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
305
- "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
306
- "dark:hover:bg-accent/50"
307
- ].join(" "),
308
- // Link variant - full customization
309
- link: [
310
- "bg-[var(--button-link-bg,transparent)]",
311
- "text-[var(--button-link-fg,hsl(var(--primary)))]",
312
- "border-[length:var(--button-link-border-width,0px)]",
313
- "border-[color:var(--button-link-border,transparent)]",
314
- "[box-shadow:var(--button-link-shadow,none)]",
315
- "hover:bg-[var(--button-link-hover-bg,transparent)]",
316
- "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
317
- "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
318
- "underline-offset-4 hover:underline"
319
- ].join(" ")
320
- },
321
- size: {
322
- default: [
323
- "h-[var(--button-height-md,2.25rem)]",
324
- "px-[var(--button-padding-x-md,1rem)]",
325
- "py-[var(--button-padding-y-md,0.5rem)]",
326
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
327
- ].join(" "),
328
- sm: [
329
- "h-[var(--button-height-sm,2rem)]",
330
- "px-[var(--button-padding-x-sm,0.75rem)]",
331
- "py-[var(--button-padding-y-sm,0.25rem)]",
332
- "gap-1.5",
333
- "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
334
- ].join(" "),
335
- md: [
336
- "h-[var(--button-height-md,2.25rem)]",
337
- "px-[var(--button-padding-x-md,1rem)]",
338
- "py-[var(--button-padding-y-md,0.5rem)]",
339
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
340
- ].join(" "),
341
- lg: [
342
- "h-[var(--button-height-lg,2.5rem)]",
343
- "px-[var(--button-padding-x-lg,1.5rem)]",
344
- "py-[var(--button-padding-y-lg,0.5rem)]",
345
- "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
346
- ].join(" "),
347
- icon: "size-[var(--button-height-md,2.25rem)]",
348
- "icon-sm": "size-[var(--button-height-sm,2rem)]",
349
- "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
350
- }
351
- },
352
- defaultVariants: {
353
- variant: "default",
354
- size: "default"
355
- }
356
- });
357
- var Pressable = React__namespace.forwardRef(
358
- ({
359
- children,
360
- className,
361
- href,
362
- onClick,
363
- variant,
364
- size,
365
- asButton = false,
366
- fallbackComponentType = "span",
367
- componentType,
368
- "aria-label": ariaLabel,
369
- "aria-describedby": ariaDescribedby,
370
- id,
371
- ...props
372
- }, ref) => {
373
- const navigation = useNavigation({ href, onClick });
374
- const {
375
- normalizedHref,
376
- target,
377
- rel,
378
- linkType,
379
- isInternal,
380
- handleClick
381
- } = navigation;
382
- const shouldRenderLink = normalizedHref && linkType !== "none";
383
- const shouldRenderButton = !shouldRenderLink && onClick;
384
- const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
385
- const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
386
- const shouldApplyButtonStyles = asButton || variant || size;
387
- const combinedClassName = cn(
388
- shouldApplyButtonStyles && buttonVariants({ variant, size }),
389
- className
390
- );
391
- const dataProps = Object.fromEntries(
392
- Object.entries(props).filter(([key]) => key.startsWith("data-"))
393
- );
394
- const buttonDataAttributes = shouldApplyButtonStyles ? {
395
- "data-slot": "button",
396
- "data-variant": variant ?? "default",
397
- "data-size": size ?? "default"
398
- } : {};
399
- const commonProps = {
400
- className: combinedClassName,
401
- onClick: handleClick,
402
- "aria-label": ariaLabel,
403
- "aria-describedby": ariaDescribedby,
404
- id,
405
- ...dataProps,
406
- ...buttonDataAttributes
407
- };
408
- if (finalComponentType === "a" && shouldRenderLink) {
409
- return /* @__PURE__ */ jsxRuntime.jsx(
410
- "a",
411
- {
412
- ref,
413
- href: normalizedHref,
414
- target,
415
- rel,
416
- ...commonProps,
417
- ...props,
418
- children
419
- }
420
- );
421
- }
422
- if (finalComponentType === "button") {
423
- return /* @__PURE__ */ jsxRuntime.jsx(
424
- "button",
425
- {
426
- ref,
427
- type: props.type || "button",
428
- ...commonProps,
429
- ...props,
430
- children
431
- }
432
- );
433
- }
434
- if (finalComponentType === "div") {
435
- return /* @__PURE__ */ jsxRuntime.jsx(
436
- "div",
437
- {
438
- ref,
439
- ...commonProps,
440
- children
441
- }
442
- );
443
- }
444
- return /* @__PURE__ */ jsxRuntime.jsx(
445
- "span",
446
- {
447
- ref,
448
- ...commonProps,
449
- children
450
- }
451
- );
452
- }
453
- );
454
- Pressable.displayName = "Pressable";
455
- function Card({ className, ...props }) {
456
- return /* @__PURE__ */ jsxRuntime.jsx(
457
- "div",
458
- {
459
- "data-slot": "card",
460
- className: cn(
461
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
462
- className
463
- ),
464
- ...props
465
- }
466
- );
467
- }
468
- function CardContent({ className, ...props }) {
469
- return /* @__PURE__ */ jsxRuntime.jsx(
470
- "div",
471
- {
472
- "data-slot": "card-content",
473
- className: cn("px-6", className),
474
- ...props
475
- }
476
- );
37
+ var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
38
+ function DynamicIcon({ apiKey, ...props }) {
39
+ return /* @__PURE__ */ jsxRuntime.jsx(icon.Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
477
40
  }
478
41
  var maxWidthStyles = {
479
42
  sm: "max-w-screen-sm",
@@ -850,6 +413,12 @@ var Section = React__namespace.default.forwardRef(
850
413
  }
851
414
  );
852
415
  Section.displayName = "Section";
416
+ var DEFAULT_STYLE_RULES = {
417
+ formContainer: "",
418
+ fieldsContainer: "",
419
+ fieldClassName: "",
420
+ formClassName: "space-y-4"
421
+ };
853
422
  var DEFAULT_FORM_FIELDS = [
854
423
  {
855
424
  name: "first_name",
@@ -894,207 +463,172 @@ var DEFAULT_FORM_FIELDS = [
894
463
  }
895
464
  ];
896
465
  function ContactImage({
466
+ eyebrow,
897
467
  heading,
898
468
  description,
899
- buttonText = "Submit",
469
+ buttonText = "Send Message",
900
470
  buttonIcon,
901
- actions,
902
- actionsSlot,
903
- formFields = DEFAULT_FORM_FIELDS,
904
- successMessage = "Thank you! Your message has been sent successfully.",
471
+ image,
472
+ contactOverlays,
473
+ contactOverlaysSlot,
474
+ formEngineSetup,
475
+ className,
476
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
477
+ contentClassName,
478
+ eyebrowClassName,
905
479
  headingClassName,
906
480
  descriptionClassName,
907
- cardClassName,
908
- cardContentClassName,
909
- formClassName,
910
- submitClassName,
911
- successMessageClassName,
912
- errorMessageClassName,
913
- backgroundImage,
481
+ imageClassName,
482
+ contactOverlaysClassName,
914
483
  background,
915
- optixFlowConfig,
916
- spacing = "none",
917
- className,
918
- containerClassName = "px-0 sm:px-0 lg:px-0 max-w-full relative z-10 h-screen w-screen flex justify-center items-center",
919
- contentClassName = "",
484
+ spacing = "py-16 md:py-32",
920
485
  pattern,
921
- patternOpacity = 0.1,
922
- formConfig,
923
- onSubmit,
924
- onSuccess,
925
- onError
486
+ patternOpacity,
487
+ optixFlowConfig
926
488
  }) {
927
- const {
928
- uploadTokens,
929
- uploadProgress,
930
- isUploading,
931
- uploadFiles,
932
- removeFile,
933
- resetUpload
934
- } = integration.useFileUpload({ onError });
935
- const { form, submissionError, formMethod, resetSubmissionState } = integration.useContactForm({
936
- formFields,
937
- formConfig,
938
- onSubmit,
939
- onSuccess: (data) => {
940
- resetUpload();
941
- onSuccess?.(data);
942
- },
943
- onError,
944
- resetOnSuccess: formConfig?.resetOnSuccess !== false,
945
- uploadTokens
946
- });
947
- const actionsContent = React.useMemo(() => {
948
- if (actionsSlot) return actionsSlot;
949
- if (actions && actions.length > 0) {
950
- return actions.map((action, index) => {
951
- const {
952
- label,
953
- icon,
954
- iconAfter,
955
- children,
956
- className: actionClassName,
957
- ...pressableProps
958
- } = action;
489
+ const contactOverlaysContent = React__namespace.useMemo(() => {
490
+ if (contactOverlaysSlot) return contactOverlaysSlot;
491
+ if (!contactOverlays || contactOverlays.length === 0) return null;
492
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-3", contactOverlaysClassName), children: contactOverlays.map((item, index) => {
493
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(
494
+ "div",
495
+ {
496
+ className: cn(
497
+ "rounded-2xl border border-white/10 bg-foreground/80 p-4 backdrop-blur-sm",
498
+ item.className
499
+ ),
500
+ children: [
501
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
502
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-fit p-2 items-center justify-center rounded-full bg-primary text-primary-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: item.icon, size: 18 }) }),
503
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
504
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-bold uppercase tracking-[0.15em] text-background/70", children: item.label }),
505
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-background", children: item.title })
506
+ ] })
507
+ ] }),
508
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-background/80", children: item.description })
509
+ ]
510
+ }
511
+ );
512
+ if (item.href) {
959
513
  return /* @__PURE__ */ jsxRuntime.jsx(
960
- Pressable,
514
+ "a",
961
515
  {
962
- asButton: true,
963
- className: actionClassName,
964
- ...pressableProps,
965
- children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
966
- icon,
967
- label,
968
- iconAfter
969
- ] })
516
+ href: item.href,
517
+ className: "block transition-transform hover:scale-[1.02]",
518
+ children: content
970
519
  },
971
520
  index
972
521
  );
973
- });
974
- }
975
- return null;
976
- }, [actionsSlot, actions]);
977
- const renderBackground = React.useMemo(() => {
978
- if (!backgroundImage) return null;
979
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0", children: [
980
- /* @__PURE__ */ jsxRuntime.jsx(
981
- img.Img,
982
- {
983
- src: backgroundImage,
984
- alt: "Full screen background image",
985
- className: "h-full w-full object-cover",
986
- loading: "eager",
987
- optixFlowConfig
988
- }
989
- ),
990
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-linear-to-b from-black/80 via-black/65 to-black/20" })
991
- ] });
992
- }, [backgroundImage, optixFlowConfig]);
993
- return /* @__PURE__ */ jsxRuntime.jsxs(
522
+ }
523
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: content }, index);
524
+ }) });
525
+ }, [contactOverlaysSlot, contactOverlays, contactOverlaysClassName]);
526
+ return /* @__PURE__ */ jsxRuntime.jsx(
994
527
  Section,
995
528
  {
996
529
  background,
997
530
  spacing,
531
+ className,
532
+ containerClassName,
998
533
  pattern,
999
534
  patternOpacity,
1000
- className: cn(
1001
- "relative flex h-full min-h-screen w-screen items-center justify-center overflow-hidden bg-black pb-0 pt-0 md:pt-0 px-0",
1002
- className
1003
- ),
1004
- containerClassName,
1005
- children: [
1006
- renderBackground,
1007
- /* @__PURE__ */ jsxRuntime.jsx(
1008
- "div",
1009
- {
1010
- className: cn(
1011
- "flex flex-col gap-4 md:gap-6 px-6 pt-28 pb-6 md:pt-0 md:pb-0",
1012
- "relative z-30 m-auto max-w-full md:max-w-md flex-col items-center justify-center text-center",
1013
- contentClassName
1014
- ),
1015
- children: /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn("mx-auto max-w-xl", cardClassName), children: /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: cn("p-6 lg:p-8", cardContentClassName), children: [
1016
- heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1017
- "h2",
1018
- {
1019
- className: cn(
1020
- "text-5xl md:text-6xl lg:text-7xl text-card-foreground text-shadow-2xl font-semibold",
1021
- headingClassName
1022
- ),
1023
- children: heading
1024
- }
1025
- ) : heading),
1026
- description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1027
- "p",
1028
- {
1029
- className: cn(
1030
- "text-center text-base text-balance text-card-foreground text-shadow-2xl",
1031
- descriptionClassName
535
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
536
+ "div",
537
+ {
538
+ className: cn(
539
+ "grid grid-cols-1 items-center gap-12 lg:grid-cols-2",
540
+ contentClassName
541
+ ),
542
+ children: [
543
+ image && /* @__PURE__ */ jsxRuntime.jsx(
544
+ framerMotion.motion.div,
545
+ {
546
+ initial: { opacity: 0, x: -20 },
547
+ whileInView: { opacity: 1, x: 0 },
548
+ viewport: { once: true, margin: "-50px" },
549
+ transition: { duration: 0.5 },
550
+ className: "order-2 lg:order-1",
551
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-hidden rounded-3xl border border-white/10 shadow-2xl", children: [
552
+ /* @__PURE__ */ jsxRuntime.jsx(
553
+ img.Img,
554
+ {
555
+ src: image.src,
556
+ alt: image.alt,
557
+ className: cn("h-full w-full object-cover", imageClassName),
558
+ optixFlowConfig
559
+ }
1032
560
  ),
1033
- children: description
1034
- }
1035
- ) : description),
1036
- /* @__PURE__ */ jsxRuntime.jsxs(
1037
- forms.Form,
1038
- {
1039
- form,
1040
- notificationConfig: {
1041
- submissionError,
1042
- successMessage
1043
- },
1044
- styleConfig: {
1045
- formClassName: cn("space-y-4", formClassName),
1046
- successMessageClassName,
1047
- errorMessageClassName
1048
- },
1049
- formConfig: {
1050
- endpoint: formConfig?.endpoint,
1051
- method: formMethod,
1052
- submissionConfig: formConfig?.submissionConfig
1053
- },
1054
- onNewSubmission: () => {
1055
- resetUpload();
1056
- resetSubmissionState();
1057
- },
1058
- children: [
1059
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-12 gap-6", children: formFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
1060
- "div",
1061
- {
1062
- className: integration.getColumnSpanClass(field.columnSpan),
1063
- children: /* @__PURE__ */ jsxRuntime.jsx(
1064
- integration.DynamicFormField,
1065
- {
1066
- field,
1067
- uploadProgress,
1068
- onFileUpload: uploadFiles,
1069
- onFileRemove: removeFile,
1070
- isUploading
561
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-linear-to-tr from-black/70 via-transparent to-transparent" }),
562
+ contactOverlaysContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-6 left-6 right-6", children: contactOverlaysContent })
563
+ ] })
564
+ }
565
+ ),
566
+ /* @__PURE__ */ jsxRuntime.jsxs(
567
+ framerMotion.motion.div,
568
+ {
569
+ initial: { opacity: 0, x: 20 },
570
+ whileInView: { opacity: 1, x: 0 },
571
+ viewport: { once: true, margin: "-50px" },
572
+ transition: { duration: 0.5 },
573
+ className: "order-1 lg:order-2",
574
+ children: [
575
+ eyebrow && (typeof eyebrow === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
576
+ "p",
577
+ {
578
+ className: cn(
579
+ "text-sm font-semibold uppercase tracking-[0.2em] text-muted-foreground",
580
+ eyebrowClassName
581
+ ),
582
+ children: eyebrow
583
+ }
584
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: eyebrowClassName, children: eyebrow })),
585
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
586
+ "h2",
587
+ {
588
+ className: cn(
589
+ "mt-2 text-3xl font-bold md:text-4xl lg:text-5xl",
590
+ headingClassName
591
+ ),
592
+ children: heading
593
+ }
594
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-2", headingClassName), children: heading })),
595
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
596
+ "p",
597
+ {
598
+ className: cn(
599
+ "mt-4 text-lg text-muted-foreground",
600
+ descriptionClassName
601
+ ),
602
+ children: description
603
+ }
604
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-4", descriptionClassName), children: description })),
605
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8", children: formEngineSetup ? /* @__PURE__ */ jsxRuntime.jsx(
606
+ integration.FormEngine,
607
+ {
608
+ formEngineSetup: {
609
+ ...formEngineSetup,
610
+ formLayoutSettings: {
611
+ ...formEngineSetup.formLayoutSettings,
612
+ formLayout: "standard",
613
+ submitButtonSetup: {
614
+ ...formEngineSetup.formLayoutSettings?.submitButtonSetup,
615
+ submitLabel: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
616
+ buttonIcon,
617
+ buttonText
618
+ ] })
1071
619
  }
1072
- )
620
+ }
1073
621
  },
1074
- field.name
1075
- )) }),
1076
- actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxRuntime.jsxs(
1077
- Pressable,
1078
- {
1079
- componentType: "button",
1080
- type: "submit",
1081
- className: cn("w-full", submitClassName),
1082
- size: "lg",
1083
- asButton: true,
1084
- disabled: form.isSubmitting,
1085
- children: [
1086
- buttonIcon,
1087
- buttonText
1088
- ]
1089
- }
1090
- )
1091
- ]
1092
- }
1093
- )
1094
- ] }) })
1095
- }
1096
- )
1097
- ]
622
+ defaultFields: DEFAULT_FORM_FIELDS,
623
+ defaultStyleRules: DEFAULT_STYLE_RULES
624
+ }
625
+ ) : null })
626
+ ]
627
+ }
628
+ )
629
+ ]
630
+ }
631
+ )
1098
632
  }
1099
633
  );
1100
634
  }