@opensite/ui 1.9.8 → 2.0.0
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.
- package/dist/contact-demo.cjs +106 -406
- package/dist/contact-demo.d.cts +36 -111
- package/dist/contact-demo.d.ts +36 -111
- package/dist/contact-demo.js +108 -405
- package/dist/contact-emergency.cjs +129 -158
- package/dist/contact-emergency.d.cts +23 -12
- package/dist/contact-emergency.d.ts +23 -12
- package/dist/contact-emergency.js +131 -159
- package/dist/contact-event.cjs +106 -147
- package/dist/contact-event.d.cts +36 -66
- package/dist/contact-event.d.ts +36 -66
- package/dist/contact-event.js +108 -148
- package/dist/contact-feedback.cjs +109 -102
- package/dist/contact-feedback.d.cts +36 -63
- package/dist/contact-feedback.d.ts +36 -63
- package/dist/contact-feedback.js +111 -103
- package/dist/contact-fitness.cjs +107 -148
- package/dist/contact-fitness.d.cts +36 -66
- package/dist/contact-fitness.d.ts +36 -66
- package/dist/contact-fitness.js +109 -149
- package/dist/contact-guest.cjs +107 -148
- package/dist/contact-guest.d.cts +35 -65
- package/dist/contact-guest.d.ts +35 -65
- package/dist/contact-guest.js +109 -149
- package/dist/contact-image.cjs +108 -149
- package/dist/contact-image.d.cts +35 -65
- package/dist/contact-image.d.ts +35 -65
- package/dist/contact-image.js +110 -150
- package/dist/contact-insurance.cjs +107 -148
- package/dist/contact-insurance.d.cts +36 -66
- package/dist/contact-insurance.d.ts +36 -66
- package/dist/contact-insurance.js +109 -149
- package/dist/contact-interview.cjs +106 -147
- package/dist/contact-interview.d.cts +20 -12
- package/dist/contact-interview.d.ts +20 -12
- package/dist/contact-interview.js +108 -148
- package/dist/contact-locations.cjs +106 -147
- package/dist/contact-locations.d.cts +21 -13
- package/dist/contact-locations.d.ts +21 -13
- package/dist/contact-locations.js +108 -148
- package/dist/contact-maintenance.cjs +103 -143
- package/dist/contact-maintenance.d.cts +21 -13
- package/dist/contact-maintenance.d.ts +21 -13
- package/dist/contact-maintenance.js +105 -144
- package/dist/contact-map.cjs +103 -143
- package/dist/contact-map.d.cts +20 -12
- package/dist/contact-map.d.ts +20 -12
- package/dist/contact-map.js +105 -144
- package/dist/contact-minimal.cjs +126 -242
- package/dist/contact-minimal.d.cts +36 -70
- package/dist/contact-minimal.d.ts +36 -70
- package/dist/contact-minimal.js +128 -243
- package/dist/contact-moving.cjs +103 -143
- package/dist/contact-moving.d.cts +20 -12
- package/dist/contact-moving.d.ts +20 -12
- package/dist/contact-moving.js +105 -144
- package/dist/contact-multistep.cjs +104 -144
- package/dist/contact-multistep.d.cts +21 -13
- package/dist/contact-multistep.d.ts +21 -13
- package/dist/contact-multistep.js +106 -145
- package/dist/contact-partnership.cjs +103 -143
- package/dist/contact-partnership.d.cts +19 -11
- package/dist/contact-partnership.d.ts +19 -11
- package/dist/contact-partnership.js +105 -144
- package/dist/contact-press.cjs +144 -150
- package/dist/contact-press.d.cts +21 -13
- package/dist/contact-press.d.ts +21 -13
- package/dist/contact-press.js +146 -151
- package/dist/contact-quote.cjs +144 -150
- package/dist/contact-quote.d.cts +19 -11
- package/dist/contact-quote.d.ts +19 -11
- package/dist/contact-quote.js +146 -151
- package/dist/contact-referral.cjs +144 -150
- package/dist/contact-referral.d.cts +20 -12
- package/dist/contact-referral.d.ts +20 -12
- package/dist/contact-referral.js +146 -151
- package/dist/contact-report.cjs +144 -150
- package/dist/contact-report.d.cts +21 -13
- package/dist/contact-report.d.ts +21 -13
- package/dist/contact-report.js +146 -151
- package/dist/contact-reservation.cjs +144 -150
- package/dist/contact-reservation.d.cts +20 -12
- package/dist/contact-reservation.d.ts +20 -12
- package/dist/contact-reservation.js +146 -151
- package/dist/contact-retreat.cjs +144 -150
- package/dist/contact-retreat.d.cts +21 -13
- package/dist/contact-retreat.d.ts +21 -13
- package/dist/contact-retreat.js +146 -151
- package/dist/contact-rsvp.cjs +144 -150
- package/dist/contact-rsvp.d.cts +20 -12
- package/dist/contact-rsvp.d.ts +20 -12
- package/dist/contact-rsvp.js +146 -151
- package/dist/contact-sales.cjs +131 -146
- package/dist/contact-sales.d.cts +34 -65
- package/dist/contact-sales.d.ts +34 -65
- package/dist/contact-sales.js +133 -147
- package/dist/contact-schedule.cjs +144 -150
- package/dist/contact-schedule.d.cts +20 -12
- package/dist/contact-schedule.d.ts +20 -12
- package/dist/contact-schedule.js +146 -151
- package/dist/contact-sponsorship.cjs +144 -150
- package/dist/contact-sponsorship.d.cts +21 -13
- package/dist/contact-sponsorship.d.ts +21 -13
- package/dist/contact-sponsorship.js +146 -151
- package/dist/contact-support.cjs +147 -120
- package/dist/contact-support.d.cts +21 -12
- package/dist/contact-support.d.ts +21 -12
- package/dist/contact-support.js +149 -121
- package/dist/contact-tenant.cjs +144 -150
- package/dist/contact-tenant.d.cts +20 -12
- package/dist/contact-tenant.d.ts +20 -12
- package/dist/contact-tenant.js +146 -151
- package/dist/contact-vendor.cjs +144 -150
- package/dist/contact-vendor.d.cts +20 -12
- package/dist/contact-vendor.d.ts +20 -12
- package/dist/contact-vendor.js +146 -151
- package/dist/contact-volunteer.cjs +144 -150
- package/dist/contact-volunteer.d.cts +20 -12
- package/dist/contact-volunteer.d.ts +20 -12
- package/dist/contact-volunteer.js +146 -151
- package/dist/contact-warranty.cjs +144 -150
- package/dist/contact-warranty.d.cts +20 -12
- package/dist/contact-warranty.d.ts +20 -12
- package/dist/contact-warranty.js +146 -151
- package/dist/contact-wedding.cjs +144 -150
- package/dist/contact-wedding.d.cts +20 -12
- package/dist/contact-wedding.d.ts +20 -12
- package/dist/contact-wedding.js +146 -151
- package/dist/registry.cjs +5791 -5883
- package/dist/registry.js +4527 -4619
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { PageSpeedFormConfig } from '@page-speed/forms/integration';
|
|
2
|
+
import { FormFieldConfig, PageSpeedFormConfig } from '@page-speed/forms/integration';
|
|
3
3
|
import { f as SectionBackground, g as SectionSpacing, t as PatternName } from './community-initiatives-Bi_ClKrO.js';
|
|
4
4
|
import { A as ActionConfig } from './blocks-k17uluAz.js';
|
|
5
5
|
import 'react/jsx-runtime';
|
|
@@ -7,76 +7,51 @@ import 'class-variance-authority';
|
|
|
7
7
|
import './button-variants-lRElsmTc.js';
|
|
8
8
|
import 'class-variance-authority/types';
|
|
9
9
|
|
|
10
|
-
interface ContactMinimalFormValues {
|
|
11
|
-
name: string;
|
|
12
|
-
email: string;
|
|
13
|
-
message: string;
|
|
14
|
-
}
|
|
15
10
|
interface ContactMinimalProps {
|
|
16
|
-
/**
|
|
17
|
-
* Main heading content
|
|
18
|
-
*/
|
|
11
|
+
/** Main heading text */
|
|
19
12
|
heading?: React.ReactNode;
|
|
20
|
-
/**
|
|
21
|
-
* Description text below heading
|
|
22
|
-
*/
|
|
13
|
+
/** Description text below heading */
|
|
23
14
|
description?: React.ReactNode;
|
|
24
|
-
/**
|
|
25
|
-
* Submit button text
|
|
26
|
-
*/
|
|
15
|
+
/** Submit button text */
|
|
27
16
|
buttonText?: string;
|
|
28
|
-
/**
|
|
29
|
-
* Submit button icon (displayed before text)
|
|
30
|
-
*/
|
|
17
|
+
/** Icon to display in submit button */
|
|
31
18
|
buttonIcon?: React.ReactNode;
|
|
32
|
-
/**
|
|
33
|
-
* Array of action configurations for additional buttons
|
|
34
|
-
*/
|
|
19
|
+
/** Array of action configurations for custom buttons */
|
|
35
20
|
actions?: ActionConfig[];
|
|
36
|
-
/**
|
|
37
|
-
* Custom slot for rendering actions (overrides actions array and default submit)
|
|
38
|
-
*/
|
|
21
|
+
/** Custom slot for rendering actions (overrides actions array) */
|
|
39
22
|
actionsSlot?: React.ReactNode;
|
|
40
23
|
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
footer?: React.ReactNode;
|
|
44
|
-
/**
|
|
45
|
-
* Custom slot for footer content (overrides footer prop)
|
|
24
|
+
* Array of form field configurations
|
|
25
|
+
* If not provided, defaults to: first_name, last_name, email, phone, message
|
|
46
26
|
*/
|
|
47
|
-
|
|
27
|
+
formFields?: FormFieldConfig[];
|
|
48
28
|
/**
|
|
49
|
-
*
|
|
29
|
+
* Success message to display after form submission
|
|
30
|
+
* @default "Thank you! Your message has been sent successfully."
|
|
50
31
|
*/
|
|
32
|
+
successMessage?: React.ReactNode;
|
|
33
|
+
/** Additional CSS classes for the section */
|
|
51
34
|
className?: string;
|
|
52
|
-
/**
|
|
53
|
-
* Additional CSS classes for the container
|
|
54
|
-
*/
|
|
35
|
+
/** Additional CSS classes for the container */
|
|
55
36
|
containerClassName?: string;
|
|
56
|
-
/**
|
|
57
|
-
* Additional CSS classes for the header wrapper
|
|
58
|
-
*/
|
|
37
|
+
/** Additional CSS classes for the header */
|
|
59
38
|
headerClassName?: string;
|
|
60
|
-
/**
|
|
61
|
-
* Additional CSS classes for the heading
|
|
62
|
-
*/
|
|
39
|
+
/** Additional CSS classes for the heading */
|
|
63
40
|
headingClassName?: string;
|
|
64
|
-
/**
|
|
65
|
-
* Additional CSS classes for the description
|
|
66
|
-
*/
|
|
41
|
+
/** Additional CSS classes for the description */
|
|
67
42
|
descriptionClassName?: string;
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
|
|
43
|
+
/** Additional CSS classes for the card */
|
|
44
|
+
cardClassName?: string;
|
|
45
|
+
/** Additional CSS classes for the card content */
|
|
46
|
+
cardContentClassName?: string;
|
|
47
|
+
/** Additional CSS classes for the form */
|
|
71
48
|
formClassName?: string;
|
|
72
|
-
/**
|
|
73
|
-
* Additional CSS classes for the submit button
|
|
74
|
-
*/
|
|
49
|
+
/** Additional CSS classes for the submit button */
|
|
75
50
|
submitClassName?: string;
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
51
|
+
/** Additional CSS classes for the success message */
|
|
52
|
+
successMessageClassName?: string;
|
|
53
|
+
/** Additional CSS classes for the error message */
|
|
54
|
+
errorMessageClassName?: string;
|
|
80
55
|
/**
|
|
81
56
|
* Background style for the section
|
|
82
57
|
*/
|
|
@@ -93,35 +68,26 @@ interface ContactMinimalProps {
|
|
|
93
68
|
* Pattern overlay opacity (0-1)
|
|
94
69
|
*/
|
|
95
70
|
patternOpacity?: number;
|
|
96
|
-
/**
|
|
97
|
-
* Form submission configuration
|
|
98
|
-
*/
|
|
71
|
+
/** Form configuration for PageSpeed forms */
|
|
99
72
|
formConfig?: PageSpeedFormConfig;
|
|
100
|
-
/**
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
onSubmit?: (values: ContactMinimalFormValues) => void | Promise<void>;
|
|
104
|
-
/**
|
|
105
|
-
* Success callback after submission
|
|
106
|
-
*/
|
|
73
|
+
/** Custom submit handler */
|
|
74
|
+
onSubmit?: (values: Record<string, any>) => void | Promise<void>;
|
|
75
|
+
/** Success callback */
|
|
107
76
|
onSuccess?: (data: unknown) => void;
|
|
108
|
-
/**
|
|
109
|
-
* Error callback if submission fails
|
|
110
|
-
*/
|
|
77
|
+
/** Error callback */
|
|
111
78
|
onError?: (error: Error) => void;
|
|
112
79
|
}
|
|
113
80
|
/**
|
|
114
|
-
* ContactMinimal -
|
|
115
|
-
* Perfect for minimal designs and quick contact forms.
|
|
81
|
+
* ContactMinimal - Contact form with flexible field configuration
|
|
116
82
|
*
|
|
117
83
|
* @example
|
|
118
84
|
* ```tsx
|
|
119
85
|
* <ContactMinimal
|
|
120
|
-
* heading="
|
|
86
|
+
* heading="Contact Us"
|
|
121
87
|
* formConfig={{ endpoint: "/api/contact", format: "json" }}
|
|
122
88
|
* />
|
|
123
89
|
* ```
|
|
124
90
|
*/
|
|
125
|
-
declare function ContactMinimal({ heading, description, buttonText, buttonIcon, actions, actionsSlot,
|
|
91
|
+
declare function ContactMinimal({ heading, description, buttonText, buttonIcon, actions, actionsSlot, formFields, successMessage, className, containerClassName, headerClassName, headingClassName, descriptionClassName, cardClassName, cardContentClassName, formClassName, submitClassName, successMessageClassName, errorMessageClassName, background, spacing, pattern, patternOpacity, formConfig, onSubmit, onSuccess, onError, }: ContactMinimalProps): React.JSX.Element;
|
|
126
92
|
|
|
127
93
|
export { ContactMinimal, type ContactMinimalProps };
|
package/dist/contact-minimal.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import React__default from 'react';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import React__default, { useMemo } from 'react';
|
|
4
|
+
import { Form } from '@page-speed/forms';
|
|
5
|
+
import { useFileUpload, useContactForm, getColumnSpanClass, DynamicFormField } from '@page-speed/forms/integration';
|
|
6
6
|
import { clsx } from 'clsx';
|
|
7
7
|
import { twMerge } from 'tailwind-merge';
|
|
8
8
|
import { cva } from 'class-variance-authority';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
|
-
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
11
|
-
import { submitPageSpeedForm, PageSpeedFormSubmissionError } from '@page-speed/forms/integration';
|
|
12
10
|
|
|
13
11
|
// components/blocks/contact/contact-minimal.tsx
|
|
14
|
-
var TextInput = TextInput$1;
|
|
15
|
-
var TextArea = TextArea$1;
|
|
16
12
|
function cn(...inputs) {
|
|
17
13
|
return twMerge(clsx(inputs));
|
|
18
14
|
}
|
|
@@ -434,123 +430,25 @@ var Pressable = React.forwardRef(
|
|
|
434
430
|
}
|
|
435
431
|
);
|
|
436
432
|
Pressable.displayName = "Pressable";
|
|
437
|
-
|
|
438
|
-
function DynamicIcon({
|
|
439
|
-
name,
|
|
440
|
-
size = 28,
|
|
441
|
-
color,
|
|
442
|
-
className,
|
|
443
|
-
alt
|
|
444
|
-
}) {
|
|
445
|
-
const [svgContent, setSvgContent] = React.useState(null);
|
|
446
|
-
const [isLoading, setIsLoading] = React.useState(true);
|
|
447
|
-
const [error, setError] = React.useState(null);
|
|
448
|
-
const { url, iconName } = React.useMemo(() => {
|
|
449
|
-
const separator = name.includes("/") ? "/" : ":";
|
|
450
|
-
const [prefix, iconName2] = name.split(separator);
|
|
451
|
-
const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}&key=au382bi7fsh96w9h9xlrnat2jglx`;
|
|
452
|
-
return {
|
|
453
|
-
url: baseUrl,
|
|
454
|
-
iconName: iconName2
|
|
455
|
-
};
|
|
456
|
-
}, [name, size]);
|
|
457
|
-
React.useEffect(() => {
|
|
458
|
-
let isMounted = true;
|
|
459
|
-
const fetchSvg = async () => {
|
|
460
|
-
const cached = svgCache.get(url);
|
|
461
|
-
if (cached) {
|
|
462
|
-
if (isMounted) {
|
|
463
|
-
setSvgContent(cached);
|
|
464
|
-
setIsLoading(false);
|
|
465
|
-
}
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
try {
|
|
469
|
-
setIsLoading(true);
|
|
470
|
-
setError(null);
|
|
471
|
-
const response = await fetch(url);
|
|
472
|
-
if (!response.ok) {
|
|
473
|
-
throw new Error(`Failed to fetch icon: ${response.status}`);
|
|
474
|
-
}
|
|
475
|
-
let svg = await response.text();
|
|
476
|
-
svg = processSvgForCurrentColor(svg);
|
|
477
|
-
svgCache.set(url, svg);
|
|
478
|
-
if (isMounted) {
|
|
479
|
-
setSvgContent(svg);
|
|
480
|
-
setIsLoading(false);
|
|
481
|
-
}
|
|
482
|
-
} catch (err) {
|
|
483
|
-
if (isMounted) {
|
|
484
|
-
setError(err instanceof Error ? err.message : "Failed to load icon");
|
|
485
|
-
setIsLoading(false);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
fetchSvg();
|
|
490
|
-
return () => {
|
|
491
|
-
isMounted = false;
|
|
492
|
-
};
|
|
493
|
-
}, [url]);
|
|
494
|
-
if (isLoading) {
|
|
495
|
-
return /* @__PURE__ */ jsx(
|
|
496
|
-
"span",
|
|
497
|
-
{
|
|
498
|
-
className: cn("inline-block", className),
|
|
499
|
-
style: { width: size, height: size },
|
|
500
|
-
"aria-hidden": "true"
|
|
501
|
-
}
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
if (error || !svgContent) {
|
|
505
|
-
return /* @__PURE__ */ jsx(
|
|
506
|
-
"span",
|
|
507
|
-
{
|
|
508
|
-
className: cn("inline-block", className),
|
|
509
|
-
style: { width: size, height: size },
|
|
510
|
-
role: "img",
|
|
511
|
-
"aria-label": alt || iconName
|
|
512
|
-
}
|
|
513
|
-
);
|
|
514
|
-
}
|
|
433
|
+
function Card({ className, ...props }) {
|
|
515
434
|
return /* @__PURE__ */ jsx(
|
|
516
|
-
"
|
|
435
|
+
"div",
|
|
517
436
|
{
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
role: "img",
|
|
525
|
-
"aria-label": alt || iconName,
|
|
526
|
-
dangerouslySetInnerHTML: { __html: svgContent }
|
|
437
|
+
"data-slot": "card",
|
|
438
|
+
className: cn(
|
|
439
|
+
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
440
|
+
className
|
|
441
|
+
),
|
|
442
|
+
...props
|
|
527
443
|
}
|
|
528
444
|
);
|
|
529
445
|
}
|
|
530
|
-
function
|
|
531
|
-
let processed = svg;
|
|
532
|
-
processed = processed.replace(
|
|
533
|
-
/stroke=["'](#000000|#000|black)["']/gi,
|
|
534
|
-
'stroke="currentColor"'
|
|
535
|
-
);
|
|
536
|
-
processed = processed.replace(
|
|
537
|
-
/fill=["'](#000000|#000|black)["']/gi,
|
|
538
|
-
'fill="currentColor"'
|
|
539
|
-
);
|
|
540
|
-
return processed;
|
|
541
|
-
}
|
|
542
|
-
function Label({
|
|
543
|
-
className,
|
|
544
|
-
...props
|
|
545
|
-
}) {
|
|
446
|
+
function CardContent({ className, ...props }) {
|
|
546
447
|
return /* @__PURE__ */ jsx(
|
|
547
|
-
|
|
448
|
+
"div",
|
|
548
449
|
{
|
|
549
|
-
"data-slot": "
|
|
550
|
-
className: cn(
|
|
551
|
-
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
552
|
-
className
|
|
553
|
-
),
|
|
450
|
+
"data-slot": "card-content",
|
|
451
|
+
className: cn("px-6", className),
|
|
554
452
|
...props
|
|
555
453
|
}
|
|
556
454
|
);
|
|
@@ -930,23 +828,69 @@ var Section = React__default.forwardRef(
|
|
|
930
828
|
}
|
|
931
829
|
);
|
|
932
830
|
Section.displayName = "Section";
|
|
831
|
+
var DEFAULT_FORM_FIELDS = [
|
|
832
|
+
{
|
|
833
|
+
name: "first_name",
|
|
834
|
+
type: "text",
|
|
835
|
+
label: "First Name",
|
|
836
|
+
placeholder: "John",
|
|
837
|
+
required: true,
|
|
838
|
+
columnSpan: 6
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
name: "last_name",
|
|
842
|
+
type: "text",
|
|
843
|
+
label: "Last Name",
|
|
844
|
+
placeholder: "Doe",
|
|
845
|
+
required: true,
|
|
846
|
+
columnSpan: 6
|
|
847
|
+
},
|
|
848
|
+
{
|
|
849
|
+
name: "email",
|
|
850
|
+
type: "email",
|
|
851
|
+
label: "Email",
|
|
852
|
+
placeholder: "john@example.com",
|
|
853
|
+
required: true,
|
|
854
|
+
columnSpan: 12
|
|
855
|
+
},
|
|
856
|
+
{
|
|
857
|
+
name: "phone",
|
|
858
|
+
type: "tel",
|
|
859
|
+
label: "Phone",
|
|
860
|
+
placeholder: "+1 (555) 000-0000",
|
|
861
|
+
required: true,
|
|
862
|
+
columnSpan: 12
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
name: "message",
|
|
866
|
+
type: "textarea",
|
|
867
|
+
label: "Message",
|
|
868
|
+
placeholder: "Your message...",
|
|
869
|
+
required: true,
|
|
870
|
+
rows: 4,
|
|
871
|
+
columnSpan: 12
|
|
872
|
+
}
|
|
873
|
+
];
|
|
933
874
|
function ContactMinimal({
|
|
934
875
|
heading,
|
|
935
876
|
description,
|
|
936
|
-
buttonText,
|
|
937
|
-
buttonIcon
|
|
877
|
+
buttonText = "Submit",
|
|
878
|
+
buttonIcon,
|
|
938
879
|
actions,
|
|
939
880
|
actionsSlot,
|
|
940
|
-
|
|
941
|
-
|
|
881
|
+
formFields = DEFAULT_FORM_FIELDS,
|
|
882
|
+
successMessage = "Thank you! Your message has been sent successfully.",
|
|
942
883
|
className,
|
|
943
|
-
containerClassName,
|
|
884
|
+
containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
|
|
944
885
|
headerClassName,
|
|
945
886
|
headingClassName,
|
|
946
887
|
descriptionClassName,
|
|
888
|
+
cardClassName,
|
|
889
|
+
cardContentClassName,
|
|
947
890
|
formClassName,
|
|
948
891
|
submitClassName,
|
|
949
|
-
|
|
892
|
+
successMessageClassName,
|
|
893
|
+
errorMessageClassName,
|
|
950
894
|
background = "white",
|
|
951
895
|
spacing = "xl",
|
|
952
896
|
pattern,
|
|
@@ -956,52 +900,27 @@ function ContactMinimal({
|
|
|
956
900
|
onSuccess,
|
|
957
901
|
onError
|
|
958
902
|
}) {
|
|
959
|
-
const
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
903
|
+
const {
|
|
904
|
+
uploadTokens,
|
|
905
|
+
uploadProgress,
|
|
906
|
+
isUploading,
|
|
907
|
+
uploadFiles,
|
|
908
|
+
removeFile,
|
|
909
|
+
resetUpload
|
|
910
|
+
} = useFileUpload({ onError });
|
|
911
|
+
const { form, submissionError, formMethod, resetSubmissionState } = useContactForm({
|
|
912
|
+
formFields,
|
|
913
|
+
formConfig,
|
|
914
|
+
onSubmit,
|
|
915
|
+
onSuccess: (data) => {
|
|
916
|
+
resetUpload();
|
|
917
|
+
onSuccess?.(data);
|
|
964
918
|
},
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
if (!value) return "Email is required";
|
|
969
|
-
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
|
|
970
|
-
return "Please enter a valid email address";
|
|
971
|
-
return void 0;
|
|
972
|
-
},
|
|
973
|
-
message: (value) => !value ? "Message is required" : void 0
|
|
974
|
-
},
|
|
975
|
-
onSubmit: async (values, helpers) => {
|
|
976
|
-
const shouldAutoSubmit = Boolean(formConfig?.endpoint);
|
|
977
|
-
if (!shouldAutoSubmit && !onSubmit) {
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
980
|
-
try {
|
|
981
|
-
let result;
|
|
982
|
-
if (shouldAutoSubmit) {
|
|
983
|
-
result = await submitPageSpeedForm(values, formConfig);
|
|
984
|
-
}
|
|
985
|
-
if (onSubmit) {
|
|
986
|
-
await onSubmit(values);
|
|
987
|
-
}
|
|
988
|
-
if (shouldAutoSubmit || onSubmit) {
|
|
989
|
-
if (formConfig?.resetOnSuccess !== false) {
|
|
990
|
-
helpers.resetForm();
|
|
991
|
-
}
|
|
992
|
-
onSuccess?.(result);
|
|
993
|
-
}
|
|
994
|
-
} catch (error) {
|
|
995
|
-
if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
|
|
996
|
-
helpers.setErrors(error.formErrors);
|
|
997
|
-
}
|
|
998
|
-
onError?.(error);
|
|
999
|
-
throw error;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
919
|
+
onError,
|
|
920
|
+
resetOnSuccess: formConfig?.resetOnSuccess !== false,
|
|
921
|
+
uploadTokens
|
|
1002
922
|
});
|
|
1003
|
-
const
|
|
1004
|
-
const actionsContent = React.useMemo(() => {
|
|
923
|
+
const actionsContent = useMemo(() => {
|
|
1005
924
|
if (actionsSlot) return actionsSlot;
|
|
1006
925
|
if (actions && actions.length > 0) {
|
|
1007
926
|
return actions.map((action, index) => {
|
|
@@ -1031,31 +950,6 @@ function ContactMinimal({
|
|
|
1031
950
|
}
|
|
1032
951
|
return null;
|
|
1033
952
|
}, [actionsSlot, actions]);
|
|
1034
|
-
const footerContent = React.useMemo(() => {
|
|
1035
|
-
if (footerSlot) return footerSlot;
|
|
1036
|
-
if (footer) {
|
|
1037
|
-
return typeof footer === "string" ? /* @__PURE__ */ jsx(
|
|
1038
|
-
"p",
|
|
1039
|
-
{
|
|
1040
|
-
className: cn(
|
|
1041
|
-
"mt-6 text-center text-sm text-balance",
|
|
1042
|
-
footerClassName
|
|
1043
|
-
),
|
|
1044
|
-
children: footer
|
|
1045
|
-
}
|
|
1046
|
-
) : /* @__PURE__ */ jsx(
|
|
1047
|
-
"div",
|
|
1048
|
-
{
|
|
1049
|
-
className: cn(
|
|
1050
|
-
"mt-6 text-center text-sm text-balance",
|
|
1051
|
-
footerClassName
|
|
1052
|
-
),
|
|
1053
|
-
children: footer
|
|
1054
|
-
}
|
|
1055
|
-
);
|
|
1056
|
-
}
|
|
1057
|
-
return null;
|
|
1058
|
-
}, [footerSlot, footer, footerClassName]);
|
|
1059
953
|
return /* @__PURE__ */ jsx(
|
|
1060
954
|
Section,
|
|
1061
955
|
{
|
|
@@ -1064,13 +958,14 @@ function ContactMinimal({
|
|
|
1064
958
|
pattern,
|
|
1065
959
|
patternOpacity,
|
|
1066
960
|
className: cn("py-12", className),
|
|
1067
|
-
|
|
961
|
+
containerClassName,
|
|
962
|
+
children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
|
|
1068
963
|
/* @__PURE__ */ jsxs("div", { className: cn("mb-10 text-center", headerClassName), children: [
|
|
1069
964
|
heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
|
|
1070
965
|
"h2",
|
|
1071
966
|
{
|
|
1072
967
|
className: cn(
|
|
1073
|
-
"mb-3 text-3xl font-bold tracking-tight",
|
|
968
|
+
"mb-3 text-3xl font-bold tracking-tight text-balance",
|
|
1074
969
|
headingClassName
|
|
1075
970
|
),
|
|
1076
971
|
children: heading
|
|
@@ -1080,68 +975,59 @@ function ContactMinimal({
|
|
|
1080
975
|
"p",
|
|
1081
976
|
{
|
|
1082
977
|
className: cn(
|
|
1083
|
-
"leading-relaxed text-
|
|
978
|
+
"leading-relaxed text-balance",
|
|
1084
979
|
descriptionClassName
|
|
1085
980
|
),
|
|
1086
981
|
children: description
|
|
1087
982
|
}
|
|
1088
983
|
) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: description }))
|
|
1089
984
|
] }),
|
|
1090
|
-
/* @__PURE__ */ jsxs(
|
|
985
|
+
/* @__PURE__ */ jsx(Card, { className: cn("mx-auto max-w-xl", cardClassName), children: /* @__PURE__ */ jsx(CardContent, { className: cn("p-6 lg:p-8", cardContentClassName), children: /* @__PURE__ */ jsxs(
|
|
1091
986
|
Form,
|
|
1092
987
|
{
|
|
1093
988
|
form,
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
989
|
+
notificationConfig: {
|
|
990
|
+
submissionError,
|
|
991
|
+
successMessage
|
|
992
|
+
},
|
|
993
|
+
styleConfig: {
|
|
994
|
+
formClassName: cn("space-y-4", formClassName),
|
|
995
|
+
successMessageClassName,
|
|
996
|
+
errorMessageClassName
|
|
997
|
+
},
|
|
998
|
+
formConfig: {
|
|
999
|
+
endpoint: formConfig?.endpoint,
|
|
1000
|
+
method: formMethod,
|
|
1001
|
+
submissionConfig: formConfig?.submissionConfig
|
|
1002
|
+
},
|
|
1003
|
+
onNewSubmission: () => {
|
|
1004
|
+
resetUpload();
|
|
1005
|
+
resetSubmissionState();
|
|
1006
|
+
},
|
|
1097
1007
|
children: [
|
|
1098
|
-
/* @__PURE__ */ jsx(
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
{
|
|
1116
|
-
...field,
|
|
1117
|
-
id: "email",
|
|
1118
|
-
type: "email",
|
|
1119
|
-
placeholder: "your@email.com",
|
|
1120
|
-
error: meta.touched && !!meta.error,
|
|
1121
|
-
"aria-label": "Email"
|
|
1122
|
-
}
|
|
1123
|
-
)
|
|
1124
|
-
] }) }),
|
|
1125
|
-
/* @__PURE__ */ jsx(Field, { name: "message", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1126
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: "message", children: "Message" }),
|
|
1127
|
-
/* @__PURE__ */ jsx(
|
|
1128
|
-
TextArea,
|
|
1129
|
-
{
|
|
1130
|
-
...field,
|
|
1131
|
-
id: "message",
|
|
1132
|
-
placeholder: "Tell us what's on your mind...",
|
|
1133
|
-
rows: 4,
|
|
1134
|
-
error: meta.touched && !!meta.error,
|
|
1135
|
-
"aria-label": "Message"
|
|
1136
|
-
}
|
|
1137
|
-
)
|
|
1138
|
-
] }) }),
|
|
1008
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-12 gap-6", children: formFields.map((field) => /* @__PURE__ */ jsx(
|
|
1009
|
+
"div",
|
|
1010
|
+
{
|
|
1011
|
+
className: getColumnSpanClass(field.columnSpan),
|
|
1012
|
+
children: /* @__PURE__ */ jsx(
|
|
1013
|
+
DynamicFormField,
|
|
1014
|
+
{
|
|
1015
|
+
field,
|
|
1016
|
+
uploadProgress,
|
|
1017
|
+
onFileUpload: uploadFiles,
|
|
1018
|
+
onFileRemove: removeFile,
|
|
1019
|
+
isUploading
|
|
1020
|
+
}
|
|
1021
|
+
)
|
|
1022
|
+
},
|
|
1023
|
+
field.name
|
|
1024
|
+
)) }),
|
|
1139
1025
|
actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxs(
|
|
1140
1026
|
Pressable,
|
|
1141
1027
|
{
|
|
1142
1028
|
componentType: "button",
|
|
1143
1029
|
type: "submit",
|
|
1144
|
-
className: cn("w-full
|
|
1030
|
+
className: cn("w-full", submitClassName),
|
|
1145
1031
|
size: "lg",
|
|
1146
1032
|
asButton: true,
|
|
1147
1033
|
disabled: form.isSubmitting,
|
|
@@ -1153,8 +1039,7 @@ function ContactMinimal({
|
|
|
1153
1039
|
)
|
|
1154
1040
|
]
|
|
1155
1041
|
}
|
|
1156
|
-
)
|
|
1157
|
-
footerContent
|
|
1042
|
+
) }) })
|
|
1158
1043
|
] })
|
|
1159
1044
|
}
|
|
1160
1045
|
);
|