@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
@@ -1,18 +1,14 @@
1
1
  "use client";
2
2
  import * as React from 'react';
3
- import React__default from 'react';
4
- import { useForm, Form, Field } from '@page-speed/forms';
5
- import { TextInput as TextInput$1, TextArea as TextArea$1 } from '@page-speed/forms/inputs';
3
+ import React__default, { useMemo } from 'react';
4
+ import { Form } from '@page-speed/forms';
5
+ import { useFileUpload, useContactForm, getColumnSpanClass, DynamicFormField } from '@page-speed/forms/integration';
6
6
  import { clsx } from 'clsx';
7
7
  import { twMerge } from 'tailwind-merge';
8
8
  import { cva } from 'class-variance-authority';
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
- import * as LabelPrimitive from '@radix-ui/react-label';
11
- import { submitPageSpeedForm, PageSpeedFormSubmissionError } from '@page-speed/forms/integration';
12
10
 
13
11
  // components/blocks/contact/contact-fitness.tsx
14
- var TextInput = TextInput$1;
15
- var TextArea = TextArea$1;
16
12
  function cn(...inputs) {
17
13
  return twMerge(clsx(inputs));
18
14
  }
@@ -457,22 +453,6 @@ function CardContent({ className, ...props }) {
457
453
  }
458
454
  );
459
455
  }
460
- function Label({
461
- className,
462
- ...props
463
- }) {
464
- return /* @__PURE__ */ jsx(
465
- LabelPrimitive.Root,
466
- {
467
- "data-slot": "label",
468
- className: cn(
469
- "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",
470
- className
471
- ),
472
- ...props
473
- }
474
- );
475
- }
476
456
  var maxWidthStyles = {
477
457
  sm: "max-w-screen-sm",
478
458
  md: "max-w-screen-md",
@@ -848,14 +828,60 @@ var Section = React__default.forwardRef(
848
828
  }
849
829
  );
850
830
  Section.displayName = "Section";
