@opensite/ui 1.7.5 → 1.7.6
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-dark.cjs +503 -124
- package/dist/contact-dark.d.cts +28 -9
- package/dist/contact-dark.d.ts +28 -9
- package/dist/contact-dark.js +505 -126
- package/dist/contact-faq.cjs +482 -104
- package/dist/contact-faq.d.cts +27 -17
- package/dist/contact-faq.d.ts +27 -17
- package/dist/contact-faq.js +484 -106
- package/dist/contact-photography.cjs +485 -116
- package/dist/contact-photography.d.cts +22 -9
- package/dist/contact-photography.d.ts +22 -9
- package/dist/contact-photography.js +487 -118
- package/dist/form-field-types-BYdJNOsW.d.cts +92 -0
- package/dist/form-field-types-BYdJNOsW.d.ts +92 -0
- package/dist/registry.cjs +2397 -2037
- package/dist/registry.js +1141 -781
- package/package.json +6 -1
package/dist/contact-dark.cjs
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var forms = require('@page-speed/forms');
|
|
6
|
-
var inputs = require('@page-speed/forms/inputs');
|
|
7
6
|
var clsx = require('clsx');
|
|
8
7
|
var tailwindMerge = require('tailwind-merge');
|
|
9
8
|
var classVarianceAuthority = require('class-variance-authority');
|
|
10
9
|
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
var inputs = require('@page-speed/forms/inputs');
|
|
11
11
|
var LabelPrimitive = require('@radix-ui/react-label');
|
|
12
12
|
var integration = require('@page-speed/forms/integration');
|
|
13
13
|
|
|
@@ -588,6 +588,389 @@ function Label({
|
|
|
588
588
|
}
|
|
589
589
|
);
|
|
590
590
|
}
|
|
591
|
+
function DynamicFormField({
|
|
592
|
+
field,
|
|
593
|
+
className,
|
|
594
|
+
uploadProgress = {},
|
|
595
|
+
onFileUpload,
|
|
596
|
+
onFileRemove,
|
|
597
|
+
isUploading = false
|
|
598
|
+
}) {
|
|
599
|
+
const fieldId = `field-${field.name}`;
|
|
600
|
+
return /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: field.name, children: ({ field: formField, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2", className), children: [
|
|
601
|
+
field.type !== "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
|
|
602
|
+
field.label,
|
|
603
|
+
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-1", children: "*" })
|
|
604
|
+
] }),
|
|
605
|
+
(field.type === "text" || field.type === "email" || field.type === "tel" || field.type === "search" || field.type === "password" || field.type === "url") && /* @__PURE__ */ jsxRuntime.jsx(
|
|
606
|
+
inputs.TextInput,
|
|
607
|
+
{
|
|
608
|
+
...formField,
|
|
609
|
+
id: fieldId,
|
|
610
|
+
type: field.type,
|
|
611
|
+
placeholder: field.placeholder,
|
|
612
|
+
error: meta.touched && !!meta.error,
|
|
613
|
+
disabled: field.disabled,
|
|
614
|
+
"aria-label": field.label
|
|
615
|
+
}
|
|
616
|
+
),
|
|
617
|
+
field.type === "number" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
618
|
+
inputs.TextInput,
|
|
619
|
+
{
|
|
620
|
+
...formField,
|
|
621
|
+
id: fieldId,
|
|
622
|
+
type: "text",
|
|
623
|
+
placeholder: field.placeholder,
|
|
624
|
+
error: meta.touched && !!meta.error,
|
|
625
|
+
disabled: field.disabled,
|
|
626
|
+
"aria-label": field.label
|
|
627
|
+
}
|
|
628
|
+
),
|
|
629
|
+
field.type === "textarea" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
630
|
+
inputs.TextArea,
|
|
631
|
+
{
|
|
632
|
+
...formField,
|
|
633
|
+
id: fieldId,
|
|
634
|
+
placeholder: field.placeholder,
|
|
635
|
+
rows: field.rows || 4,
|
|
636
|
+
error: meta.touched && !!meta.error,
|
|
637
|
+
disabled: field.disabled,
|
|
638
|
+
"aria-label": field.label
|
|
639
|
+
}
|
|
640
|
+
),
|
|
641
|
+
field.type === "select" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
|
|
642
|
+
inputs.Select,
|
|
643
|
+
{
|
|
644
|
+
...formField,
|
|
645
|
+
id: fieldId,
|
|
646
|
+
options: field.options,
|
|
647
|
+
placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
|
|
648
|
+
error: meta.touched && !!meta.error,
|
|
649
|
+
disabled: field.disabled,
|
|
650
|
+
"aria-label": field.label
|
|
651
|
+
}
|
|
652
|
+
),
|
|
653
|
+
field.type === "multi-select" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
|
|
654
|
+
inputs.Select,
|
|
655
|
+
{
|
|
656
|
+
...formField,
|
|
657
|
+
id: fieldId,
|
|
658
|
+
options: field.options,
|
|
659
|
+
placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
|
|
660
|
+
error: meta.touched && !!meta.error,
|
|
661
|
+
disabled: field.disabled,
|
|
662
|
+
"aria-label": field.label,
|
|
663
|
+
multiple: true
|
|
664
|
+
}
|
|
665
|
+
),
|
|
666
|
+
field.type === "radio" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
|
|
667
|
+
inputs.Radio,
|
|
668
|
+
{
|
|
669
|
+
...formField,
|
|
670
|
+
id: fieldId,
|
|
671
|
+
options: field.options,
|
|
672
|
+
disabled: field.disabled,
|
|
673
|
+
layout: field.layout || "stacked",
|
|
674
|
+
error: meta.touched && !!meta.error,
|
|
675
|
+
"aria-label": field.label
|
|
676
|
+
}
|
|
677
|
+
),
|
|
678
|
+
field.type === "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-2", children: [
|
|
679
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
680
|
+
inputs.Checkbox,
|
|
681
|
+
{
|
|
682
|
+
...formField,
|
|
683
|
+
id: fieldId,
|
|
684
|
+
value: formField.value === true || formField.value === "true",
|
|
685
|
+
onChange: (checked) => formField.onChange(checked),
|
|
686
|
+
disabled: field.disabled,
|
|
687
|
+
error: meta.touched && !!meta.error,
|
|
688
|
+
"aria-label": field.label
|
|
689
|
+
}
|
|
690
|
+
),
|
|
691
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
692
|
+
Label,
|
|
693
|
+
{
|
|
694
|
+
htmlFor: fieldId,
|
|
695
|
+
className: "font-normal cursor-pointer leading-relaxed",
|
|
696
|
+
children: [
|
|
697
|
+
field.label,
|
|
698
|
+
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-1", children: "*" })
|
|
699
|
+
]
|
|
700
|
+
}
|
|
701
|
+
)
|
|
702
|
+
] }),
|
|
703
|
+
field.type === "checkbox-group" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
|
|
704
|
+
inputs.CheckboxGroup,
|
|
705
|
+
{
|
|
706
|
+
...formField,
|
|
707
|
+
id: fieldId,
|
|
708
|
+
options: field.options,
|
|
709
|
+
disabled: field.disabled,
|
|
710
|
+
layout: field.layout || "stacked",
|
|
711
|
+
error: meta.touched && !!meta.error,
|
|
712
|
+
"aria-label": field.label
|
|
713
|
+
}
|
|
714
|
+
),
|
|
715
|
+
(field.type === "date-picker" || field.type === "date") && /* @__PURE__ */ jsxRuntime.jsx(
|
|
716
|
+
inputs.DatePicker,
|
|
717
|
+
{
|
|
718
|
+
...formField,
|
|
719
|
+
id: fieldId,
|
|
720
|
+
placeholder: field.placeholder,
|
|
721
|
+
error: meta.touched && !!meta.error,
|
|
722
|
+
disabled: field.disabled,
|
|
723
|
+
"aria-label": field.label
|
|
724
|
+
}
|
|
725
|
+
),
|
|
726
|
+
field.type === "date-range" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
727
|
+
inputs.DateRangePicker,
|
|
728
|
+
{
|
|
729
|
+
...formField,
|
|
730
|
+
id: fieldId,
|
|
731
|
+
error: meta.touched && !!meta.error,
|
|
732
|
+
disabled: field.disabled,
|
|
733
|
+
"aria-label": field.label
|
|
734
|
+
}
|
|
735
|
+
),
|
|
736
|
+
field.type === "time" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
737
|
+
inputs.TimePicker,
|
|
738
|
+
{
|
|
739
|
+
...formField,
|
|
740
|
+
id: fieldId,
|
|
741
|
+
placeholder: field.placeholder,
|
|
742
|
+
error: meta.touched && !!meta.error,
|
|
743
|
+
disabled: field.disabled,
|
|
744
|
+
"aria-label": field.label
|
|
745
|
+
}
|
|
746
|
+
),
|
|
747
|
+
field.type === "file" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
748
|
+
inputs.FileInput,
|
|
749
|
+
{
|
|
750
|
+
...formField,
|
|
751
|
+
id: fieldId,
|
|
752
|
+
accept: field.accept,
|
|
753
|
+
maxSize: field.maxSize || 5 * 1024 * 1024,
|
|
754
|
+
maxFiles: field.maxFiles || 1,
|
|
755
|
+
multiple: field.multiple || false,
|
|
756
|
+
placeholder: field.placeholder || "Choose file(s)...",
|
|
757
|
+
error: meta.touched && !!meta.error,
|
|
758
|
+
disabled: field.disabled || isUploading,
|
|
759
|
+
showProgress: true,
|
|
760
|
+
uploadProgress,
|
|
761
|
+
onChange: (files) => {
|
|
762
|
+
formField.onChange(files);
|
|
763
|
+
if (files.length > 0 && onFileUpload) {
|
|
764
|
+
onFileUpload(files);
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
onFileRemove,
|
|
768
|
+
"aria-label": field.label
|
|
769
|
+
}
|
|
770
|
+
),
|
|
771
|
+
field.type === "rich-text" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
772
|
+
inputs.RichTextEditor,
|
|
773
|
+
{
|
|
774
|
+
...formField,
|
|
775
|
+
id: fieldId,
|
|
776
|
+
placeholder: field.placeholder,
|
|
777
|
+
error: meta.touched && !!meta.error,
|
|
778
|
+
disabled: field.disabled,
|
|
779
|
+
"aria-label": field.label
|
|
780
|
+
}
|
|
781
|
+
),
|
|
782
|
+
meta.touched && meta.error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: meta.error })
|
|
783
|
+
] }) });
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// lib/form-field-types.ts
|
|
787
|
+
function generateInitialValues(fields) {
|
|
788
|
+
return fields.reduce(
|
|
789
|
+
(acc, field) => {
|
|
790
|
+
if (field.type === "checkbox") {
|
|
791
|
+
acc[field.name] = false;
|
|
792
|
+
} else if (field.type === "checkbox-group" || field.type === "multi-select") {
|
|
793
|
+
acc[field.name] = [];
|
|
794
|
+
} else if (field.type === "file") {
|
|
795
|
+
acc[field.name] = [];
|
|
796
|
+
} else if (field.type === "date-range") {
|
|
797
|
+
acc[field.name] = { start: null, end: null };
|
|
798
|
+
} else {
|
|
799
|
+
acc[field.name] = "";
|
|
800
|
+
}
|
|
801
|
+
return acc;
|
|
802
|
+
},
|
|
803
|
+
{}
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
function generateValidationSchema(fields) {
|
|
807
|
+
return fields.reduce(
|
|
808
|
+
(acc, field) => {
|
|
809
|
+
acc[field.name] = (value, allValues) => {
|
|
810
|
+
if (field.required) {
|
|
811
|
+
if (!value || typeof value === "string" && !value.trim()) {
|
|
812
|
+
return `${field.label} is required`;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (field.type === "email" && value) {
|
|
816
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
|
|
817
|
+
return "Please enter a valid email address";
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if (field.type === "url" && value) {
|
|
821
|
+
try {
|
|
822
|
+
new URL(value);
|
|
823
|
+
} catch {
|
|
824
|
+
return "Please enter a valid URL";
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (field.validator) {
|
|
828
|
+
return field.validator(value, allValues);
|
|
829
|
+
}
|
|
830
|
+
return void 0;
|
|
831
|
+
};
|
|
832
|
+
return acc;
|
|
833
|
+
},
|
|
834
|
+
{}
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
function getColumnSpanClass(span) {
|
|
838
|
+
if (!span || span === 12) return "col-span-12";
|
|
839
|
+
return `col-span-12 sm:col-span-${Math.min(span, 12)}`;
|
|
840
|
+
}
|
|
841
|
+
function useFileUpload(options) {
|
|
842
|
+
const [uploadTokens, setUploadTokens] = React.useState([]);
|
|
843
|
+
const [uploadProgress, setUploadProgress] = React.useState({});
|
|
844
|
+
const [isUploading, setIsUploading] = React.useState(false);
|
|
845
|
+
const endpoint = options?.endpoint || "https://api.dashtrack.com/contacts/_/contact_form_uploads";
|
|
846
|
+
const uploadFiles = React.useCallback(
|
|
847
|
+
async (files) => {
|
|
848
|
+
if (files.length === 0) return;
|
|
849
|
+
setIsUploading(true);
|
|
850
|
+
try {
|
|
851
|
+
const tokens = [];
|
|
852
|
+
for (const file of files) {
|
|
853
|
+
const formData = new FormData();
|
|
854
|
+
formData.append("contact_form_upload[file_upload]", file);
|
|
855
|
+
formData.append("contact_form_upload[title]", file.name);
|
|
856
|
+
formData.append("contact_form_upload[file_name]", file.name);
|
|
857
|
+
formData.append("contact_form_upload[file_size]", String(file.size));
|
|
858
|
+
const response = await fetch(endpoint, {
|
|
859
|
+
method: "POST",
|
|
860
|
+
body: formData
|
|
861
|
+
});
|
|
862
|
+
if (!response.ok) {
|
|
863
|
+
throw new Error(`Upload failed: ${response.statusText}`);
|
|
864
|
+
}
|
|
865
|
+
const data = await response.json();
|
|
866
|
+
if (data.contact_form_upload?.token) {
|
|
867
|
+
tokens.push(`upload_${data.contact_form_upload.token}`);
|
|
868
|
+
}
|
|
869
|
+
setUploadProgress((prev) => ({
|
|
870
|
+
...prev,
|
|
871
|
+
[file.name]: 100
|
|
872
|
+
}));
|
|
873
|
+
}
|
|
874
|
+
setUploadTokens(tokens);
|
|
875
|
+
} catch (error) {
|
|
876
|
+
console.error("File upload error:", error);
|
|
877
|
+
options?.onError?.(error);
|
|
878
|
+
} finally {
|
|
879
|
+
setIsUploading(false);
|
|
880
|
+
}
|
|
881
|
+
},
|
|
882
|
+
[endpoint, options]
|
|
883
|
+
);
|
|
884
|
+
const removeFile = React.useCallback((file, index) => {
|
|
885
|
+
setUploadTokens((prev) => prev.filter((_, i) => i !== index));
|
|
886
|
+
setUploadProgress((prev) => {
|
|
887
|
+
const newProgress = { ...prev };
|
|
888
|
+
delete newProgress[file.name];
|
|
889
|
+
return newProgress;
|
|
890
|
+
});
|
|
891
|
+
}, []);
|
|
892
|
+
const resetUpload = React.useCallback(() => {
|
|
893
|
+
setUploadTokens([]);
|
|
894
|
+
setUploadProgress({});
|
|
895
|
+
}, []);
|
|
896
|
+
return {
|
|
897
|
+
uploadTokens,
|
|
898
|
+
uploadProgress,
|
|
899
|
+
isUploading,
|
|
900
|
+
uploadFiles,
|
|
901
|
+
removeFile,
|
|
902
|
+
resetUpload
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
function useContactForm(options) {
|
|
906
|
+
const {
|
|
907
|
+
formFields,
|
|
908
|
+
formConfig,
|
|
909
|
+
onSubmit,
|
|
910
|
+
onSuccess,
|
|
911
|
+
onError,
|
|
912
|
+
resetOnSuccess = true,
|
|
913
|
+
uploadTokens = []
|
|
914
|
+
} = options;
|
|
915
|
+
const [isSubmitted, setIsSubmitted] = React.useState(false);
|
|
916
|
+
const [submissionError, setSubmissionError] = React.useState(null);
|
|
917
|
+
const form = forms.useForm({
|
|
918
|
+
initialValues: React.useMemo(
|
|
919
|
+
() => generateInitialValues(formFields),
|
|
920
|
+
[formFields]
|
|
921
|
+
),
|
|
922
|
+
validationSchema: React.useMemo(
|
|
923
|
+
() => generateValidationSchema(formFields),
|
|
924
|
+
[formFields]
|
|
925
|
+
),
|
|
926
|
+
onSubmit: async (values, helpers) => {
|
|
927
|
+
setSubmissionError(null);
|
|
928
|
+
const shouldAutoSubmit = Boolean(formConfig?.endpoint);
|
|
929
|
+
if (!shouldAutoSubmit && !onSubmit) {
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
try {
|
|
933
|
+
let result;
|
|
934
|
+
const submissionValues = {
|
|
935
|
+
...values,
|
|
936
|
+
...uploadTokens.length > 0 && {
|
|
937
|
+
contact_form_upload_tokens: uploadTokens
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
if (shouldAutoSubmit) {
|
|
941
|
+
result = await submitPageSpeedForm(submissionValues, formConfig);
|
|
942
|
+
}
|
|
943
|
+
if (onSubmit) {
|
|
944
|
+
await onSubmit(submissionValues);
|
|
945
|
+
}
|
|
946
|
+
if (shouldAutoSubmit || onSubmit) {
|
|
947
|
+
setIsSubmitted(true);
|
|
948
|
+
if (resetOnSuccess) {
|
|
949
|
+
helpers.resetForm();
|
|
950
|
+
}
|
|
951
|
+
onSuccess?.(result);
|
|
952
|
+
setTimeout(() => setIsSubmitted(false), 5e3);
|
|
953
|
+
}
|
|
954
|
+
} catch (error) {
|
|
955
|
+
if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
|
|
956
|
+
helpers.setErrors(error.formErrors);
|
|
957
|
+
}
|
|
958
|
+
const errorMessage = error instanceof Error ? error.message : "Form submission failed";
|
|
959
|
+
setSubmissionError(errorMessage);
|
|
960
|
+
onError?.(error);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
|
|
965
|
+
return {
|
|
966
|
+
form,
|
|
967
|
+
isSubmitted,
|
|
968
|
+
submissionError,
|
|
969
|
+
formMethod
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// lib/forms.ts
|
|
591
974
|
var PageSpeedFormSubmissionError = class extends Error {
|
|
592
975
|
constructor(message, options = {}) {
|
|
593
976
|
super(message);
|
|
@@ -1078,12 +1461,47 @@ var Section = React__namespace.default.forwardRef(
|
|
|
1078
1461
|
}
|
|
1079
1462
|
);
|
|
1080
1463
|
Section.displayName = "Section";
|
|
1464
|
+
var DEFAULT_FORM_FIELDS = [
|
|
1465
|
+
{
|
|
1466
|
+
name: "firstName",
|
|
1467
|
+
type: "text",
|
|
1468
|
+
label: "First Name",
|
|
1469
|
+
placeholder: "First name",
|
|
1470
|
+
required: true,
|
|
1471
|
+
columnSpan: 6
|
|
1472
|
+
},
|
|
1473
|
+
{
|
|
1474
|
+
name: "lastName",
|
|
1475
|
+
type: "text",
|
|
1476
|
+
label: "Last Name",
|
|
1477
|
+
placeholder: "Last name",
|
|
1478
|
+
required: true,
|
|
1479
|
+
columnSpan: 6
|
|
1480
|
+
},
|
|
1481
|
+
{
|
|
1482
|
+
name: "email",
|
|
1483
|
+
type: "email",
|
|
1484
|
+
label: "Email Address",
|
|
1485
|
+
placeholder: "your@email.com",
|
|
1486
|
+
required: true,
|
|
1487
|
+
columnSpan: 12
|
|
1488
|
+
},
|
|
1489
|
+
{
|
|
1490
|
+
name: "message",
|
|
1491
|
+
type: "textarea",
|
|
1492
|
+
label: "Message",
|
|
1493
|
+
placeholder: "Your message...",
|
|
1494
|
+
required: true,
|
|
1495
|
+
rows: 4,
|
|
1496
|
+
columnSpan: 12
|
|
1497
|
+
}
|
|
1498
|
+
];
|
|
1081
1499
|
function ContactDark({
|
|
1082
1500
|
heading,
|
|
1083
1501
|
description,
|
|
1084
1502
|
contactHeading = "Contact Information",
|
|
1085
1503
|
contactDescription = "Fill up the form and our team will get back to you within 24 hours.",
|
|
1086
|
-
buttonText,
|
|
1504
|
+
buttonText = "Submit",
|
|
1087
1505
|
buttonIcon,
|
|
1088
1506
|
actions,
|
|
1089
1507
|
actionsSlot,
|
|
@@ -1091,6 +1509,9 @@ function ContactDark({
|
|
|
1091
1509
|
contactOptionsSlot,
|
|
1092
1510
|
socialLinks,
|
|
1093
1511
|
socialLinksSlot,
|
|
1512
|
+
formFields = DEFAULT_FORM_FIELDS,
|
|
1513
|
+
successMessage = "Thank you! Your message has been sent successfully.",
|
|
1514
|
+
errorMessage = "There was an error sending your message. Please try again.",
|
|
1094
1515
|
className,
|
|
1095
1516
|
headerClassName,
|
|
1096
1517
|
headingClassName,
|
|
@@ -1102,6 +1523,8 @@ function ContactDark({
|
|
|
1102
1523
|
infoPanelClassName,
|
|
1103
1524
|
contactOptionsClassName,
|
|
1104
1525
|
socialLinksClassName,
|
|
1526
|
+
successMessageClassName,
|
|
1527
|
+
errorMessageClassName,
|
|
1105
1528
|
background,
|
|
1106
1529
|
spacing = "py-8 md:py-32",
|
|
1107
1530
|
containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
|
|
@@ -1112,53 +1535,26 @@ function ContactDark({
|
|
|
1112
1535
|
onSuccess,
|
|
1113
1536
|
onError
|
|
1114
1537
|
}) {
|
|
1115
|
-
const
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
},
|
|
1131
|
-
message: (value) => !value ? "Message is required" : void 0
|
|
1538
|
+
const {
|
|
1539
|
+
uploadTokens,
|
|
1540
|
+
uploadProgress,
|
|
1541
|
+
isUploading,
|
|
1542
|
+
uploadFiles,
|
|
1543
|
+
removeFile,
|
|
1544
|
+
resetUpload
|
|
1545
|
+
} = useFileUpload({ onError });
|
|
1546
|
+
const { form, isSubmitted, submissionError, formMethod } = useContactForm({
|
|
1547
|
+
formFields,
|
|
1548
|
+
formConfig,
|
|
1549
|
+
onSubmit,
|
|
1550
|
+
onSuccess: (data) => {
|
|
1551
|
+
resetUpload();
|
|
1552
|
+
onSuccess?.(data);
|
|
1132
1553
|
},
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
return;
|
|
1137
|
-
}
|
|
1138
|
-
try {
|
|
1139
|
-
let result;
|
|
1140
|
-
if (shouldAutoSubmit) {
|
|
1141
|
-
result = await submitPageSpeedForm(values, formConfig);
|
|
1142
|
-
}
|
|
1143
|
-
if (onSubmit) {
|
|
1144
|
-
await onSubmit(values);
|
|
1145
|
-
}
|
|
1146
|
-
if (shouldAutoSubmit || onSubmit) {
|
|
1147
|
-
if (formConfig?.resetOnSuccess !== false) {
|
|
1148
|
-
helpers.resetForm();
|
|
1149
|
-
}
|
|
1150
|
-
onSuccess?.(result);
|
|
1151
|
-
}
|
|
1152
|
-
} catch (error) {
|
|
1153
|
-
if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
|
|
1154
|
-
helpers.setErrors(error.formErrors);
|
|
1155
|
-
}
|
|
1156
|
-
onError?.(error);
|
|
1157
|
-
throw error;
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1554
|
+
onError,
|
|
1555
|
+
resetOnSuccess: formConfig?.resetOnSuccess !== false,
|
|
1556
|
+
uploadTokens
|
|
1160
1557
|
});
|
|
1161
|
-
const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
|
|
1162
1558
|
const actionsContent = React__namespace.useMemo(() => {
|
|
1163
1559
|
if (actionsSlot) return actionsSlot;
|
|
1164
1560
|
if (actions && actions.length > 0) {
|
|
@@ -1269,87 +1665,70 @@ function ContactDark({
|
|
|
1269
1665
|
cardClassName
|
|
1270
1666
|
),
|
|
1271
1667
|
children: [
|
|
1272
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
"aria-label": "Last Name"
|
|
1304
|
-
}
|
|
1305
|
-
)
|
|
1306
|
-
] }) })
|
|
1307
|
-
] }),
|
|
1308
|
-
/* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "email", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
1309
|
-
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: "Email Address" }),
|
|
1310
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1311
|
-
inputs.TextInput,
|
|
1668
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("p-6 lg:p-12", formPanelClassName), children: [
|
|
1669
|
+
isSubmitted && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1670
|
+
"div",
|
|
1671
|
+
{
|
|
1672
|
+
className: cn(
|
|
1673
|
+
"mb-6 p-4 bg-primary/10 border border-primary rounded-md",
|
|
1674
|
+
successMessageClassName
|
|
1675
|
+
),
|
|
1676
|
+
children: typeof successMessage === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-primary-foreground/90 text-center", children: successMessage }) : successMessage
|
|
1677
|
+
}
|
|
1678
|
+
),
|
|
1679
|
+
submissionError && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1680
|
+
"div",
|
|
1681
|
+
{
|
|
1682
|
+
className: cn(
|
|
1683
|
+
"mb-6 p-4 bg-destructive/10 border border-destructive rounded-md",
|
|
1684
|
+
errorMessageClassName
|
|
1685
|
+
),
|
|
1686
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive text-center", children: submissionError })
|
|
1687
|
+
}
|
|
1688
|
+
),
|
|
1689
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1690
|
+
forms.Form,
|
|
1691
|
+
{
|
|
1692
|
+
form,
|
|
1693
|
+
action: formConfig?.endpoint,
|
|
1694
|
+
method: formMethod,
|
|
1695
|
+
className: cn("space-y-6", formClassName),
|
|
1696
|
+
children: [
|
|
1697
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-12 gap-4", children: formFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1698
|
+
"div",
|
|
1312
1699
|
{
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1700
|
+
className: getColumnSpanClass(field.columnSpan),
|
|
1701
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1702
|
+
DynamicFormField,
|
|
1703
|
+
{
|
|
1704
|
+
field,
|
|
1705
|
+
uploadProgress,
|
|
1706
|
+
onFileUpload: uploadFiles,
|
|
1707
|
+
onFileRemove: removeFile,
|
|
1708
|
+
isUploading
|
|
1709
|
+
}
|
|
1710
|
+
)
|
|
1711
|
+
},
|
|
1712
|
+
field.name
|
|
1713
|
+
)) }),
|
|
1714
|
+
actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1715
|
+
Pressable,
|
|
1326
1716
|
{
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1717
|
+
componentType: "button",
|
|
1718
|
+
type: "submit",
|
|
1719
|
+
className: cn("w-full", submitClassName),
|
|
1720
|
+
asButton: true,
|
|
1721
|
+
disabled: form.isSubmitting,
|
|
1722
|
+
children: [
|
|
1723
|
+
buttonIcon,
|
|
1724
|
+
buttonText
|
|
1725
|
+
]
|
|
1333
1726
|
}
|
|
1334
1727
|
)
|
|
1335
|
-
]
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
componentType: "button",
|
|
1340
|
-
type: "submit",
|
|
1341
|
-
className: cn("w-full", submitClassName),
|
|
1342
|
-
asButton: true,
|
|
1343
|
-
disabled: form.isSubmitting,
|
|
1344
|
-
children: [
|
|
1345
|
-
buttonIcon,
|
|
1346
|
-
buttonText
|
|
1347
|
-
]
|
|
1348
|
-
}
|
|
1349
|
-
)
|
|
1350
|
-
]
|
|
1351
|
-
}
|
|
1352
|
-
) }),
|
|
1728
|
+
]
|
|
1729
|
+
}
|
|
1730
|
+
)
|
|
1731
|
+
] }),
|
|
1353
1732
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1354
1733
|
"div",
|
|
1355
1734
|
{
|