@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.
@@ -3,12 +3,12 @@
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');
11
10
  var img = require('@page-speed/img');
11
+ var inputs = require('@page-speed/forms/inputs');
12
12
  var LabelPrimitive = require('@radix-ui/react-label');
13
13
  var integration = require('@page-speed/forms/integration');
14
14
 
@@ -501,6 +501,389 @@ function Label({
501
501
  }
502
502
  );
503
503
  }
504
+ function DynamicFormField({
505
+ field,
506
+ className,
507
+ uploadProgress = {},
508
+ onFileUpload,
509
+ onFileRemove,
510
+ isUploading = false
511
+ }) {
512
+ const fieldId = `field-${field.name}`;
513
+ return /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: field.name, children: ({ field: formField, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-2", className), children: [
514
+ field.type !== "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: fieldId, children: [
515
+ field.label,
516
+ field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-1", children: "*" })
517
+ ] }),
518
+ (field.type === "text" || field.type === "email" || field.type === "tel" || field.type === "search" || field.type === "password" || field.type === "url") && /* @__PURE__ */ jsxRuntime.jsx(
519
+ inputs.TextInput,
520
+ {
521
+ ...formField,
522
+ id: fieldId,
523
+ type: field.type,
524
+ placeholder: field.placeholder,
525
+ error: meta.touched && !!meta.error,
526
+ disabled: field.disabled,
527
+ "aria-label": field.label
528
+ }
529
+ ),
530
+ field.type === "number" && /* @__PURE__ */ jsxRuntime.jsx(
531
+ inputs.TextInput,
532
+ {
533
+ ...formField,
534
+ id: fieldId,
535
+ type: "text",
536
+ placeholder: field.placeholder,
537
+ error: meta.touched && !!meta.error,
538
+ disabled: field.disabled,
539
+ "aria-label": field.label
540
+ }
541
+ ),
542
+ field.type === "textarea" && /* @__PURE__ */ jsxRuntime.jsx(
543
+ inputs.TextArea,
544
+ {
545
+ ...formField,
546
+ id: fieldId,
547
+ placeholder: field.placeholder,
548
+ rows: field.rows || 4,
549
+ error: meta.touched && !!meta.error,
550
+ disabled: field.disabled,
551
+ "aria-label": field.label
552
+ }
553
+ ),
554
+ field.type === "select" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
555
+ inputs.Select,
556
+ {
557
+ ...formField,
558
+ id: fieldId,
559
+ options: field.options,
560
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
561
+ error: meta.touched && !!meta.error,
562
+ disabled: field.disabled,
563
+ "aria-label": field.label
564
+ }
565
+ ),
566
+ field.type === "multi-select" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
567
+ inputs.Select,
568
+ {
569
+ ...formField,
570
+ id: fieldId,
571
+ options: field.options,
572
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
573
+ error: meta.touched && !!meta.error,
574
+ disabled: field.disabled,
575
+ "aria-label": field.label,
576
+ multiple: true
577
+ }
578
+ ),
579
+ field.type === "radio" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
580
+ inputs.Radio,
581
+ {
582
+ ...formField,
583
+ id: fieldId,
584
+ options: field.options,
585
+ disabled: field.disabled,
586
+ layout: field.layout || "stacked",
587
+ error: meta.touched && !!meta.error,
588
+ "aria-label": field.label
589
+ }
590
+ ),
591
+ field.type === "checkbox" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-2", children: [
592
+ /* @__PURE__ */ jsxRuntime.jsx(
593
+ inputs.Checkbox,
594
+ {
595
+ ...formField,
596
+ id: fieldId,
597
+ value: formField.value === true || formField.value === "true",
598
+ onChange: (checked) => formField.onChange(checked),
599
+ disabled: field.disabled,
600
+ error: meta.touched && !!meta.error,
601
+ "aria-label": field.label
602
+ }
603
+ ),
604
+ /* @__PURE__ */ jsxRuntime.jsxs(
605
+ Label,
606
+ {
607
+ htmlFor: fieldId,
608
+ className: "font-normal cursor-pointer leading-relaxed",
609
+ children: [
610
+ field.label,
611
+ field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-1", children: "*" })
612
+ ]
613
+ }
614
+ )
615
+ ] }),
616
+ field.type === "checkbox-group" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
617
+ inputs.CheckboxGroup,
618
+ {
619
+ ...formField,
620
+ id: fieldId,
621
+ options: field.options,
622
+ disabled: field.disabled,
623
+ layout: field.layout || "stacked",
624
+ error: meta.touched && !!meta.error,
625
+ "aria-label": field.label
626
+ }
627
+ ),
628
+ (field.type === "date-picker" || field.type === "date") && /* @__PURE__ */ jsxRuntime.jsx(
629
+ inputs.DatePicker,
630
+ {
631
+ ...formField,
632
+ id: fieldId,
633
+ placeholder: field.placeholder,
634
+ error: meta.touched && !!meta.error,
635
+ disabled: field.disabled,
636
+ "aria-label": field.label
637
+ }
638
+ ),
639
+ field.type === "date-range" && /* @__PURE__ */ jsxRuntime.jsx(
640
+ inputs.DateRangePicker,
641
+ {
642
+ ...formField,
643
+ id: fieldId,
644
+ error: meta.touched && !!meta.error,
645
+ disabled: field.disabled,
646
+ "aria-label": field.label
647
+ }
648
+ ),
649
+ field.type === "time" && /* @__PURE__ */ jsxRuntime.jsx(
650
+ inputs.TimePicker,
651
+ {
652
+ ...formField,
653
+ id: fieldId,
654
+ placeholder: field.placeholder,
655
+ error: meta.touched && !!meta.error,
656
+ disabled: field.disabled,
657
+ "aria-label": field.label
658
+ }
659
+ ),
660
+ field.type === "file" && /* @__PURE__ */ jsxRuntime.jsx(
661
+ inputs.FileInput,
662
+ {
663
+ ...formField,
664
+ id: fieldId,
665
+ accept: field.accept,
666
+ maxSize: field.maxSize || 5 * 1024 * 1024,
667
+ maxFiles: field.maxFiles || 1,
668
+ multiple: field.multiple || false,
669
+ placeholder: field.placeholder || "Choose file(s)...",
670
+ error: meta.touched && !!meta.error,
671
+ disabled: field.disabled || isUploading,
672
+ showProgress: true,
673
+ uploadProgress,
674
+ onChange: (files) => {
675
+ formField.onChange(files);
676
+ if (files.length > 0 && onFileUpload) {
677
+ onFileUpload(files);
678
+ }
679
+ },
680
+ onFileRemove,
681
+ "aria-label": field.label
682
+ }
683
+ ),
684
+ field.type === "rich-text" && /* @__PURE__ */ jsxRuntime.jsx(
685
+ inputs.RichTextEditor,
686
+ {
687
+ ...formField,
688
+ id: fieldId,
689
+ placeholder: field.placeholder,
690
+ error: meta.touched && !!meta.error,
691
+ disabled: field.disabled,
692
+ "aria-label": field.label
693
+ }
694
+ ),
695
+ meta.touched && meta.error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: meta.error })
696
+ ] }) });
697
+ }
698
+
699
+ // lib/form-field-types.ts
700
+ function generateInitialValues(fields) {
701
+ return fields.reduce(
702
+ (acc, field) => {
703
+ if (field.type === "checkbox") {
704
+ acc[field.name] = false;
705
+ } else if (field.type === "checkbox-group" || field.type === "multi-select") {
706
+ acc[field.name] = [];
707
+ } else if (field.type === "file") {
708
+ acc[field.name] = [];
709
+ } else if (field.type === "date-range") {
710
+ acc[field.name] = { start: null, end: null };
711
+ } else {
712
+ acc[field.name] = "";
713
+ }
714
+ return acc;
715
+ },
716
+ {}
717
+ );
718
+ }
719
+ function generateValidationSchema(fields) {
720
+ return fields.reduce(
721
+ (acc, field) => {
722
+ acc[field.name] = (value, allValues) => {
723
+ if (field.required) {
724
+ if (!value || typeof value === "string" && !value.trim()) {
725
+ return `${field.label} is required`;
726
+ }
727
+ }
728
+ if (field.type === "email" && value) {
729
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
730
+ return "Please enter a valid email address";
731
+ }
732
+ }
733
+ if (field.type === "url" && value) {
734
+ try {
735
+ new URL(value);
736
+ } catch {
737
+ return "Please enter a valid URL";
738
+ }
739
+ }
740
+ if (field.validator) {
741
+ return field.validator(value, allValues);
742
+ }
743
+ return void 0;
744
+ };
745
+ return acc;
746
+ },
747
+ {}
748
+ );
749
+ }
750
+ function getColumnSpanClass(span) {
751
+ if (!span || span === 12) return "col-span-12";
752
+ return `col-span-12 sm:col-span-${Math.min(span, 12)}`;
753
+ }
754
+ function useFileUpload(options) {
755
+ const [uploadTokens, setUploadTokens] = React.useState([]);
756
+ const [uploadProgress, setUploadProgress] = React.useState({});
757
+ const [isUploading, setIsUploading] = React.useState(false);
758
+ const endpoint = options?.endpoint || "https://api.dashtrack.com/contacts/_/contact_form_uploads";
759
+ const uploadFiles = React.useCallback(
760
+ async (files) => {
761
+ if (files.length === 0) return;
762
+ setIsUploading(true);
763
+ try {
764
+ const tokens = [];
765
+ for (const file of files) {
766
+ const formData = new FormData();
767
+ formData.append("contact_form_upload[file_upload]", file);
768
+ formData.append("contact_form_upload[title]", file.name);
769
+ formData.append("contact_form_upload[file_name]", file.name);
770
+ formData.append("contact_form_upload[file_size]", String(file.size));
771
+ const response = await fetch(endpoint, {
772
+ method: "POST",
773
+ body: formData
774
+ });
775
+ if (!response.ok) {
776
+ throw new Error(`Upload failed: ${response.statusText}`);
777
+ }
778
+ const data = await response.json();
779
+ if (data.contact_form_upload?.token) {
780
+ tokens.push(`upload_${data.contact_form_upload.token}`);
781
+ }
782
+ setUploadProgress((prev) => ({
783
+ ...prev,
784
+ [file.name]: 100
785
+ }));
786
+ }
787
+ setUploadTokens(tokens);
788
+ } catch (error) {
789
+ console.error("File upload error:", error);
790
+ options?.onError?.(error);
791
+ } finally {
792
+ setIsUploading(false);
793
+ }
794
+ },
795
+ [endpoint, options]
796
+ );
797
+ const removeFile = React.useCallback((file, index) => {
798
+ setUploadTokens((prev) => prev.filter((_, i) => i !== index));
799
+ setUploadProgress((prev) => {
800
+ const newProgress = { ...prev };
801
+ delete newProgress[file.name];
802
+ return newProgress;
803
+ });
804
+ }, []);
805
+ const resetUpload = React.useCallback(() => {
806
+ setUploadTokens([]);
807
+ setUploadProgress({});
808
+ }, []);
809
+ return {
810
+ uploadTokens,
811
+ uploadProgress,
812
+ isUploading,
813
+ uploadFiles,
814
+ removeFile,
815
+ resetUpload
816
+ };
817
+ }
818
+ function useContactForm(options) {
819
+ const {
820
+ formFields,
821
+ formConfig,
822
+ onSubmit,
823
+ onSuccess,
824
+ onError,
825
+ resetOnSuccess = true,
826
+ uploadTokens = []
827
+ } = options;
828
+ const [isSubmitted, setIsSubmitted] = React.useState(false);
829
+ const [submissionError, setSubmissionError] = React.useState(null);
830
+ const form = forms.useForm({
831
+ initialValues: React.useMemo(
832
+ () => generateInitialValues(formFields),
833
+ [formFields]
834
+ ),
835
+ validationSchema: React.useMemo(
836
+ () => generateValidationSchema(formFields),
837
+ [formFields]
838
+ ),
839
+ onSubmit: async (values, helpers) => {
840
+ setSubmissionError(null);
841
+ const shouldAutoSubmit = Boolean(formConfig?.endpoint);
842
+ if (!shouldAutoSubmit && !onSubmit) {
843
+ return;
844
+ }
845
+ try {
846
+ let result;
847
+ const submissionValues = {
848
+ ...values,
849
+ ...uploadTokens.length > 0 && {
850
+ contact_form_upload_tokens: uploadTokens
851
+ }
852
+ };
853
+ if (shouldAutoSubmit) {
854
+ result = await submitPageSpeedForm(submissionValues, formConfig);
855
+ }
856
+ if (onSubmit) {
857
+ await onSubmit(submissionValues);
858
+ }
859
+ if (shouldAutoSubmit || onSubmit) {
860
+ setIsSubmitted(true);
861
+ if (resetOnSuccess) {
862
+ helpers.resetForm();
863
+ }
864
+ onSuccess?.(result);
865
+ setTimeout(() => setIsSubmitted(false), 5e3);
866
+ }
867
+ } catch (error) {
868
+ if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
869
+ helpers.setErrors(error.formErrors);
870
+ }
871
+ const errorMessage = error instanceof Error ? error.message : "Form submission failed";
872
+ setSubmissionError(errorMessage);
873
+ onError?.(error);
874
+ }
875
+ }
876
+ });
877
+ const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
878
+ return {
879
+ form,
880
+ isSubmitted,
881
+ submissionError,
882
+ formMethod
883
+ };
884
+ }
885
+
886
+ // lib/forms.ts
504
887
  var PageSpeedFormSubmissionError = class extends Error {
505
888
  constructor(message, options = {}) {
506
889
  super(message);
@@ -882,19 +1265,67 @@ function PatternBackground({
882
1265
  }
883
1266
  );
884
1267
  }
1268
+ var DEFAULT_FORM_FIELDS = [
1269
+ {
1270
+ name: "first_name",
1271
+ type: "text",
1272
+ label: "First Name",
1273
+ placeholder: "First name",
1274
+ required: true,
1275
+ columnSpan: 6
1276
+ },
1277
+ {
1278
+ name: "last_name",
1279
+ type: "text",
1280
+ label: "Last Name",
1281
+ placeholder: "Last name",
1282
+ required: true,
1283
+ columnSpan: 6
1284
+ },
1285
+ {
1286
+ name: "email",
1287
+ type: "email",
1288
+ label: "Email",
1289
+ placeholder: "your@email.com",
1290
+ required: true,
1291
+ columnSpan: 12
1292
+ },
1293
+ {
1294
+ name: "phone",
1295
+ type: "tel",
1296
+ label: "Phone",
1297
+ placeholder: "+1 (555) 000-0000",
1298
+ required: true,
1299
+ columnSpan: 12
1300
+ },
1301
+ {
1302
+ name: "message",
1303
+ type: "textarea",
1304
+ label: "Message",
1305
+ placeholder: "Your message...",
1306
+ required: true,
1307
+ rows: 4,
1308
+ columnSpan: 12
1309
+ }
1310
+ ];
885
1311
  function ContactPhotography({
886
1312
  heading,
887
1313
  description,
888
- buttonText,
1314
+ buttonText = "Submit",
889
1315
  buttonIcon,
890
1316
  actions,
891
1317
  actionsSlot,
1318
+ formFields = DEFAULT_FORM_FIELDS,
1319
+ successMessage = "Thank you! Your message has been sent successfully.",
1320
+ errorMessage = "There was an error sending your message. Please try again.",
892
1321
  className,
893
1322
  headingClassName,
894
1323
  descriptionClassName,
895
1324
  contentClassName,
896
1325
  formClassName,
897
1326
  submitClassName,
1327
+ successMessageClassName,
1328
+ errorMessageClassName,
898
1329
  background,
899
1330
  pattern,
900
1331
  patternOpacity,
@@ -908,55 +1339,26 @@ function ContactPhotography({
908
1339
  onSuccess,
909
1340
  onError
910
1341
  }) {
911
- const form = forms.useForm({
912
- initialValues: {
913
- first_name: "",
914
- last_name: "",
915
- email: "",
916
- phone: "",
917
- message: ""
1342
+ const {
1343
+ uploadTokens,
1344
+ uploadProgress,
1345
+ isUploading,
1346
+ uploadFiles,
1347
+ removeFile,
1348
+ resetUpload
1349
+ } = useFileUpload({ onError });
1350
+ const { form, isSubmitted, submissionError, formMethod } = useContactForm({
1351
+ formFields,
1352
+ formConfig,
1353
+ onSubmit,
1354
+ onSuccess: (data) => {
1355
+ resetUpload();
1356
+ onSuccess?.(data);
918
1357
  },
919
- validationSchema: {
920
- first_name: (value) => !value ? "First name is required" : void 0,
921
- last_name: (value) => !value ? "Last name is required" : void 0,
922
- email: (value) => {
923
- if (!value) return "Email is required";
924
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
925
- return "Please enter a valid email address";
926
- return void 0;
927
- },
928
- phone: (value) => !value ? "Phone is required" : void 0,
929
- message: (value) => !value ? "Message is required" : void 0
930
- },
931
- onSubmit: async (values, helpers) => {
932
- const shouldAutoSubmit = Boolean(formConfig?.endpoint);
933
- if (!shouldAutoSubmit && !onSubmit) {
934
- return;
935
- }
936
- try {
937
- let result;
938
- if (shouldAutoSubmit) {
939
- result = await submitPageSpeedForm(values, formConfig);
940
- }
941
- if (onSubmit) {
942
- await onSubmit(values);
943
- }
944
- if (shouldAutoSubmit || onSubmit) {
945
- if (formConfig?.resetOnSuccess !== false) {
946
- helpers.resetForm();
947
- }
948
- onSuccess?.(result);
949
- }
950
- } catch (error) {
951
- if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
952
- helpers.setErrors(error.formErrors);
953
- }
954
- onError?.(error);
955
- throw error;
956
- }
957
- }
1358
+ onError,
1359
+ resetOnSuccess: formConfig?.resetOnSuccess !== false,
1360
+ uploadTokens
958
1361
  });
959
- const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
960
1362
  const actionsContent = React.useMemo(() => {
961
1363
  if (actionsSlot) return actionsSlot;
962
1364
  if (actions && actions.length > 0) {
@@ -1035,6 +1437,26 @@ function ContactPhotography({
1035
1437
  children: description
1036
1438
  }
1037
1439
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description })),
1440
+ isSubmitted && /* @__PURE__ */ jsxRuntime.jsx(
1441
+ "div",
1442
+ {
1443
+ className: cn(
1444
+ "p-4 bg-primary/10 border border-primary rounded-md",
1445
+ successMessageClassName
1446
+ ),
1447
+ children: typeof successMessage === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-primary-foreground/90 text-center", children: successMessage }) : successMessage
1448
+ }
1449
+ ),
1450
+ submissionError && /* @__PURE__ */ jsxRuntime.jsx(
1451
+ "div",
1452
+ {
1453
+ className: cn(
1454
+ "p-4 bg-destructive/10 border border-destructive rounded-md",
1455
+ errorMessageClassName
1456
+ ),
1457
+ children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive text-center", children: submissionError })
1458
+ }
1459
+ ),
1038
1460
  /* @__PURE__ */ jsxRuntime.jsxs(
1039
1461
  forms.Form,
1040
1462
  {
@@ -1043,76 +1465,23 @@ function ContactPhotography({
1043
1465
  method: formMethod,
1044
1466
  className: cn("space-y-4", formClassName),
1045
1467
  children: [
1046
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [
1047
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "first_name", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1048
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "first-name", children: "First Name" }),
1049
- /* @__PURE__ */ jsxRuntime.jsx(
1050
- inputs.TextInput,
1051
- {
1052
- ...field,
1053
- id: "first-name",
1054
- placeholder: "John",
1055
- error: meta.touched && !!meta.error,
1056
- "aria-label": "First Name"
1057
- }
1058
- )
1059
- ] }) }),
1060
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "last_name", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1061
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "last-name", children: "Last Name" }),
1062
- /* @__PURE__ */ jsxRuntime.jsx(
1063
- inputs.TextInput,
1468
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-12 gap-4", children: formFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
1469
+ "div",
1470
+ {
1471
+ className: getColumnSpanClass(field.columnSpan),
1472
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1473
+ DynamicFormField,
1064
1474
  {
1065
- ...field,
1066
- id: "last-name",
1067
- placeholder: "Doe",
1068
- error: meta.touched && !!meta.error,
1069
- "aria-label": "Last Name"
1475
+ field,
1476
+ uploadProgress,
1477
+ onFileUpload: uploadFiles,
1478
+ onFileRemove: removeFile,
1479
+ isUploading
1070
1480
  }
1071
1481
  )
1072
- ] }) })
1073
- ] }),
1074
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "email", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1075
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: "Email" }),
1076
- /* @__PURE__ */ jsxRuntime.jsx(
1077
- inputs.TextInput,
1078
- {
1079
- ...field,
1080
- id: "email",
1081
- type: "email",
1082
- placeholder: "john@example.com",
1083
- error: meta.touched && !!meta.error,
1084
- "aria-label": "Email"
1085
- }
1086
- )
1087
- ] }) }),
1088
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "phone", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1089
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "phone", children: "Phone" }),
1090
- /* @__PURE__ */ jsxRuntime.jsx(
1091
- inputs.TextInput,
1092
- {
1093
- ...field,
1094
- id: "phone",
1095
- type: "tel",
1096
- placeholder: "+1 (555) 000-0000",
1097
- error: meta.touched && !!meta.error,
1098
- "aria-label": "Phone"
1099
- }
1100
- )
1101
- ] }) }),
1102
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "message", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1103
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "message", children: "Message" }),
1104
- /* @__PURE__ */ jsxRuntime.jsx(
1105
- inputs.TextArea,
1106
- {
1107
- ...field,
1108
- id: "message",
1109
- placeholder: "Your message...",
1110
- rows: 4,
1111
- error: meta.touched && !!meta.error,
1112
- "aria-label": "Message"
1113
- }
1114
- )
1115
- ] }) }),
1482
+ },
1483
+ field.name
1484
+ )) }),
1116
1485
  actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxRuntime.jsxs(
1117
1486
  Pressable,
1118
1487
  {