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