831
+ var DEFAULT_FORM_FIELDS = [
832
+ {
833
+ name: "first_name",
834
+ type: "text",
835
+ label: "First Name",
836
+ placeholder: "John",
837
+ required: true,
838
+ columnSpan: 6
839
+ },
840
+ {
841
+ name: "last_name",
842
+ type: "text",
843
+ label: "Last Name",
844
+ placeholder: "Doe",
845
+ required: true,
846
+ columnSpan: 6
847
+ },
848
+ {
849
+ name: "email",
850
+ type: "email",
851
+ label: "Email",
852
+ placeholder: "john@example.com",
853
+ required: true,
854
+ columnSpan: 12
855
+ },
856
+ {
857
+ name: "phone",
858
+ type: "tel",
859
+ label: "Phone",
860
+ placeholder: "+1 (555) 000-0000",
861
+ required: true,
862
+ columnSpan: 12
863
+ },
864
+ {
865
+ name: "message",
866
+ type: "textarea",
867
+ label: "Message",
868
+ placeholder: "Your message...",
869
+ required: true,
870
+ rows: 4,
871
+ columnSpan: 12
872
+ }
873
+ ];
851
874
  function ContactFitness({
852
875
  heading,
853
876
  description,
854
- buttonText,
877
+ buttonText = "Submit",
855
878
  buttonIcon,
856
879
  actions,
857
880
  actionsSlot,
881
+ formFields = DEFAULT_FORM_FIELDS,
882
+ successMessage = "Thank you! Your message has been sent successfully.",
858
883
  className,
884
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
859
885
  headerClassName,
860
886
  headingClassName,
861
887
  descriptionClassName,
@@ -863,66 +889,38 @@ function ContactFitness({
863
889
  cardContentClassName,
864
890
  formClassName,
865
891
  submitClassName,
866
- background,
867
- spacing = "py-8 md:py-32",
868
- containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
892
+ successMessageClassName,
893
+ errorMessageClassName,
894
+ background = "white",
895
+ spacing = "xl",
869
896
  pattern,
870
- patternOpacity,
897
+ patternOpacity = 0.1,
871
898
  formConfig,
872
899
  onSubmit,
873
900
  onSuccess,
874
901
  onError
875
902
  }) {
876
- const form = useForm({
877
- initialValues: {
878
- first_name: "",
879
- last_name: "",
880
- email: "",
881
- phone: "",
882
- message: ""
883
- },
884
- validationSchema: {
885
- first_name: (value) => !value ? "First name is required" : void 0,
886
- last_name: (value) => !value ? "Last name is required" : void 0,
887
- email: (value) => {
888
- if (!value) return "Email is required";
889
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
890
- return "Please enter a valid email address";
891
- return void 0;
892
- },
893
- phone: (value) => !value ? "Phone is required" : void 0,
894
- message: (value) => !value ? "Message is required" : void 0
903
+ const {
904
+ uploadTokens,
905
+ uploadProgress,
906
+ isUploading,
907
+ uploadFiles,
908
+ removeFile,
909
+ resetUpload
910
+ } = useFileUpload({ onError });
911
+ const { form, submissionError, formMethod, resetSubmissionState } = useContactForm({
912
+ formFields,
913
+ formConfig,
914
+ onSubmit,
915
+ onSuccess: (data) => {
916
+ resetUpload();
917
+ onSuccess?.(data);
895
918
  },
896
- onSubmit: async (values, helpers) => {
897
- const shouldAutoSubmit = Boolean(formConfig?.endpoint);
898
- if (!shouldAutoSubmit && !onSubmit) {
899
- return;
900
- }
901
- try {
902
- let result;
903
- if (shouldAutoSubmit) {
904
- result = await submitPageSpeedForm(values, formConfig);
905
- }
906
- if (onSubmit) {
907
- await onSubmit(values);
908
- }
909
- if (shouldAutoSubmit || onSubmit) {
910
- if (formConfig?.resetOnSuccess !== false) {
911
- helpers.resetForm();
912
- }
913
- onSuccess?.(result);
914
- }
915
- } catch (error) {
916
- if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
917
- helpers.setErrors(error.formErrors);
918
- }
919
- onError?.(error);
920
- throw error;
921
- }
922
- }
919
+ onError,
920
+ resetOnSuccess: formConfig?.resetOnSuccess !== false,
921
+ uploadTokens
923
922
  });
924
- const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
925
- const actionsContent = React.useMemo(() => {
923
+ const actionsContent = useMemo(() => {
926
924
  if (actionsSlot) return actionsSlot;
927
925
  if (actions && actions.length > 0) {
928
926
  return actions.map((action, index) => {
@@ -959,9 +957,9 @@ function ContactFitness({
959
957
  spacing,
960
958
  pattern,
961
959
  patternOpacity,
962
- className,
960
+ className: cn("py-12", className),
963
961
  containerClassName,
964
- children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
962
+ children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
965
963
  /* @__PURE__ */ jsxs("div", { className: cn("mb-10 text-center", headerClassName), children: [
966
964
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
967
965
  "h2",
@@ -988,81 +986,43 @@ function ContactFitness({
988
986
  Form,
989
987
  {
990
988
  form,
991
- action: formConfig?.endpoint,
992
- method: formMethod,
993
- className: cn("space-y-4", formClassName),
989
+ notificationConfig: {
990
+ submissionError,
991
+ successMessage
992
+ },
993
+ styleConfig: {
994
+ formClassName: cn("space-y-4", formClassName),
995
+ successMessageClassName,
996
+ errorMessageClassName
997
+ },
998
+ formConfig: {
999
+ endpoint: formConfig?.endpoint,
1000
+ method: formMethod,
1001
+ submissionConfig: formConfig?.submissionConfig
1002
+ },
1003
+ onNewSubmission: () => {
1004
+ resetUpload();
1005
+ resetSubmissionState();
1006
+ },
994
1007
  children: [
995
- /* @__PURE__ */ jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [
996
- /* @__PURE__ */ jsx(Field, { name: "first_name", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
997
- /* @__PURE__ */ jsx(Label, { htmlFor: "first-name", children: "First Name" }),
998
- /* @__PURE__ */ jsx(
999
- TextInput,
1000
- {
1001
- ...field,
1002
- id: "first-name",
1003
- placeholder: "John",
1004
- error: meta.touched && !!meta.error,
1005
- "aria-label": "First Name"
1006
- }
1007
- )
1008
- ] }) }),
1009
- /* @__PURE__ */ jsx(Field, { name: "last_name", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1010
- /* @__PURE__ */ jsx(Label, { htmlFor: "last-name", children: "Last Name" }),
1011
- /* @__PURE__ */ jsx(
1012
- TextInput,
1008
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-12 gap-6", children: formFields.map((field) => /* @__PURE__ */ jsx(
1009
+ "div",
1010
+ {
1011
+ className: getColumnSpanClass(field.columnSpan),
1012
+ children: /* @__PURE__ */ jsx(
1013
+ DynamicFormField,
1013
1014
  {
1014
- ...field,
1015
- id: "last-name",
1016
- placeholder: "Doe",
1017
- error: meta.touched && !!meta.error,
1018
- "aria-label": "Last Name"
1015
+ field,
1016
+ uploadProgress,
1017
+ onFileUpload: uploadFiles,
1018
+ onFileRemove: removeFile,
1019
+ isUploading
1019
1020
  }
1020
1021
  )
1021
- ] }) })
1022
- ] }),
1023
- /* @__PURE__ */ jsx(Field, { name: "email", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1024
- /* @__PURE__ */ jsx(Label, { htmlFor: "email", children: "Email" }),
1025
- /* @__PURE__ */ jsx(
1026
- TextInput,
1027
- {
1028
- ...field,
1029
- id: "email",
1030
- type: "email",
1031
- placeholder: "john@example.com",
1032
- error: meta.touched && !!meta.error,
1033
- "aria-label": "Email"
1034
- }
1035
- )
1036
- ] }) }),
1037
- /* @__PURE__ */ jsx(Field, { name: "phone", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1038
- /* @__PURE__ */ jsx(Label, { htmlFor: "phone", children: "Phone" }),
1039
- /* @__PURE__ */ jsx(
1040
- TextInput,
1041
- {
1042
- ...field,
1043
- id: "phone",
1044
- type: "tel",
1045
- placeholder: "+1 (555) 000-0000",
1046
- error: meta.touched && !!meta.error,
1047
- "aria-label": "Phone"
1048
- }
1049
- )
1050
- ] }) }),
1051
- /* @__PURE__ */ jsx(Field, { name: "message", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1052
- /* @__PURE__ */ jsx(Label, { htmlFor: "message", children: "Message" }),
1053
- /* @__PURE__ */ jsx(
1054
- TextArea,
1055
- {
1056
- ...field,
1057
- id: "message",
1058
- placeholder: "Your message...",
1059
- rows: 4,
1060
- error: meta.touched && !!meta.error,
1061
- "aria-label": "Message"
1062
- }
1063
- )
1064
- ] }) }),
1065
- actionsSlot || actions ? actionsContent : /* @__PURE__ */ jsxs(
1022
+ },
1023
+ field.name
1024
+ )) }),
1025
+ actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxs(
1066
1026
  Pressable,
1067
1027
  {
1068
1028
  componentType: "button",
@@ -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-guest.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
  }
@@ -479,22 +474,6 @@ function CardContent({ className, ...props }) {
479
474
  }
480
475
  );
481
476
  }
482
- function Label({
483
- className,
484
- ...props
485
- }) {
486
- return /* @__PURE__ */ jsxRuntime.jsx(
487
- LabelPrimitive__namespace.Root,
488
- {
489
- "data-slot": "label",
490
- className: cn(
491
- "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",
492
- className
493
- ),
494
- ...props
495
- }
496
- );
497
- }
498
477
  var maxWidthStyles = {
499
478
  sm: "max-w-screen-sm",
500
479
  md: "max-w-screen-md",
@@ -870,14 +849,60 @@ var Section = React__namespace.default.forwardRef(
870
849
  }
871
850
  );
872
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
+ ];
873
895
  function ContactGuest({
874
896
  heading,
875
897
  description,
876
- buttonText,
898
+ buttonText = "Submit",
877
899
  buttonIcon,
878
900
  actions,
879
901
  actionsSlot,
902
+ formFields = DEFAULT_FORM_FIELDS,
903
+ successMessage = "Thank you! Your message has been sent successfully.",
880
904
  className,
905
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
881
906
  headerClassName,
882
907
  headingClassName,
883
908
  descriptionClassName,
@@ -885,66 +910,38 @@ function ContactGuest({
885
910
  cardContentClassName,
886
911
  formClassName,
887
912
  submitClassName,
888
- background,
889
- spacing = "py-8 md:py-32",
890
- containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
913
+ successMessageClassName,
914
+ errorMessageClassName,
915
+ background = "white",
916
+ spacing = "xl",
891
917
  pattern,
892
- patternOpacity,
918
+ patternOpacity = 0.1,
893
919
  formConfig,
894
920
  onSubmit,
895
921
  onSuccess,
896
922
  onError
897
923
  }) {
898
- const form = forms.useForm({
899
- initialValues: {
900
- first_name: "",
901
- last_name: "",
902
- email: "",
903
- phone: "",
904
- message: ""
905
- },
906
- validationSchema: {
907
- first_name: (value) => !value ? "First name is required" : void 0,
908
- last_name: (value) => !value ? "Last name is required" : void 0,
909
- email: (value) => {
910
- if (!value) return "Email is required";
911
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
912
- return "Please enter a valid email address";
913
- return void 0;
914
- },
915
- phone: (value) => !value ? "Phone is required" : void 0,
916
- message: (value) => !value ? "Message is required" : void 0
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);
917
939
  },
918
- onSubmit: async (values, helpers) => {
919
- const shouldAutoSubmit = Boolean(formConfig?.endpoint);
920
- if (!shouldAutoSubmit && !onSubmit) {
921
- return;
922
- }
923
- try {
924
- let result;
925
- if (shouldAutoSubmit) {
926
- result = await integration.submitPageSpeedForm(values, formConfig);
927
- }
928
- if (onSubmit) {
929
- await onSubmit(values);
930
- }
931
- if (shouldAutoSubmit || onSubmit) {
932
- if (formConfig?.resetOnSuccess !== false) {
933
- helpers.resetForm();
934
- }
935
- onSuccess?.(result);
936
- }
937
- } catch (error) {
938
- if (error instanceof integration.PageSpeedFormSubmissionError && error.formErrors) {
939
- helpers.setErrors(error.formErrors);
940
- }
941
- onError?.(error);
942
- throw error;
943
- }
944
- }
940
+ onError,
941
+ resetOnSuccess: formConfig?.resetOnSuccess !== false,
942
+ uploadTokens
945
943
  });
946
- const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
947
- const actionsContent = React__namespace.useMemo(() => {
944
+ const actionsContent = React.useMemo(() => {
948
945
  if (actionsSlot) return actionsSlot;
949
946
  if (actions && actions.length > 0) {
950
947
  return actions.map((action, index) => {
@@ -981,9 +978,9 @@ function ContactGuest({
981
978
  spacing,
982
979
  pattern,
983
980
  patternOpacity,
984
- className,
981
+ className: cn("py-12", className),
985
982
  containerClassName,
986
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
983
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto max-w-4xl", children: [
987
984
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mb-10 text-center", headerClassName), children: [
988
985
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
989
986
  "h2",
@@ -1010,81 +1007,43 @@ function ContactGuest({
1010
1007
  forms.Form,
1011
1008
  {
1012
1009
  form,
1013
- action: formConfig?.endpoint,
1014
- method: formMethod,
1015
- 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
+ },
1016
1028
  children: [
1017
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [
1018
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "first_name", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1019
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "first-name", children: "First Name" }),
1020
- /* @__PURE__ */ jsxRuntime.jsx(
1021
- TextInput,
1022
- {
1023
- ...field,
1024
- id: "first-name",
1025
- placeholder: "John",
1026
- error: meta.touched && !!meta.error,
1027
- "aria-label": "First Name"
1028
- }
1029
- )
1030
- ] }) }),
1031
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "last_name", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1032
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "last-name", children: "Last Name" }),
1033
- /* @__PURE__ */ jsxRuntime.jsx(
1034
- TextInput,
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
1035
  {
1036
- ...field,
1037
- id: "last-name",
1038
- placeholder: "Doe",
1039
- error: meta.touched && !!meta.error,
1040
- "aria-label": "Last Name"
1036
+ field,
1037
+ uploadProgress,
1038
+ onFileUpload: uploadFiles,
1039
+ onFileRemove: removeFile,
1040
+ isUploading
1041
1041
  }
1042
1042
  )
1043
- ] }) })
1044
- ] }),
1045
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "email", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1046
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: "Email" }),
1047
- /* @__PURE__ */ jsxRuntime.jsx(
1048
- TextInput,
1049
- {
1050
- ...field,
1051
- id: "email",
1052
- type: "email",
1053
- placeholder: "john@example.com",
1054
- error: meta.touched && !!meta.error,
1055
- "aria-label": "Email"
1056
- }
1057
- )
1058
- ] }) }),
1059
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "phone", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1060
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "phone", children: "Phone" }),
1061
- /* @__PURE__ */ jsxRuntime.jsx(
1062
- TextInput,
1063
- {
1064
- ...field,
1065
- id: "phone",
1066
- type: "tel",
1067
- placeholder: "+1 (555) 000-0000",
1068
- error: meta.touched && !!meta.error,
1069
- "aria-label": "Phone"
1070
- }
1071
- )
1072
- ] }) }),
1073
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "message", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1074
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "message", children: "Message" }),
1075
- /* @__PURE__ */ jsxRuntime.jsx(
1076
- TextArea,
1077
- {
1078
- ...field,
1079
- id: "message",
1080
- placeholder: "Your message...",
1081
- rows: 4,
1082
- error: meta.touched && !!meta.error,
1083
- "aria-label": "Message"
1084
- }
1085
- )
1086
- ] }) }),
1087
- actionsSlot || actions ? actionsContent : /* @__PURE__ */ jsxRuntime.jsxs(
1043
+ },
1044
+ field.name
1045
+ )) }),
1046
+ actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxRuntime.jsxs(
1088
1047
  Pressable,
1089
1048
  {
1090
1049
  componentType: "button",