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